View | Details | Raw Unified | Return to bug 111086 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java (-11 / +13 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.Map;
14
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
14
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
16
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
15
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
Lines 120-126 Link Here
120
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
119
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
121
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
120
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
122
	 */
121
	 */
123
	public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) {
122
	public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
124
		
123
		
125
		if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
124
		if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
126
		if (actualType == TypeBinding.NULL) return;
125
		if (actualType == TypeBinding.NULL) return;
Lines 144-150 Link Here
144
		// collect through enclosing type
143
		// collect through enclosing type
145
		ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType();
144
		ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType();
146
		if (formalEnclosingType != null) {
145
		if (formalEnclosingType != null) {
147
			formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), substitutes, constraint);
146
			formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), inferenceContext, constraint);
148
		}
147
		}
149
		// collect through type arguments
148
		// collect through type arguments
150
		if (this.arguments == null) return;
149
		if (this.arguments == null) return;
Lines 157-163 Link Here
157
        		formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments;
156
        		formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments;
158
        		break;
157
        		break;
159
        	case Binding.RAW_TYPE :
158
        	case Binding.RAW_TYPE :
160
        		substitutes.clear(); // clear all variables to indicate raw generic method in the end
159
        		if (!inferenceContext.checkRawSubstitution()) {
160
	           		inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference
161
        		}
161
        		return;
162
        		return;
162
        	default :
163
        	default :
163
        		return;
164
        		return;
Lines 171-189 Link Here
171
        		actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments;
172
        		actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments;
172
        		break;
173
        		break;
173
        	case Binding.RAW_TYPE :
174
        	case Binding.RAW_TYPE :
174
        		substitutes.clear(); // clear all variables to indicate raw generic method in the end
175
        		if (!inferenceContext.checkRawSubstitution()) {
175
        		if (constraint == TypeConstants.CONSTRAINT_EQUAL) {
176
	           		inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference
176
        			substitutes.put(TypeBinding.VOID, Binding.NO_TYPES); // marker for impossible inference
177
        		}
177
        		}
178
        		return;
178
        		return;
179
        	default :
179
        	default :
180
        		return;
180
        		return;
181
        }
181
        }
182
        inferenceContext.depth++;
182
        for (int i = 0, length = formalArguments.length; i < length; i++) {
183
        for (int i = 0, length = formalArguments.length; i < length; i++) {
183
        	TypeBinding formalArgument = formalArguments[i];
184
        	TypeBinding formalArgument = formalArguments[i];
184
        	TypeBinding actualArgument = actualArguments[i];
185
        	TypeBinding actualArgument = actualArguments[i];
185
        	if (formalArgument.isWildcard()) {
186
        	if (formalArgument.isWildcard()) {
186
                formalArgument.collectSubstitutes(scope, actualArgument, substitutes, constraint);
187
                formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, constraint);
187
                continue;
188
                continue;
188
        	} else if (actualArgument.isWildcard()){
189
        	} else if (actualArgument.isWildcard()){
189
    			WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument;
190
    			WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument;
Lines 191-200 Link Here
191
    				if (constraint == TypeConstants.CONSTRAINT_SUPER) { // JLS 15.12.7, p.459
192
    				if (constraint == TypeConstants.CONSTRAINT_SUPER) { // JLS 15.12.7, p.459
192
						switch(actualWildcardArgument.boundKind) {
193
						switch(actualWildcardArgument.boundKind) {
193
		    				case Wildcard.EXTENDS :
194
		    				case Wildcard.EXTENDS :
194
		    					formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, substitutes, TypeConstants.CONSTRAINT_SUPER);
195
		    					formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
195
		    					continue;
196
		    					continue;
196
		    				case Wildcard.SUPER :
197
		    				case Wildcard.SUPER :
197
		    					formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, substitutes, TypeConstants.CONSTRAINT_EXTENDS);
198
		    					formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
198
		    					continue;
199
		    					continue;
199
		    				default :
200
		    				default :
200
		    					continue; // cannot infer anything further from unbound wildcard
201
		    					continue; // cannot infer anything further from unbound wildcard
Lines 205-212 Link Here
205
    			}
206
    			}
206
        	}
207
        	}
207
        	// by default, use EQUAL constraint
208
        	// by default, use EQUAL constraint
208
            formalArgument.collectSubstitutes(scope, actualArgument, substitutes, TypeConstants.CONSTRAINT_EQUAL);
209
            formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
209
        }
210
        }
211
        inferenceContext.depth--;
210
	}
212
	}
211
	
213
	
212
	/**
214
	/**
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java (-2 / +2 lines)
Lines 17-23 Link Here
17
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
19
19
20
public class MethodBinding extends Binding implements TypeConstants {
20
public class MethodBinding extends Binding {
21
	
21
	
22
	public int modifiers;
22
	public int modifiers;
23
	public char[] selector;
23
	public char[] selector;
Lines 537-543 Link Here
537
 * Answer true if the receiver is a "public static void main(String[])" method
537
 * Answer true if the receiver is a "public static void main(String[])" method
538
 */
538
 */
539
public final boolean isMain() {
539
public final boolean isMain() {
540
	if (this.selector.length == 4 && CharOperation.equals(this.selector, MAIN)
540
	if (this.selector.length == 4 && CharOperation.equals(this.selector, TypeConstants.MAIN)
541
			&& ((this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0)
541
			&& ((this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0)
542
			&& TypeBinding.VOID == this.returnType  
542
			&& TypeBinding.VOID == this.returnType  
543
			&& this.parameters.length == 1) {
543
			&& this.parameters.length == 1) {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java (-84 / +56 lines)
Lines 10-17 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.HashMap;
14
import java.util.Map;
15
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
13
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
16
14
17
/**
15
/**
Lines 28-34 Link Here
28
    public boolean wasInferred; // only set to true for instances resulting from method invocation inferrence
26
    public boolean wasInferred; // only set to true for instances resulting from method invocation inferrence
29
    public boolean isRaw; // set to true for method behaving as raw for substitution purpose
27
    public boolean isRaw; // set to true for method behaving as raw for substitution purpose
30
    private MethodBinding tiebreakMethod;
28
    private MethodBinding tiebreakMethod;
31
    public boolean isUnchecked; // indicates whether inferred arguments used unchecked conversion during bound check or was raw
29
    public boolean isUnchecked; // transient flag set during inference (warning: bindings are shared, so flag cannot be trusted beyond)
32
	
30
	
33
	/**
31
	/**
34
	 * Perform inference of generic method type parameters and/or expected type
32
	 * Perform inference of generic method type parameters and/or expected type
Lines 54-72 Link Here
54
				
52
				
55
			// initializes the map of substitutes (var --> type[][]{ equal, extends, super}
53
			// initializes the map of substitutes (var --> type[][]{ equal, extends, super}
56
			TypeBinding[] parameters = originalMethod.parameters;
54
			TypeBinding[] parameters = originalMethod.parameters;
57
			int varLength = typeVariables.length;
55
			InferenceContext inferenceContext = new InferenceContext(originalMethod);
58
			Map collectedSubstitutes = new HashMap(varLength);
56
			methodSubstitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext);
59
			for (int i = 0; i < varLength; i++)
60
				collectedSubstitutes.put(typeVariables[i], new TypeBinding[3][]);
61
			
62
			substitutes = new TypeBinding[varLength];
63
			methodSubstitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, collectedSubstitutes, substitutes);
64
			if (methodSubstitute == null) 
57
			if (methodSubstitute == null) 
65
				return null;
58
				return null;
66
			// substitutes may hold null to denote unresolved vars, but null arguments got replaced with respective original variable in param method
59
			// substitutes may hold null to denote unresolved vars, but null arguments got replaced with respective original variable in param method
67
			
60
			
68
			// 15.12.2.8 - inferring unresolved type arguments
61
			// 15.12.2.8 - inferring unresolved type arguments
69
			if (hasUnresolvedTypeArgument(substitutes)) {
62
			if (inferenceContext.hasUnresolvedTypeArgument()) {
70
				TypeBinding expectedType = null;
63
				TypeBinding expectedType = null;
71
				if (methodSubstitute.returnType != TypeBinding.VOID) {
64
				if (methodSubstitute.returnType != TypeBinding.VOID) {
72
					// if message invocation has expected type
65
					// if message invocation has expected type
Lines 76-82 Link Here
76
					}
69
					}
77
					if (expectedType == null) expectedType = scope.getJavaLangObject(); // assume Object by default
70
					if (expectedType == null) expectedType = scope.getJavaLangObject(); // assume Object by default
78
				}
71
				}
79
				methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, collectedSubstitutes, substitutes);
72
				methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, inferenceContext);
80
				if (methodSubstitute == null) 
73
				if (methodSubstitute == null) 
81
					return null;
74
					return null;
82
			}
75
			}
Lines 103-128 Link Here
103
				}
96
				}
104
			}
97
			}
105
		}
98
		}
106
107
		return methodSubstitute;
99
		return methodSubstitute;
108
	}
100
	}
109
101
110
	/**
102
	/**
111
	 * Returns true if any unresolved variable is detected, i.e. any variable is substituted with itself
112
	 */
113
	private static boolean hasUnresolvedTypeArgument(TypeBinding[] substitutes) {
114
		for (int i = 0, varLength = substitutes.length; i <varLength; i++) {
115
			if (substitutes[i] == null) {
116
				return true;
117
			}
118
		}
119
		return false;
120
	}
121
122
	/**
123
	 * Collect argument type mapping, handling varargs
103
	 * Collect argument type mapping, handling varargs
124
	 */
104
	 */
125
	private static ParameterizedGenericMethodBinding inferFromArgumentTypes(Scope scope, MethodBinding originalMethod, TypeBinding[] arguments, TypeBinding[] parameters, Map collectedSubstitutes, TypeBinding[] substitutes) {
105
	private static ParameterizedGenericMethodBinding inferFromArgumentTypes(Scope scope, MethodBinding originalMethod, TypeBinding[] arguments, TypeBinding[] parameters, InferenceContext inferenceContext) {
126
106
127
		if (originalMethod.isVarargs()) {
107
		if (originalMethod.isVarargs()) {
128
			int paramLength = parameters.length;
108
			int paramLength = parameters.length;
Lines 130-137 Link Here
130
			int argLength = arguments.length;
110
			int argLength = arguments.length;
131
			// process mandatory arguments
111
			// process mandatory arguments
132
			for (int i = 0; i < minArgLength; i++) {
112
			for (int i = 0; i < minArgLength; i++) {
133
				parameters[i].collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
113
				parameters[i].collectSubstitutes(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
134
				if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
114
				if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
135
			}
115
			}
136
			// process optional arguments
116
			// process optional arguments
137
			if (minArgLength < argLength) {
117
			if (minArgLength < argLength) {
Lines 154-209 Link Here
154
					varargType = ((ArrayBinding)varargType).elementsType(); 
134
					varargType = ((ArrayBinding)varargType).elementsType(); 
155
				}
135
				}
156
				for (int i = minArgLength; i < argLength; i++) {
136
				for (int i = minArgLength; i < argLength; i++) {
157
					varargType.collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
137
					varargType.collectSubstitutes(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
158
					if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
138
					if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
159
				}
139
				}
160
			}
140
			}
161
		} else {
141
		} else {
162
			int paramLength = parameters.length;
142
			int paramLength = parameters.length;
163
			for (int i = 0; i < paramLength; i++) {
143
			for (int i = 0; i < paramLength; i++) {
164
				parameters[i].collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
144
				parameters[i].collectSubstitutes(scope, arguments[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
165
				if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
145
				if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
166
			}
146
			}
167
		}
147
		}
168
		TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
148
		if (inferenceContext.status == InferenceContext.RAW_SUBSTITUTION) {
169
		int varLength = originalVariables.length;
170
		substitutes = resolveSubstituteConstraints(scope, originalVariables , substitutes, false/*ignore Ti<:Uk*/, collectedSubstitutes);
171
		if (substitutes == null) 
172
			return null; // incompatible
173
		if (substitutes.length == 0) {
174
			// raw generic method inferred
149
			// raw generic method inferred
175
			return scope.environment().createParameterizedGenericMethod(originalMethod, (RawTypeBinding)null);
150
			return scope.environment().createParameterizedGenericMethod(originalMethod, (RawTypeBinding)null);
176
		}
151
		}
152
		TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
153
		if (!resolveSubstituteConstraints(scope, originalVariables , inferenceContext, false/*ignore Ti<:Uk*/)) 
154
			return null; // impossible substitution
155
177
		// apply inferred variable substitutions - replacing unresolved variable with original ones in param method
156
		// apply inferred variable substitutions - replacing unresolved variable with original ones in param method
178
		TypeBinding[] resolvedSubstitutes = substitutes;
157
		TypeBinding[] inferredSustitutes = inferenceContext.substitutes;
179
		for (int i = 0; i < varLength; i++) {
158
		TypeBinding[] actualSubstitutes = inferredSustitutes;
180
			if (substitutes[i] == null) {
159
		for (int i = 0, varLength = originalVariables.length; i < varLength; i++) {
181
				if (resolvedSubstitutes == substitutes) {
160
			if (inferredSustitutes[i] == null) {
182
					System.arraycopy(substitutes, 0, resolvedSubstitutes = new TypeBinding[varLength], 0, i); // clone to replace null with original variable in param method
161
				if (actualSubstitutes == inferredSustitutes) {
162
					System.arraycopy(inferredSustitutes, 0, actualSubstitutes = new TypeBinding[varLength], 0, i); // clone to replace null with original variable in param method
183
				}
163
				}
184
				resolvedSubstitutes[i] = originalVariables[i];
164
				actualSubstitutes[i] = originalVariables[i];
185
			} else if (resolvedSubstitutes != substitutes) {
165
			} else if (actualSubstitutes != inferredSustitutes) {
186
				resolvedSubstitutes[i] = substitutes[i];
166
				actualSubstitutes[i] = inferredSustitutes[i];
187
			}
167
			}
188
		}
168
		}
189
		return scope.environment().createParameterizedGenericMethod(originalMethod, resolvedSubstitutes);		
169
		ParameterizedGenericMethodBinding paramMethod = scope.environment().createParameterizedGenericMethod(originalMethod, actualSubstitutes);
170
		return paramMethod;
190
	}
171
	}
191
	
172
	
192
	private static TypeBinding[] resolveSubstituteConstraints(Scope scope, TypeVariableBinding[] typeVariables, TypeBinding[] substitutes, boolean considerEXTENDSConstraints, Map collectedSubstitutes) {
173
	private static boolean resolveSubstituteConstraints(Scope scope, TypeVariableBinding[] typeVariables, InferenceContext inferenceContext, boolean considerEXTENDSConstraints) {
193
		if (collectedSubstitutes.isEmpty()) {
174
		TypeBinding[] substitutes = inferenceContext.substitutes;
194
			// raw generic method inferred
195
			return Binding.NO_TYPES; // empty array
196
		}
197
		int varLength = typeVariables.length;
175
		int varLength = typeVariables.length;
198
		
199
		// check Tj=U constraints
176
		// check Tj=U constraints
200
		nextTypeParameter: 
177
		nextTypeParameter: 
201
			for (int i = 0; i < varLength; i++) {
178
			for (int i = 0; i < varLength; i++) {
202
				TypeVariableBinding current = typeVariables[i];
179
				TypeVariableBinding current = typeVariables[i];
203
				TypeBinding substitute = substitutes[i];
180
				TypeBinding substitute = substitutes[i];
204
				if (substitute != null) continue nextTypeParameter; // already inferred previously
181
				if (substitute != null) continue nextTypeParameter; // already inferred previously
205
				TypeBinding[][] variableSubstitutes = (TypeBinding[][]) collectedSubstitutes.get(current);
182
				TypeBinding [] equalSubstitutes = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EQUAL);
206
				TypeBinding [] equalSubstitutes = variableSubstitutes[CONSTRAINT_EQUAL];
207
				if (equalSubstitutes != null) {
183
				if (equalSubstitutes != null) {
208
					nextConstraint:
184
					nextConstraint:
209
						for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) {
185
						for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) {
Lines 234-266 Link Here
234
						}
210
						}
235
				}
211
				}
236
			}
212
			}
237
		if (hasUnresolvedTypeArgument(substitutes)) {
213
		if (inferenceContext.hasUnresolvedTypeArgument()) {
238
			// check Tj>:U constraints
214
			// check Tj>:U constraints
239
			nextTypeParameter: 
215
			nextTypeParameter: 
240
				for (int i = 0; i < varLength; i++) {
216
				for (int i = 0; i < varLength; i++) {
241
					TypeVariableBinding current = typeVariables[i];
217
					TypeVariableBinding current = typeVariables[i];
242
					TypeBinding substitute = substitutes[i];
218
					TypeBinding substitute = substitutes[i];
243
					if (substitute != null) continue nextTypeParameter; // already inferred previously
219
					if (substitute != null) continue nextTypeParameter; // already inferred previously
244
					TypeBinding[][] variableSubstitutes = (TypeBinding[][]) collectedSubstitutes.get(current);
220
					TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_SUPER);
245
					TypeBinding [] bounds = variableSubstitutes[CONSTRAINT_SUPER];
246
					if (bounds == null) continue nextTypeParameter;
221
					if (bounds == null) continue nextTypeParameter;
247
					TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds);
222
					TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds);
248
					if (mostSpecificSubstitute == null)
223
					if (mostSpecificSubstitute == null) {
249
						return null; // incompatible
224
						return false; // incompatible
225
					}
250
					if (mostSpecificSubstitute != TypeBinding.VOID) {
226
					if (mostSpecificSubstitute != TypeBinding.VOID) {
251
						substitutes[i] = mostSpecificSubstitute;
227
						substitutes[i] = mostSpecificSubstitute;
252
					}
228
					}
253
				}
229
				}
254
		}
230
		}
255
		if (considerEXTENDSConstraints && hasUnresolvedTypeArgument(substitutes)) {
231
		if (considerEXTENDSConstraints && inferenceContext.hasUnresolvedTypeArgument()) {
256
			// check Tj<:U constraints
232
			// check Tj<:U constraints
257
			nextTypeParameter: 
233
			nextTypeParameter: 
258
				for (int i = 0; i < varLength; i++) {
234
				for (int i = 0; i < varLength; i++) {
259
					TypeVariableBinding current = typeVariables[i];
235
					TypeVariableBinding current = typeVariables[i];
260
					TypeBinding substitute = substitutes[i];
236
					TypeBinding substitute = substitutes[i];
261
					if (substitute != null) continue nextTypeParameter; // already inferred previously
237
					if (substitute != null) continue nextTypeParameter; // already inferred previously
262
					TypeBinding[][] variableSubstitutes = (TypeBinding[][]) collectedSubstitutes.get(current);
238
					TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS);
263
					TypeBinding [] bounds = variableSubstitutes[CONSTRAINT_EXTENDS];
264
					if (bounds == null) continue nextTypeParameter;
239
					if (bounds == null) continue nextTypeParameter;
265
					TypeBinding[] glb = Scope.greaterLowerBound(bounds);
240
					TypeBinding[] glb = Scope.greaterLowerBound(bounds);
266
					TypeBinding mostSpecificSubstitute = null;
241
					TypeBinding mostSpecificSubstitute = null;
Lines 271-277 Link Here
271
						}
246
						}
272
					} 
247
					} 
273
		}
248
		}
274
		return substitutes;
249
		return true;
275
	}
250
	}
276
	
251
	
277
	/**
252
	/**
Lines 288-294 Link Here
288
		}		
263
		}		
289
	    this.isRaw = true;
264
	    this.isRaw = true;
290
	    this.tagBits = originalMethod.tagBits;
265
	    this.tagBits = originalMethod.tagBits;
291
		this.isUnchecked = false;
292
	    this.environment = environment;
266
	    this.environment = environment;
293
		this.modifiers = originalMethod.modifiers;
267
		this.modifiers = originalMethod.modifiers;
294
		this.selector = originalMethod.selector;
268
		this.selector = originalMethod.selector;
Lines 322-328 Link Here
322
	    this.typeArguments = typeArguments;
296
	    this.typeArguments = typeArguments;
323
	    this.isRaw = false;
297
	    this.isRaw = false;
324
	    this.tagBits = originalMethod.tagBits;
298
	    this.tagBits = originalMethod.tagBits;
325
		this.isUnchecked = false;
326
	    this.originalMethod = originalMethod;
299
	    this.originalMethod = originalMethod;
327
	    this.parameters = Scope.substitute(this, originalMethod.parameters);
300
	    this.parameters = Scope.substitute(this, originalMethod.parameters);
328
	    this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions);
301
	    this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions);
Lines 383-397 Link Here
383
	 * Given some type expectation, and type variable bounds, perform some inference.
356
	 * Given some type expectation, and type variable bounds, perform some inference.
384
	 * Returns true if still had unresolved type variable at the end of the operation
357
	 * Returns true if still had unresolved type variable at the end of the operation
385
	 */
358
	 */
386
	private ParameterizedGenericMethodBinding inferFromExpectedType(Scope scope, TypeBinding expectedType, Map collectedSubstitutes, TypeBinding[] substitutes) {
359
	private ParameterizedGenericMethodBinding inferFromExpectedType(Scope scope, TypeBinding expectedType, InferenceContext inferenceContext) {
387
	    TypeVariableBinding[] originalVariables = this.originalMethod.typeVariables; // immediate parent (could be a parameterized method)
360
	    TypeVariableBinding[] originalVariables = this.originalMethod.typeVariables; // immediate parent (could be a parameterized method)
388
		int varLength = originalVariables.length;
361
		int varLength = originalVariables.length;
389
		
362
		
390
		computeSubstitutes: {
363
		computeSubstitutes: {
391
		    // infer from expected return type
364
		    // infer from expected return type
392
			if (expectedType != null) {
365
			if (expectedType != null) {
393
			    this.returnType.collectSubstitutes(scope, expectedType, collectedSubstitutes, CONSTRAINT_SUPER);
366
			    this.returnType.collectSubstitutes(scope, expectedType, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
394
				if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
367
			    if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
395
			}
368
			}
396
		    // infer from bounds of type parameters
369
		    // infer from bounds of type parameters
397
			for (int i = 0; i < varLength; i++) {
370
			for (int i = 0; i < varLength; i++) {
Lines 400-430 Link Here
400
				boolean argAlreadyInferred = argument != originalVariable;
373
				boolean argAlreadyInferred = argument != originalVariable;
401
				if (originalVariable.firstBound == originalVariable.superclass) {
374
				if (originalVariable.firstBound == originalVariable.superclass) {
402
					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass);
375
					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass);
403
					argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER);
376
					argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
404
					if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
377
					if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
405
					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
378
					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
406
					// e.g. given: <E extends Object, S extends Collection<E>> S test1(S param)
379
					// e.g. given: <E extends Object, S extends Collection<E>> S test1(S param)
407
					//                   invocation: test1(new Vector<String>())    will infer: S=Vector<String>  and with code below: E=String
380
					//                   invocation: test1(new Vector<String>())    will infer: S=Vector<String>  and with code below: E=String
408
					if (argAlreadyInferred) {
381
					if (argAlreadyInferred) {
409
						substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS);
382
						substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
410
						if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
383
						if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
411
					}
384
					}
412
				}
385
				}
413
				for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) {
386
				for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) {
414
					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]);
387
					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]);
415
					argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER);
388
					argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
416
					if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
389
					if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
417
					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
390
					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
418
					if (argAlreadyInferred) {
391
					if (argAlreadyInferred) {
419
						substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS);
392
						substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
420
						if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution
393
						if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution
421
					}
394
					}
422
				}
395
				}
423
			}
396
			}
424
			substitutes = resolveSubstituteConstraints(scope, originalVariables, substitutes, true/*consider Ti<:Uk*/, collectedSubstitutes);
397
			if (inferenceContext.status == InferenceContext.RAW_SUBSTITUTION) {
425
			if (substitutes == null) 
426
				return null; // incompatible
427
			if (substitutes.length == 0) {
428
		    	// raw generic method inferred
398
		    	// raw generic method inferred
429
		    	this.isRaw = true;
399
		    	this.isRaw = true;
430
				this.isUnchecked = false;
400
				this.isUnchecked = false;
Lines 432-443 Link Here
432
		    		this.typeArguments[i] = originalVariables[i].upperBound();
402
		    		this.typeArguments[i] = originalVariables[i].upperBound();
433
		    	}
403
		    	}
434
		    	break computeSubstitutes;
404
		    	break computeSubstitutes;
435
			}
405
			}		
406
			if (!resolveSubstituteConstraints(scope, originalVariables, inferenceContext, true/*consider Ti<:Uk*/)) 
407
				return null; // incompatible
436
			// this.typeArguments = substitutes; - no op since side effects got performed during #resolveSubstituteConstraints
408
			// this.typeArguments = substitutes; - no op since side effects got performed during #resolveSubstituteConstraints
437
	    	for (int i = 0; i < varLength; i++) {
409
	    	for (int i = 0; i < varLength; i++) {
438
	    		TypeBinding substitute = substitutes[i];
410
	    		TypeBinding substitute = inferenceContext.substitutes[i];
439
	    		if (substitute != null) {
411
	    		if (substitute != null) {
440
	    			this.typeArguments[i] = substitutes[i];
412
	    			this.typeArguments[i] = inferenceContext.substitutes[i];
441
	    		} else {
413
	    		} else {
442
	    			// remaining unresolved variable are considered to be Object (or their bound actually)
414
	    			// remaining unresolved variable are considered to be Object (or their bound actually)
443
		    		this.typeArguments[i] = originalVariables[i].upperBound();
415
		    		this.typeArguments[i] = originalVariables[i].upperBound();
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java (-4 / +3 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.Map;
14
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
14
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16
import org.eclipse.jdt.internal.compiler.impl.Constant;
15
import org.eclipse.jdt.internal.compiler.impl.Constant;
Lines 45-51 Link Here
45
 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
44
 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
46
 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
45
 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
47
*/
46
*/
48
public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) {
47
public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
49
	
48
	
50
	if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
49
	if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
51
	if (actualType == TypeBinding.NULL) return;
50
	if (actualType == TypeBinding.NULL) return;
Lines 54-63 Link Here
54
		case Binding.ARRAY_TYPE :
53
		case Binding.ARRAY_TYPE :
55
	        int actualDim = actualType.dimensions();
54
	        int actualDim = actualType.dimensions();
56
	        if (actualDim == this.dimensions) {
55
	        if (actualDim == this.dimensions) {
57
			    this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), substitutes, constraint);
56
			    this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), inferenceContext, constraint);
58
	        } else if (actualDim > this.dimensions) {
57
	        } else if (actualDim > this.dimensions) {
59
	            ArrayBinding actualReducedType = this.environment.createArrayType(actualType.leafComponentType(), actualDim - this.dimensions);
58
	            ArrayBinding actualReducedType = this.environment.createArrayType(actualType.leafComponentType(), actualDim - this.dimensions);
60
	            this.leafComponentType.collectSubstitutes(scope, actualReducedType, substitutes, constraint);
59
	            this.leafComponentType.collectSubstitutes(scope, actualReducedType, inferenceContext, constraint);
61
	        }
60
	        }
62
			break;
61
			break;
63
		case Binding.TYPE_PARAMETER :
62
		case Binding.TYPE_PARAMETER :
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java (-3 / +1 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.Map;
14
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
14
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
16
15
Lines 112-119 Link Here
112
 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
111
 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
113
 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
112
 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
114
 */
113
 */
115
public void collectSubstitutes(Scope scope, TypeBinding actualType,
114
public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
116
		Map substitutes, int constraint) {
117
	// no substitute by default
115
	// no substitute by default
118
}
116
}
119
117
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java (-27 / +5 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.Map;
14
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
14
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
16
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Lines 165-171 Link Here
165
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
164
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
166
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
165
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
167
	 */
166
	 */
168
	public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) {
167
	public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
168
		
169
		//	only infer for type params of the generic method
170
		if (this.declaringElement != inferenceContext.genericMethod) return;
169
		
171
		
170
		// cannot infer anything from a null type
172
		// cannot infer anything from a null type
171
		switch (actualType.kind()) {
173
		switch (actualType.kind()) {
Lines 195-225 Link Here
195
				variableConstraint =TypeConstants.CONSTRAINT_EXTENDS;
197
				variableConstraint =TypeConstants.CONSTRAINT_EXTENDS;
196
				break;
198
				break;
197
		}
199
		}
198
	    TypeBinding[][] variableSubstitutes = (TypeBinding[][])substitutes.get(this);
200
		inferenceContext.recordSubstitute(this, actualType, variableConstraint);
199
	    if (variableSubstitutes != null) {
200
		    insertLoop: {
201
		    	TypeBinding[] constraintSubstitutes = variableSubstitutes[variableConstraint];
202
		    	int length;
203
		    	if (constraintSubstitutes == null) {
204
		    		length = 0;
205
		    		constraintSubstitutes = new TypeBinding[1];
206
		    	} else {
207
		    		length = constraintSubstitutes.length;
208
			        for (int i = 0; i < length; i++) {
209
			        	TypeBinding substitute = constraintSubstitutes[i];
210
			            if (substitute == actualType) return; // already there
211
			            if (substitute == null) {
212
			                constraintSubstitutes[i] = actualType;
213
			                break insertLoop;
214
			            }
215
			        }
216
			        // no free spot found, need to grow by one
217
			        System.arraycopy(constraintSubstitutes, 0, constraintSubstitutes = new TypeBinding[length+1], 0, length);
218
		    	}
219
		        constraintSubstitutes[length] = actualType;
220
		        variableSubstitutes[variableConstraint] = constraintSubstitutes;
221
		    }
222
	    }
223
	}
201
	}
224
	
202
	
225
	public char[] constantPoolName() { /* java/lang/Object */ 
203
	public char[] constantPoolName() { /* java/lang/Object */ 
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java (-16 / +15 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.Map;
14
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
14
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
16
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
Lines 90-96 Link Here
90
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
89
	 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
91
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
90
	 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
92
	 */
91
	 */
93
	public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) {
92
	public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
94
93
95
		if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
94
		if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
96
		if (actualType == TypeBinding.NULL) return;
95
		if (actualType == TypeBinding.NULL) return;
Lines 124-139 Link Here
124
								case Wildcard.UNBOUND: // A={?} << F={? extends U}  --> 0
123
								case Wildcard.UNBOUND: // A={?} << F={? extends U}  --> 0
125
									break;
124
									break;
126
								case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U
125
								case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U
127
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EXTENDS);
126
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
128
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
127
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
129
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EXTENDS);
128
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
130
						        	}									
129
						        	}									
131
									break;
130
									break;
132
								case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0
131
								case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0
133
									break;
132
									break;
134
							}
133
							}
135
						} else { // A=V << F={? extends U} ---> V << U
134
						} else { // A=V << F={? extends U} ---> V << U
136
							this.bound.collectSubstitutes(scope, actualType, substitutes, TypeConstants.CONSTRAINT_EXTENDS);
135
							this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
137
						}
136
						}
138
						break;
137
						break;
139
					case Wildcard.SUPER: // F={? super U}
138
					case Wildcard.SUPER: // F={? super U}
Lines 145-158 Link Here
145
								case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0
144
								case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0
146
									break;
145
									break;
147
								case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0
146
								case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0
148
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER);
147
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
149
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
148
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
150
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER);
149
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
151
						        	}									
150
						        	}									
152
									break;
151
									break;
153
							}
152
							}
154
						} else { // A=V << F={? super U} ---> V >> U
153
						} else { // A=V << F={? super U} ---> V >> U
155
							this.bound.collectSubstitutes(scope, actualType, substitutes, TypeConstants.CONSTRAINT_SUPER);							
154
							this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER);							
156
						}						
155
						}						
157
						break;
156
						break;
158
				}
157
				}
Lines 180-188 Link Here
180
								case Wildcard.UNBOUND: // A={?} == F={? extends U}  --> 0
179
								case Wildcard.UNBOUND: // A={?} == F={? extends U}  --> 0
181
									break;
180
									break;
182
								case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U
181
								case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U
183
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EQUAL);
182
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
184
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
183
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
185
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EQUAL);
184
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
186
						        	}											
185
						        	}											
187
									break;
186
									break;
188
								case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0
187
								case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0
Lines 200-208 Link Here
200
								case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0
199
								case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0
201
									break;
200
									break;
202
								case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0
201
								case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0
203
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EQUAL);
202
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
204
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
203
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
205
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EQUAL);
204
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
206
						        	}	
205
						        	}	
207
						        	break;
206
						        	break;
208
							}
207
							}
Lines 234-242 Link Here
234
								case Wildcard.UNBOUND: // A={?} >> F={? extends U}  --> 0
233
								case Wildcard.UNBOUND: // A={?} >> F={? extends U}  --> 0
235
									break;
234
									break;
236
								case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U
235
								case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U
237
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER);
236
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
238
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
237
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
239
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER);
238
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
240
						        	}										
239
						        	}										
241
									break;
240
									break;
242
								case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0
241
								case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0
Lines 254-262 Link Here
254
								case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0
253
								case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0
255
									break;
254
									break;
256
								case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U
255
								case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U
257
									this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER);
256
									this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
258
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
257
						        	for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) {
259
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER);
258
										this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER);
260
						        	}	
259
						        	}	
261
						        	break;
260
						        	break;
262
							}
261
							}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (-17 / +25 lines)
Lines 172-199 Link Here
172
	// for null reference analysis
172
	// for null reference analysis
173
	public static final int IsNonNull = Bit18;
173
	public static final int IsNonNull = Bit18;
174
	
174
	
175
	
176
	// constants used when checking invocation arguments
177
	public static final int INVOCATION_ARGUMENT_OK = 0;
178
	public static final int INVOCATION_ARGUMENT_UNCHECKED = 1;
179
	public static final int INVOCATION_ARGUMENT_WILDCARD = 2;
180
	
175
	public ASTNode() {
181
	public ASTNode() {
176
182
177
		super();
183
		super();
178
	}
184
	}
179
	private static boolean checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) {
185
	private static int checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) {
180
		argument.computeConversion(scope, parameterType, argumentType);
186
		argument.computeConversion(scope, parameterType, argumentType);
181
187
182
		if (argumentType != TypeBinding.NULL && parameterType.isWildcard()) {
188
		if (argumentType != TypeBinding.NULL && parameterType.isWildcard()) {
183
			WildcardBinding wildcard = (WildcardBinding) parameterType;
189
			WildcardBinding wildcard = (WildcardBinding) parameterType;
184
			if (wildcard.boundKind != Wildcard.SUPER && wildcard.otherBounds == null) // lub wildcards are tolerated
190
			if (wildcard.boundKind != Wildcard.SUPER && wildcard.otherBounds == null) // lub wildcards are tolerated
185
		    	return true; // unsafeWildcardInvocation
191
		    	return INVOCATION_ARGUMENT_WILDCARD;
186
		}
192
		}
187
		TypeBinding checkedParameterType = originalParameterType == null ? parameterType : originalParameterType;
193
		TypeBinding checkedParameterType = originalParameterType == null ? parameterType : originalParameterType;
188
		if (argumentType != checkedParameterType) {
194
		if (argumentType != checkedParameterType && argumentType.needsUncheckedConversion(checkedParameterType)) {
189
			if (argumentType.needsUncheckedConversion(checkedParameterType)) {
195
			scope.problemReporter().unsafeTypeConversion(argument, argumentType, checkedParameterType);
190
				scope.problemReporter().unsafeTypeConversion(argument, argumentType, checkedParameterType);
196
			return INVOCATION_ARGUMENT_UNCHECKED;
191
			}
192
		}
197
		}
193
		return false;
198
		return INVOCATION_ARGUMENT_OK;
194
	}
199
	}
195
	public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
200
	public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
196
		boolean unsafeWildcardInvocation = false;
197
		TypeBinding[] params = method.parameters;
201
		TypeBinding[] params = method.parameters;
198
		int paramLength = params.length;
202
		int paramLength = params.length;
199
		boolean isRawMemberInvocation = !method.isStatic() 
203
		boolean isRawMemberInvocation = !method.isStatic() 
Lines 210-224 Link Here
210
				}
214
				}
211
			}
215
			}
212
		}
216
		}
213
		if (arguments != null) {
217
		int invocationStatus = INVOCATION_ARGUMENT_OK;
218
		if (arguments == null) {
219
			if (method.isVarargs()) {
220
				TypeBinding parameterType = ((ArrayBinding) params[paramLength-1]).elementsType(); // no element was supplied for vararg parameter
221
		    	if (!parameterType.isReifiable()) {
222
				    scope.problemReporter().unsafeGenericArrayForVarargs(parameterType, (ASTNode)invocationSite);					
223
		    	}				
224
			}
225
		} else {
214
			if (method.isVarargs()) {
226
			if (method.isVarargs()) {
215
				// 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
227
				// 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
216
				int lastIndex = paramLength - 1;
228
				int lastIndex = paramLength - 1;
217
				for (int i = 0; i < lastIndex; i++) {
229
				for (int i = 0; i < lastIndex; i++) {
218
					TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
230
					TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
219
				    if (checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam)) {
231
					invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam);
220
					    unsafeWildcardInvocation = true;
221
				    }
222
				}
232
				}
223
			   int argLength = arguments.length;
233
			   int argLength = arguments.length;
224
			   if (lastIndex < argLength) { // vararg argument was provided
234
			   if (lastIndex < argLength) { // vararg argument was provided
Lines 233-240 Link Here
233
						originalRawParam = rawOriginalGenericMethod == null ? null : ((ArrayBinding)rawOriginalGenericMethod.parameters[lastIndex]).elementsType();
243
						originalRawParam = rawOriginalGenericMethod == null ? null : ((ArrayBinding)rawOriginalGenericMethod.parameters[lastIndex]).elementsType();
234
				    }
244
				    }
235
					for (int i = lastIndex; i < argLength; i++) {
245
					for (int i = lastIndex; i < argLength; i++) {
236
					    if (checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam))
246
						invocationStatus |= checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam);
237
						    unsafeWildcardInvocation = true;
238
					}
247
					}
239
				}
248
				}
240
	
249
	
Lines 262-276 Link Here
262
			} else {
271
			} else {
263
				for (int i = 0; i < paramLength; i++) {
272
				for (int i = 0; i < paramLength; i++) {
264
					TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
273
					TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
265
				    if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i], originalRawParam))
274
					invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i], originalRawParam);
266
					    unsafeWildcardInvocation = true;
267
				}
275
				}
268
			}
276
			}
269
			if (argsContainCast) {
277
			if (argsContainCast) {
270
				CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
278
				CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
271
			}
279
			}
272
		}
280
		}
273
		if (unsafeWildcardInvocation) {
281
		if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) {
274
		    scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes);
282
		    scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes);
275
		} else if (!method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) {
283
		} else if (!method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) {
276
		    scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method);
284
		    scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method);
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java (+142 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.lookup;
12
13
/**
14
 * Context used during type inference for a generic method invocation
15
 */
16
public class InferenceContext {
17
	
18
	private TypeBinding[][][] collectedSubstitutes;
19
	MethodBinding genericMethod;
20
	int depth;
21
	int status;
22
	TypeBinding[] substitutes;
23
	final static int FAILED = 1;
24
	final static int RAW_SUBSTITUTION = 2;
25
	
26
public InferenceContext(MethodBinding genericMethod) {
27
	this.genericMethod = genericMethod;
28
	TypeVariableBinding[] typeVariables = genericMethod.typeVariables;
29
	int varLength = typeVariables.length;
30
	this.collectedSubstitutes = new TypeBinding[varLength][3][];
31
	this.substitutes = new TypeBinding[varLength];
32
}
33
34
public boolean checkRawSubstitution() {
35
	// only at first level, during inference from arguments
36
	if (depth > 0) return false;
37
//	if (this.argumentIndex < 0 || this.depth != 0) {
38
//		return false;
39
//	}
40
	this.status = RAW_SUBSTITUTION;
41
	return true;
42
}		
43
44
public TypeBinding[] getSubstitutes(TypeVariableBinding typeVariable, int constraint) {
45
	return this.collectedSubstitutes[typeVariable.rank][constraint];
46
}
47
48
/**
49
 * Returns true if any unresolved variable is detected, i.e. any variable is substituted with itself
50
 */
51
public boolean hasUnresolvedTypeArgument() {
52
	for (int i = 0, varLength = this.substitutes.length; i <varLength; i++) {
53
		if (this.substitutes[i] == null) {
54
			return true;
55
		}
56
	}
57
	return false;
58
}		
59
60
public void recordSubstitute(TypeVariableBinding typeVariable, TypeBinding actualType, int constraint) {
61
    TypeBinding[][] variableSubstitutes = this.collectedSubstitutes[typeVariable.rank];
62
    insertLoop: {
63
    	TypeBinding[] constraintSubstitutes = variableSubstitutes[constraint];
64
    	int length;
65
    	if (constraintSubstitutes == null) {
66
    		length = 0;
67
    		constraintSubstitutes = new TypeBinding[1];
68
    	} else {
69
    		length = constraintSubstitutes.length;
70
	        for (int i = 0; i < length; i++) {
71
	        	TypeBinding substitute = constraintSubstitutes[i];
72
	            if (substitute == actualType) return; // already there
73
	            if (substitute == null) {
74
	                constraintSubstitutes[i] = actualType;
75
	                break insertLoop;
76
	            }
77
	        }
78
	        // no free spot found, need to grow by one
79
	        System.arraycopy(constraintSubstitutes, 0, constraintSubstitutes = new TypeBinding[length+1], 0, length);
80
    	}
81
        constraintSubstitutes[length] = actualType;
82
        variableSubstitutes[constraint] = constraintSubstitutes;
83
    }
84
}
85
public String toString() {
86
	StringBuffer buffer = new StringBuffer(20);
87
	buffer.append("InferenceContex for ");//$NON-NLS-1$
88
	for (int i = 0, length = this.genericMethod.typeVariables.length; i < length; i++) {
89
		buffer.append(this.genericMethod.typeVariables[i]);
90
	}
91
	buffer.append(this.genericMethod); 
92
	buffer.append("\n\t[status=");//$NON-NLS-1$
93
	switch(this.status) {
94
		case 0 :
95
			buffer.append("ok]");//$NON-NLS-1$
96
			break;
97
		case FAILED :
98
			buffer.append("failed]");//$NON-NLS-1$
99
			break;
100
		case RAW_SUBSTITUTION :
101
			buffer.append("raw-subst]");//$NON-NLS-1$
102
			break;
103
	}
104
	buffer.append("[depth=").append(this.depth).append(']'); //$NON-NLS-1$
105
	buffer.append("\n\t[collected={");//$NON-NLS-1$
106
	for (int i = 0, length = this.collectedSubstitutes == null ? 0 : this.collectedSubstitutes.length; i < length; i++) {
107
		TypeBinding[][] collected = this.collectedSubstitutes[i];
108
		for (int j = TypeConstants.CONSTRAINT_EQUAL; j < TypeConstants.CONSTRAINT_SUPER; j++) {
109
			TypeBinding[] constraintCollected = collected[j];
110
			if (constraintCollected != null) {
111
				for (int k = 0, clength = constraintCollected.length; k < clength; k++) {
112
					buffer.append("\n\t\t").append(this.genericMethod.typeVariables[i].sourceName); //$NON-NLS-1$
113
					switch (j) {
114
						case TypeConstants.CONSTRAINT_EQUAL :
115
							buffer.append("="); //$NON-NLS-1$
116
							break;
117
						case TypeConstants.CONSTRAINT_EXTENDS :
118
							buffer.append("<:"); //$NON-NLS-1$
119
							break;
120
						case TypeConstants.CONSTRAINT_SUPER :
121
							buffer.append(">:"); //$NON-NLS-1$
122
							break;
123
					}
124
					buffer.append(constraintCollected[k]);
125
				}
126
			}
127
		}
128
	}
129
	buffer.append("}]");//$NON-NLS-1$
130
	buffer.append("\n\t[inferred=");//$NON-NLS-1$
131
	int count = 0;
132
	for (int i = 0, length = this.substitutes == null ? 0 : this.substitutes.length; i < length; i++) {
133
		if (this.substitutes[i] == null) continue;
134
		count++;
135
		buffer.append('{').append(this.genericMethod.typeVariables[i].sourceName);
136
		buffer.append("=").append(this.substitutes[i]).append('}'); //$NON-NLS-1$
137
	}
138
	if (count == 0) buffer.append("{}"); //$NON-NLS-1$
139
	buffer.append(']');
140
	return buffer.toString();
141
}
142
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java (-6 / +513 lines)
Lines 11903-11909 Link Here
11903
	}		
11903
	}		
11904
	
11904
	
11905
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=78467 
11905
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=78467 
11906
	public void _test0412() {
11906
	public void testONLY_0412() {
11907
		this.runNegativeTest(
11907
		this.runNegativeTest(
11908
			new String[] {
11908
			new String[] {
11909
				"X.java",
11909
				"X.java",
Lines 11924-11930 Link Here
11924
				"   Zork z;\n" +
11924
				"   Zork z;\n" +
11925
				"}",
11925
				"}",
11926
			},
11926
			},
11927
			"should warn about unchecked array conversion for T[]");	
11927
			"----------\n" + 
11928
			"1. ERROR in X.java (at line 15)\n" + 
11929
			"	Zork z;\n" + 
11930
			"	^^^^\n" + 
11931
			"Zork cannot be resolved to a type\n" + 
11932
			"----------\n");	
11933
	}
11934
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=78467 - variation
11935
	public void testONLY_0412a() {
11936
		this.runNegativeTest(
11937
			new String[] {
11938
				"X.java",
11939
				"import java.util.*;\n" +
11940
				"public class X {\n" + 
11941
				"\n" + 
11942
				"    public static <T> T first(T... args) {\n" + 
11943
				"        return args[0];\n" + 
11944
				"    }\n" + 
11945
				"    \n" + 
11946
				"    public static void main(String[] args) {\n" + 
11947
				"    	if (false) { \n" + 
11948
				"    		List<String> ls = first(); \n" + 
11949
				"    		int i; \n" + 
11950
				"    		i++; \n" + 
11951
				"    	}\n" + 
11952
				"        System.out.println(first(\"SUCCESS\", \"List\"));\n" + 
11953
				"    }\n" + 
11954
				"   Zork z;\n" +
11955
				"}",
11956
			},
11957
			"----------\n" + 
11958
			"1. WARNING in X.java (at line 10)\n" + 
11959
			"	List<String> ls = first(); \n" + 
11960
			"	                  ^^^^^^^\n" + 
11961
			"Type safety : A generic array of List<String> is created for a varargs parameter\n" + 
11962
			"----------\n" + 
11963
			"2. ERROR in X.java (at line 16)\n" + 
11964
			"	Zork z;\n" + 
11965
			"	^^^^\n" + 
11966
			"Zork cannot be resolved to a type\n" + 
11967
			"----------\n");	
11928
	}
11968
	}
11929
	
11969
	
11930
	public void test0413() {
11970
	public void test0413() {
Lines 31782-31799 Link Here
31782
			"public class GenericsProblem {\n" + 
31822
			"public class GenericsProblem {\n" + 
31783
			"	public <T> void test(T val) {\n" + 
31823
			"	public <T> void test(T val) {\n" + 
31784
			"		GenericsProblem gp = new GenericsProblem();\n" + 
31824
			"		GenericsProblem gp = new GenericsProblem();\n" + 
31785
			"		// this is fine with both\n" + 
31786
			"		Class<? extends GenericsProblem> cl2 = gp.getClass();\n" + 
31825
			"		Class<? extends GenericsProblem> cl2 = gp.getClass();\n" + 
31787
			"		// This fails on Sun\'s compiler\n" + 
31788
			"		Class<? extends T> cl = val.getClass();\n" + 
31826
			"		Class<? extends T> cl = val.getClass();\n" + 
31789
			"	}\n" + 
31827
			"	}\n" + 
31790
			"}\n",
31828
			"}\n",
31791
		},
31829
		},
31792
		"----------\n" + 
31830
		"----------\n" + 
31793
		"1. ERROR in GenericsProblem.java (at line 7)\n" + 
31831
		"1. ERROR in GenericsProblem.java (at line 5)\n" + 
31794
		"	Class<? extends T> cl = val.getClass();\n" + 
31832
		"	Class<? extends T> cl = val.getClass();\n" + 
31795
		"	                        ^^^^^^^^^^^^^^\n" + 
31833
		"	                        ^^^^^^^^^^^^^^\n" + 
31796
		"Type mismatch: cannot convert from Class<capture-of ? extends Object> to Class<? extends T>\n" + 
31834
		"Type mismatch: cannot convert from Class<capture-of ? extends Object> to Class<? extends T>\n" + 
31797
		"----------\n");
31835
		"----------\n");
31798
}		
31836
}
31837
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061
31838
public void test1008() {
31839
	this.runNegativeTest(
31840
		new String[] {
31841
			"X.java",
31842
			"public class X {\n" + 
31843
			"	void foo(L l, C<? extends X> c) {\n" + 
31844
			"		X x = bar(l, c);\n" + 
31845
			"	}\n" + 
31846
			"	<T> T bar(L<T> l, C<? extends T> c) { \n" + 
31847
			"		return null;\n" + 
31848
			"	}	\n" + 
31849
			"}\n" + 
31850
			"class C<E> {}\n" + 
31851
			"class L<E> {}\n" + 
31852
			"\n" + 
31853
			"\n", // =================
31854
		},
31855
		"----------\n" + 
31856
		"1. WARNING in X.java (at line 2)\r\n" + 
31857
		"	void foo(L l, C<? extends X> c) {\r\n" + 
31858
		"	         ^\n" + 
31859
		"L is a raw type. References to generic type L<E> should be parameterized\n" + 
31860
		"----------\n" + 
31861
		"2. WARNING in X.java (at line 3)\r\n" + 
31862
		"	X x = bar(l, c);\r\n" + 
31863
		"	      ^^^^^^^^^\n" + 
31864
		"Type safety: Unchecked invocation bar(L, C) of the generic method bar(L<T>, C<? extends T>) of type X\n" + 
31865
		"----------\n" + 
31866
		"3. ERROR in X.java (at line 3)\r\n" + 
31867
		"	X x = bar(l, c);\r\n" + 
31868
		"	      ^^^^^^^^^\n" + 
31869
		"Type mismatch: cannot convert from Object to X\n" + 
31870
		"----------\n" + 
31871
		"4. WARNING in X.java (at line 3)\r\n" + 
31872
		"	X x = bar(l, c);\r\n" + 
31873
		"	          ^\n" + 
31874
		"Type safety: The expression of type L needs unchecked conversion to conform to L<T>\n" + 
31875
		"----------\n");
31876
}
31877
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
31878
public void test1009() {
31879
	this.runNegativeTest(
31880
		new String[] {
31881
			"X.java",
31882
			"import java.util.Map;\n" + 
31883
			"public class X {\n" + 
31884
			"\n" + 
31885
			"	void foo(Map<String,Map> map) {\n" + 
31886
			"		bar(map);\n" + 
31887
			"	}\n" + 
31888
			"	<U,V> void bar(Map<U,Map<U,V>> map) {\n" + 
31889
			"	}\n" + 
31890
			"}\n", // =================
31891
		},
31892
		"----------\n" + 
31893
		"1. WARNING in X.java (at line 4)\n" + 
31894
		"	void foo(Map<String,Map> map) {\n" + 
31895
		"	                    ^^^\n" + 
31896
		"Map is a raw type. References to generic type Map<K,V> should be parameterized\n" + 
31897
		"----------\n" + 
31898
		"2. ERROR in X.java (at line 5)\n" + 
31899
		"	bar(map);\n" + 
31900
		"	^^^\n" + 
31901
		"The method bar(Map<U,Map<U,V>>) in the type X is not applicable for the arguments (Map<String,Map>)\n" + 
31902
		"----------\n");
31903
}	
31904
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
31905
public void test1010() {
31906
	this.runNegativeTest(
31907
		new String[] {
31908
			"X.java",
31909
			"import java.util.Map;\n" + 
31910
			"public class X {\n" + 
31911
			"\n" + 
31912
			"	void foo(Map<String,Map> map) {\n" + 
31913
			"		bar(map);\n" + 
31914
			"	}\n" + 
31915
			"	<U,V> void bar(Map<U,? extends Map<U,V>> map) {\n" + 
31916
			"	}\n" + 
31917
			"}\n", // =================
31918
		},
31919
		"----------\n" + 
31920
		"1. WARNING in X.java (at line 4)\n" + 
31921
		"	void foo(Map<String,Map> map) {\n" + 
31922
		"	                    ^^^\n" + 
31923
		"Map is a raw type. References to generic type Map<K,V> should be parameterized\n" + 
31924
		"----------\n" + 
31925
		"2. ERROR in X.java (at line 5)\n" + 
31926
		"	bar(map);\n" + 
31927
		"	^^^\n" + 
31928
		"The method bar(Map<U,? extends Map<U,V>>) in the type X is not applicable for the arguments (Map<String,Map>)\n" + 
31929
		"----------\n");
31930
}
31931
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
31932
public void test1011() {
31933
	this.runNegativeTest(
31934
		new String[] {
31935
			"X.java",
31936
			"import java.util.*;\n" + 
31937
			"public class X {\n" + 
31938
			"	void foo(HashMap map, String s, Map<String,String> map2) {\n" + 
31939
			"		bar(map, s, map2); //1\n" + 
31940
			"		bar(map2, s, map2); //2\n" + 
31941
			"		bar2(map, s, map2); //3\n" + 
31942
			"		bar3(map, s, map2); //4\n" + 
31943
			"	}\n" + 
31944
			"	<U> void bar(Map<U,U> map, U u, Map<U,U> map2) {}\n" + 
31945
			"	void bar2(Map<String,String> map, String s, Map<String,String> map2) {}\n" + 
31946
			"	<U> void bar3(Map<String,String> map, U s, Map<U,U> map2) {}\n" + 
31947
			"}\n", // =================
31948
		},
31949
		"----------\n" + 
31950
		"1. WARNING in X.java (at line 3)\n" + 
31951
		"	void foo(HashMap map, String s, Map<String,String> map2) {\n" + 
31952
		"	         ^^^^^^^\n" + 
31953
		"HashMap is a raw type. References to generic type HashMap<K,V> should be parameterized\n" + 
31954
		"----------\n" + 
31955
		"2. WARNING in X.java (at line 4)\n" + 
31956
		"	bar(map, s, map2); //1\n" + 
31957
		"	^^^^^^^^^^^^^^^^^\n" + 
31958
		"Type safety: Unchecked invocation bar(Map, Object, Map) of the generic method bar(Map<U,U>, U, Map<U,U>) of type X\n" + 
31959
		"----------\n" + 
31960
		"3. WARNING in X.java (at line 4)\n" + 
31961
		"	bar(map, s, map2); //1\n" + 
31962
		"	    ^^^\n" + 
31963
		"Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<U,U>\n" + 
31964
		"----------\n" + 
31965
		"4. WARNING in X.java (at line 6)\n" + 
31966
		"	bar2(map, s, map2); //3\n" + 
31967
		"	     ^^^\n" + 
31968
		"Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<String,String>\n" + 
31969
		"----------\n" + 
31970
		"5. WARNING in X.java (at line 7)\n" + 
31971
		"	bar3(map, s, map2); //4\n" + 
31972
		"	     ^^^\n" + 
31973
		"Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<String,String>\n" + 
31974
		"----------\n");
31975
}
31976
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
31977
public void test1012() {
31978
	this.runNegativeTest(
31979
		new String[] {
31980
			"X.java",
31981
			"public class X {\n" + 
31982
			"	void foo(L l, C<X> c) {\n" + 
31983
			"		X x = bar1(l, c);\n" + 
31984
			"		L<X> lx = bar2(l, c);\n" + 
31985
			"		C<X> cx = bar3(l, c);\n" + 
31986
			"	}\n" + 
31987
			"	<T> T bar1(L<T> l, C<T> c) {\n" + 
31988
			"		return null;\n" + 
31989
			"	}\n" + 
31990
			"	<T> L<T> bar2(L<T> l, C<T> c) {\n" + 
31991
			"		return null;\n" + 
31992
			"	}\n" + 
31993
			"	<T> C<T> bar3(L<T> l, C<T> c) {\n" + 
31994
			"		return null;\n" + 
31995
			"	}\n" + 
31996
			"}\n" + 
31997
			"\n" + 
31998
			"class C<E> {}\n" + 
31999
			"class L<E> {}\n", // =================
32000
		},
32001
		"----------\n" + 
32002
		"1. WARNING in X.java (at line 2)\r\n" + 
32003
		"	void foo(L l, C<X> c) {\r\n" + 
32004
		"	         ^\n" + 
32005
		"L is a raw type. References to generic type L<E> should be parameterized\n" + 
32006
		"----------\n" + 
32007
		"2. WARNING in X.java (at line 3)\r\n" + 
32008
		"	X x = bar1(l, c);\r\n" + 
32009
		"	      ^^^^^^^^^^\n" + 
32010
		"Type safety: Unchecked invocation bar1(L, C) of the generic method bar1(L<T>, C<T>) of type X\n" + 
32011
		"----------\n" + 
32012
		"3. ERROR in X.java (at line 3)\r\n" + 
32013
		"	X x = bar1(l, c);\r\n" + 
32014
		"	      ^^^^^^^^^^\n" + 
32015
		"Type mismatch: cannot convert from Object to X\n" + 
32016
		"----------\n" + 
32017
		"4. WARNING in X.java (at line 3)\r\n" + 
32018
		"	X x = bar1(l, c);\r\n" + 
32019
		"	           ^\n" + 
32020
		"Type safety: The expression of type L needs unchecked conversion to conform to L<T>\n" + 
32021
		"----------\n" + 
32022
		"5. WARNING in X.java (at line 4)\r\n" + 
32023
		"	L<X> lx = bar2(l, c);\r\n" + 
32024
		"	          ^^^^^^^^^^\n" + 
32025
		"Type safety: Unchecked invocation bar2(L, C) of the generic method bar2(L<T>, C<T>) of type X\n" + 
32026
		"----------\n" + 
32027
		"6. WARNING in X.java (at line 4)\r\n" + 
32028
		"	L<X> lx = bar2(l, c);\r\n" + 
32029
		"	          ^^^^^^^^^^\n" + 
32030
		"Type safety: The expression of type L needs unchecked conversion to conform to L<X>\n" + 
32031
		"----------\n" + 
32032
		"7. WARNING in X.java (at line 4)\r\n" + 
32033
		"	L<X> lx = bar2(l, c);\r\n" + 
32034
		"	               ^\n" + 
32035
		"Type safety: The expression of type L needs unchecked conversion to conform to L<T>\n" + 
32036
		"----------\n" + 
32037
		"8. WARNING in X.java (at line 5)\r\n" + 
32038
		"	C<X> cx = bar3(l, c);\r\n" + 
32039
		"	          ^^^^^^^^^^\n" + 
32040
		"Type safety: Unchecked invocation bar3(L, C) of the generic method bar3(L<T>, C<T>) of type X\n" + 
32041
		"----------\n" + 
32042
		"9. WARNING in X.java (at line 5)\r\n" + 
32043
		"	C<X> cx = bar3(l, c);\r\n" + 
32044
		"	          ^^^^^^^^^^\n" + 
32045
		"Type safety: The expression of type C needs unchecked conversion to conform to C<X>\n" + 
32046
		"----------\n" + 
32047
		"10. WARNING in X.java (at line 5)\r\n" + 
32048
		"	C<X> cx = bar3(l, c);\r\n" + 
32049
		"	               ^\n" + 
32050
		"Type safety: The expression of type L needs unchecked conversion to conform to L<T>\n" + 
32051
		"----------\n");
32052
}
32053
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32054
public void test1013() {
32055
	this.runNegativeTest(
32056
		new String[] {
32057
			"X.java",
32058
			"import java.util.*;\n" + 
32059
			"\n" + 
32060
			"public class X {\n" + 
32061
			"	public static void main(String[] args) {\n" + 
32062
			"		List<String> ls = new ArrayList<String>();\n" + 
32063
			"		ls.add(\"foo\");\n" + 
32064
			"		List<X> lx = new ArrayList<X>();\n" + 
32065
			"		lx.add(new X());\n" + 
32066
			"		new X().foo(ls, lx);\n" + 
32067
			"	}\n" + 
32068
			"	void done() {\n" + 
32069
			"		System.out.println(\"[done]\");\n" + 
32070
			"	}\n" + 
32071
			"	void foo(List l1, List<X> l2) {\n" + 
32072
			"		X x = bar1(l1, l2);\n" + 
32073
			"		x.done();\n" + 
32074
			"		List<X> lx = bar2(l1, l2);\n" + 
32075
			"		lx.get(0).done();\n" + 
32076
			"	}\n" + 
32077
			"	<T> T bar1(List<T> l1, List<T> l2) {\n" + 
32078
			"		return l1.get(0);\n" + 
32079
			"	}\n" + 
32080
			"	<T> List<T> bar2(List<T> l1, List<T> l2) {\n" + 
32081
			"		return l1;\n" + 
32082
			"	}\n" + 
32083
			"}\n", // =================
32084
		},
32085
		"----------\n" + 
32086
		"1. WARNING in X.java (at line 14)\r\n" + 
32087
		"	void foo(List l1, List<X> l2) {\r\n" + 
32088
		"	         ^^^^\n" + 
32089
		"List is a raw type. References to generic type List<E> should be parameterized\n" + 
32090
		"----------\n" + 
32091
		"2. WARNING in X.java (at line 15)\r\n" + 
32092
		"	X x = bar1(l1, l2);\r\n" + 
32093
		"	      ^^^^^^^^^^^^\n" + 
32094
		"Type safety: Unchecked invocation bar1(List, List) of the generic method bar1(List<T>, List<T>) of type X\n" + 
32095
		"----------\n" + 
32096
		"3. ERROR in X.java (at line 15)\r\n" + 
32097
		"	X x = bar1(l1, l2);\r\n" + 
32098
		"	      ^^^^^^^^^^^^\n" + 
32099
		"Type mismatch: cannot convert from Object to X\n" + 
32100
		"----------\n" + 
32101
		"4. WARNING in X.java (at line 15)\r\n" + 
32102
		"	X x = bar1(l1, l2);\r\n" + 
32103
		"	           ^^\n" + 
32104
		"Type safety: The expression of type List needs unchecked conversion to conform to List<T>\n" + 
32105
		"----------\n" + 
32106
		"5. WARNING in X.java (at line 17)\r\n" + 
32107
		"	List<X> lx = bar2(l1, l2);\r\n" + 
32108
		"	             ^^^^^^^^^^^^\n" + 
32109
		"Type safety: Unchecked invocation bar2(List, List) of the generic method bar2(List<T>, List<T>) of type X\n" + 
32110
		"----------\n" + 
32111
		"6. WARNING in X.java (at line 17)\r\n" + 
32112
		"	List<X> lx = bar2(l1, l2);\r\n" + 
32113
		"	             ^^^^^^^^^^^^\n" + 
32114
		"Type safety: The expression of type List needs unchecked conversion to conform to List<X>\n" + 
32115
		"----------\n" + 
32116
		"7. WARNING in X.java (at line 17)\r\n" + 
32117
		"	List<X> lx = bar2(l1, l2);\r\n" + 
32118
		"	                  ^^\n" + 
32119
		"Type safety: The expression of type List needs unchecked conversion to conform to List<T>\n" + 
32120
		"----------\n");
32121
}
32122
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32123
public void test1014() {
32124
	this.runNegativeTest(
32125
		new String[] {
32126
			"X.java",
32127
			"import java.util.*;\n" + 
32128
			"\n" + 
32129
			"public class X {\n" + 
32130
			"	void foo1(List l, List<String> ls) {\n" + 
32131
			"		Set<Map.Entry<String,String>> mss1 = bar(l, ls).entrySet();\n" + 
32132
			"		String s = bar(l, ls).entrySet();\n" + 
32133
			"	}\n" + 
32134
			"	<U,V> Map<U,V> bar(List<U> lu, List<V> lv) { return null; }\n" + 
32135
			"}\n", // =================
32136
		},
32137
		"----------\n" + 
32138
		"1. WARNING in X.java (at line 4)\n" + 
32139
		"	void foo1(List l, List<String> ls) {\n" + 
32140
		"	          ^^^^\n" + 
32141
		"List is a raw type. References to generic type List<E> should be parameterized\n" + 
32142
		"----------\n" + 
32143
		"2. WARNING in X.java (at line 5)\n" + 
32144
		"	Set<Map.Entry<String,String>> mss1 = bar(l, ls).entrySet();\n" + 
32145
		"	                                     ^^^^^^^^^^\n" + 
32146
		"Type safety: Unchecked invocation bar(List, List) of the generic method bar(List<U>, List<V>) of type X\n" + 
32147
		"----------\n" + 
32148
		"3. WARNING in X.java (at line 5)\n" + 
32149
		"	Set<Map.Entry<String,String>> mss1 = bar(l, ls).entrySet();\n" + 
32150
		"	                                     ^^^^^^^^^^^^^^^^^^^^^\n" + 
32151
		"Type safety: The expression of type Set needs unchecked conversion to conform to Set<Map.Entry<String,String>>\n" + 
32152
		"----------\n" + 
32153
		"4. WARNING in X.java (at line 5)\n" + 
32154
		"	Set<Map.Entry<String,String>> mss1 = bar(l, ls).entrySet();\n" + 
32155
		"	                                         ^\n" + 
32156
		"Type safety: The expression of type List needs unchecked conversion to conform to List<U>\n" + 
32157
		"----------\n" + 
32158
		"5. WARNING in X.java (at line 6)\n" + 
32159
		"	String s = bar(l, ls).entrySet();\n" + 
32160
		"	           ^^^^^^^^^^\n" + 
32161
		"Type safety: Unchecked invocation bar(List, List) of the generic method bar(List<U>, List<V>) of type X\n" + 
32162
		"----------\n" + 
32163
		"6. ERROR in X.java (at line 6)\n" + 
32164
		"	String s = bar(l, ls).entrySet();\n" + 
32165
		"	           ^^^^^^^^^^^^^^^^^^^^^\n" + 
32166
		"Type mismatch: cannot convert from Set to String\n" + 
32167
		"----------\n" + 
32168
		"7. WARNING in X.java (at line 6)\n" + 
32169
		"	String s = bar(l, ls).entrySet();\n" + 
32170
		"	               ^\n" + 
32171
		"Type safety: The expression of type List needs unchecked conversion to conform to List<U>\n" + 
32172
		"----------\n");
32173
}
32174
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32175
public void test1015() {
32176
	this.runNegativeTest(
32177
		new String[] {
32178
			"X.java",
32179
			"import java.util.*;\n" + 
32180
			"public class X {\n" + 
32181
			"	void foo1(List l, List<String> ls) {\n" + 
32182
			"		List<String> ls1 = bar(l, ls);\n" + 
32183
			"		String s = bar(l, ls);\n" + 
32184
			"	}\n" + 
32185
			"	<U,V> List<V> bar(List<U> lu, List<V> lv) { return null; }\n" + 
32186
			"}\n", // =================
32187
		},
32188
		"----------\n" + 
32189
		"1. WARNING in X.java (at line 3)\n" + 
32190
		"	void foo1(List l, List<String> ls) {\n" + 
32191
		"	          ^^^^\n" + 
32192
		"List is a raw type. References to generic type List<E> should be parameterized\n" + 
32193
		"----------\n" + 
32194
		"2. WARNING in X.java (at line 4)\n" + 
32195
		"	List<String> ls1 = bar(l, ls);\n" + 
32196
		"	                   ^^^^^^^^^^\n" + 
32197
		"Type safety: Unchecked invocation bar(List, List) of the generic method bar(List<U>, List<V>) of type X\n" + 
32198
		"----------\n" + 
32199
		"3. WARNING in X.java (at line 4)\n" + 
32200
		"	List<String> ls1 = bar(l, ls);\n" + 
32201
		"	                   ^^^^^^^^^^\n" + 
32202
		"Type safety: The expression of type List needs unchecked conversion to conform to List<String>\n" + 
32203
		"----------\n" + 
32204
		"4. WARNING in X.java (at line 4)\n" + 
32205
		"	List<String> ls1 = bar(l, ls);\n" + 
32206
		"	                       ^\n" + 
32207
		"Type safety: The expression of type List needs unchecked conversion to conform to List<U>\n" + 
32208
		"----------\n" + 
32209
		"5. WARNING in X.java (at line 5)\n" + 
32210
		"	String s = bar(l, ls);\n" + 
32211
		"	           ^^^^^^^^^^\n" + 
32212
		"Type safety: Unchecked invocation bar(List, List) of the generic method bar(List<U>, List<V>) of type X\n" + 
32213
		"----------\n" + 
32214
		"6. ERROR in X.java (at line 5)\n" + 
32215
		"	String s = bar(l, ls);\n" + 
32216
		"	           ^^^^^^^^^^\n" + 
32217
		"Type mismatch: cannot convert from List to String\n" + 
32218
		"----------\n" + 
32219
		"7. WARNING in X.java (at line 5)\n" + 
32220
		"	String s = bar(l, ls);\n" + 
32221
		"	               ^\n" + 
32222
		"Type safety: The expression of type List needs unchecked conversion to conform to List<U>\n" + 
32223
		"----------\n");
32224
}
32225
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32226
public void test1016() {
32227
	this.runNegativeTest(
32228
		new String[] {
32229
			"X.java",
32230
			"import java.util.*;\n" + 
32231
			"public class X {\n" + 
32232
			"	void foo1() {\n" + 
32233
			"		List ls1 = bar(null);\n" + 
32234
			"		List<String> ls2 = bar(null);\n" + 
32235
			"		String s = bar(null);\n" + 
32236
			"	}\n" + 
32237
			"	<U> List<U> bar(List<U> lu) { return null; }\n" + 
32238
			"}\n", // =================
32239
		},
32240
		"----------\n" + 
32241
		"1. WARNING in X.java (at line 4)\n" + 
32242
		"	List ls1 = bar(null);\n" + 
32243
		"	^^^^\n" + 
32244
		"List is a raw type. References to generic type List<E> should be parameterized\n" + 
32245
		"----------\n" + 
32246
		"2. ERROR in X.java (at line 6)\n" + 
32247
		"	String s = bar(null);\n" + 
32248
		"	           ^^^^^^^^^\n" + 
32249
		"Type mismatch: cannot convert from List<Object> to String\n" + 
32250
		"----------\n");
32251
}
32252
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32253
public void test1017() {
32254
	this.runNegativeTest(
32255
		new String[] {
32256
			"SortedList.java",
32257
			"import java.util.*;\n" + 
32258
			"\n" + 
32259
			"public class SortedList<E extends Comparable> extends LinkedList<E>\n" + 
32260
			"{\n" + 
32261
			"    public boolean add(E e){\n" + 
32262
			"      int index = Collections.binarySearch(this,e);\n" + 
32263
			"      if (index<0)\n" + 
32264
			"      super.add(-index-1,e);\n" + 
32265
			"      return true;\n" + 
32266
			"  }\n" + 
32267
			"}", // =================
32268
		},
32269
		"----------\n" + 
32270
		"1. WARNING in SortedList.java (at line 3)\n" + 
32271
		"	public class SortedList<E extends Comparable> extends LinkedList<E>\n" + 
32272
		"	             ^^^^^^^^^^\n" + 
32273
		"The serializable class SortedList does not declare a static final serialVersionUID field of type long\n" + 
32274
		"----------\n" + 
32275
		"2. WARNING in SortedList.java (at line 3)\n" + 
32276
		"	public class SortedList<E extends Comparable> extends LinkedList<E>\n" + 
32277
		"	                                  ^^^^^^^^^^\n" + 
32278
		"Comparable is a raw type. References to generic type Comparable<T> should be parameterized\n" + 
32279
		"----------\n" + 
32280
		"3. WARNING in SortedList.java (at line 5)\n" + 
32281
		"	public boolean add(E e){\n" + 
32282
		"	               ^^^^^^^^\n" + 
32283
		"The method add(E) of type SortedList<E> should be tagged with @Override since it actually overrides a superclass method\n" + 
32284
		"----------\n" + 
32285
		"4. ERROR in SortedList.java (at line 6)\n" + 
32286
		"	int index = Collections.binarySearch(this,e);\n" + 
32287
		"	                        ^^^^^^^^^^^^\n" + 
32288
		"The method binarySearch(List<? extends Comparable<? super T>>, T) in the type Collections is not applicable for the arguments (SortedList<E>, E)\n" + 
32289
		"----------\n");
32290
}
32291
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation
32292
public void test1018() {
32293
	this.runConformTest(
32294
		new String[] {
32295
			"X.java",
32296
			"public class X<U,V> {\n" + 
32297
			"\n" + 
32298
			"	void foo(U u) {\n" + 
32299
			"		bar(u, new Exception());\n" + 
32300
			"	}\n" + 
32301
			"	<T extends Exception> T bar(U u, T t) { return null; }\n" + 
32302
			"}", // =================
32303
		},
32304
		"");
32305
}
31799
}
32306
}

Return to bug 111086