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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java (-9 / +50 lines)
Lines 162-169 Link Here
162
    // iterate superclass to avoid recording interfaces if searched supertype is class
162
    // iterate superclass to avoid recording interfaces if searched supertype is class
163
    if (erasureIsClass) {
163
    if (erasureIsClass) {
164
		while ((currentType = currentType.superclass()) != null) { 
164
		while ((currentType = currentType.superclass()) != null) { 
165
			if (currentType.id == wellKnownErasureID || (!currentType.isTypeVariable() && !currentType.isIntersectionType() && currentType.erasure().id == wellKnownErasureID))
165
			if (currentType.id == wellKnownErasureID)
166
				return currentType;
166
				return currentType;
167
			switch(currentType.kind()) {
168
				case Binding.PARAMETERIZED_TYPE :
169
				case Binding.RAW_TYPE :
170
				case Binding.ARRAY_TYPE :
171
					if (currentType.erasure().id == wellKnownErasureID) 
172
						return currentType;
173
			}
167
		}    
174
		}    
168
		return null;
175
		return null;
169
    }
176
    }
Lines 191-199 Link Here
191
			
198
			
192
	for (int i = 0; i < nextPosition; i++) {
199
	for (int i = 0; i < nextPosition; i++) {
193
		currentType = interfacesToVisit[i];
200
		currentType = interfacesToVisit[i];
194
		if (currentType.id == wellKnownErasureID || (!currentType.isTypeVariable() && !currentType.isIntersectionType() && currentType.erasure().id == wellKnownErasureID))
201
		if (currentType.id == wellKnownErasureID)
195
			return currentType;
202
			return currentType;
196
203
		switch(currentType.kind()) {
204
			case Binding.PARAMETERIZED_TYPE :
205
			case Binding.RAW_TYPE :
206
			case Binding.ARRAY_TYPE : 
207
				if (currentType.erasure().id == wellKnownErasureID) 
208
					return currentType;
209
		}
197
		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
210
		ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
198
		if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
211
		if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
199
			int itsLength = itsInterfaces.length;
212
			int itsLength = itsInterfaces.length;
Lines 216-222 Link Here
216
public TypeBinding findSuperTypeWithSameErasure(TypeBinding otherType) {
229
public TypeBinding findSuperTypeWithSameErasure(TypeBinding otherType) {
217
	if (this == otherType) return this;
230
	if (this == otherType) return this;
218
	if (otherType == null) return null;
231
	if (otherType == null) return null;
219
	switch(kind()) {
232
	int kind;
233
	switch(kind = kind()) {
220
		case Binding.ARRAY_TYPE :
234
		case Binding.ARRAY_TYPE :
221
			ArrayBinding arrayType = (ArrayBinding) this;
235
			ArrayBinding arrayType = (ArrayBinding) this;
222
			int otherDim = otherType.dimensions();
236
			int otherDim = otherType.dimensions();
Lines 253-265 Link Here
253
		case Binding.RAW_TYPE :
267
		case Binding.RAW_TYPE :
254
		case Binding.WILDCARD_TYPE :
268
		case Binding.WILDCARD_TYPE :
255
		    // do not allow type variables/intersection types to match with erasures for free
269
		    // do not allow type variables/intersection types to match with erasures for free
256
		    if (!otherType.isTypeVariable() && !otherType.isIntersectionType()) otherType = otherType.erasure();
270
			switch(otherType.kind()) {
257
		    if (this == otherType || (!isTypeVariable() && !isIntersectionType() && erasure() == otherType)) return this;
271
				case Binding.PARAMETERIZED_TYPE :
272
				case Binding.RAW_TYPE :
273
				case Binding.ARRAY_TYPE : 
274
					otherType = otherType.erasure();
275
			}
276
		    if (this == otherType)
277
		    	return this;
278
			switch(kind) {
279
				case Binding.PARAMETERIZED_TYPE :
280
				case Binding.RAW_TYPE :
281
				case Binding.ARRAY_TYPE : 
282
					if (erasure() == otherType)
283
						return this;
284
			}
258
		    
285
		    
259
		    ReferenceBinding currentType = (ReferenceBinding)this;
286
		    ReferenceBinding currentType = (ReferenceBinding)this;
260
		    if (!otherType.isInterface()) {
287
		    if (!otherType.isInterface()) {
261
				while ((currentType = currentType.superclass()) != null) {
288
				while ((currentType = currentType.superclass()) != null) {
262
					if (currentType == otherType || (!currentType.isTypeVariable() && !currentType.isIntersectionType() && currentType.erasure() == otherType)) return currentType;
289
					if (currentType == otherType)
290
						return currentType;
291
					switch(currentType.kind()) {
292
						case Binding.PARAMETERIZED_TYPE :
293
						case Binding.RAW_TYPE :
294
						case Binding.ARRAY_TYPE : 
295
							if (currentType.erasure() == otherType)
296
								return currentType;
297
					}					
263
				}
298
				}
264
				return null;
299
				return null;
265
		    }
300
		    }
Lines 287-295 Link Here
287
					
322
					
288
			for (int i = 0; i < nextPosition; i++) {
323
			for (int i = 0; i < nextPosition; i++) {
289
				currentType = interfacesToVisit[i];
324
				currentType = interfacesToVisit[i];
290
				if (currentType == otherType || (!currentType.isTypeVariable() && !currentType.isIntersectionType() && currentType.erasure() == otherType))
325
				if (currentType == otherType)
291
					return currentType;
326
					return currentType;
292
327
				switch(currentType.kind()) {
328
					case Binding.PARAMETERIZED_TYPE :
329
					case Binding.RAW_TYPE :
330
					case Binding.ARRAY_TYPE : 
331
						if (currentType.erasure() == otherType)
332
							return currentType;
333
				}					
293
				ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
334
				ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
294
				if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
335
				if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
295
					int itsLength = itsInterfaces.length;
336
					int itsLength = itsInterfaces.length;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java (-2 / +11 lines)
Lines 75-87 Link Here
75
								if (!wildcardBound.isCompatibleWith(superclassBound))
75
								if (!wildcardBound.isCompatibleWith(superclassBound))
76
									return TypeConstants.MISMATCH;
76
									return TypeConstants.MISMATCH;
77
							} else {
77
							} else {
78
								TypeBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeWithSameErasure(superclassBound);
78
								TypeBinding match = wildcardBound.findSuperTypeWithSameErasure(superclassBound);
79
								if (match != null) {
79
								if (match != null) {
80
									if (!match.isIntersectingWith(superclassBound)) {
80
									if (!match.isIntersectingWith(superclassBound)) {
81
										return TypeConstants.MISMATCH;
81
										return TypeConstants.MISMATCH;
82
									}
82
									}
83
								} else {
83
								} else {
84
									return TypeConstants.MISMATCH;
84
									match =  superclassBound.findSuperTypeWithSameErasure(wildcardBound);
85
									if (match != null) {
86
										if (!match.isIntersectingWith(wildcardBound)) {
87
											return TypeConstants.MISMATCH;
88
										}
89
									} else {
90
										if (!wildcardBound.isTypeVariable() && !superclassBound.isTypeVariable()) {
91
											return TypeConstants.MISMATCH;
92
										}
93
									}
85
								}
94
								}
86
							}
95
							}
87
						}
96
						}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java (-7 / +15 lines)
Lines 101-125 Link Here
101
		switch (wildcard.boundKind) {
101
		switch (wildcard.boundKind) {
102
			case Wildcard.EXTENDS :
102
			case Wildcard.EXTENDS :
103
				// still need to capture bound supertype as well so as not to expose wildcards to the outside (111208)
103
				// still need to capture bound supertype as well so as not to expose wildcards to the outside (111208)
104
				TypeBinding substitutedWildcardBound = originalWildcardBound.capture(scope, this.position);
104
				TypeBinding capturedWildcardBound = originalWildcardBound.capture(scope, this.position);
105
				if (wildcard.bound.isInterface()) {
105
				if (wildcard.bound.isInterface()) {
106
					this.superclass = substitutedVariableSuperclass;
106
					this.superclass = substitutedVariableSuperclass;
107
					// merge wildcard bound into variable superinterfaces using glb
107
					// merge wildcard bound into variable superinterfaces using glb
108
					if (substitutedVariableInterfaces == Binding.NO_SUPERINTERFACES) {
108
					if (substitutedVariableInterfaces == Binding.NO_SUPERINTERFACES) {
109
						this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) substitutedWildcardBound };
109
						this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound };
110
					} else {
110
					} else {
111
						int length = substitutedVariableInterfaces.length;
111
						int length = substitutedVariableInterfaces.length;
112
						System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length);
112
						System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length);
113
						substitutedVariableInterfaces[0] =  (ReferenceBinding) substitutedWildcardBound;
113
						substitutedVariableInterfaces[0] =  (ReferenceBinding) capturedWildcardBound;
114
						this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces);
114
						this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces);
115
					}
115
					}
116
				} else {
116
				} else {
117
					// per construction the wildcard bound is a subtype of variable superclass
117
					// the wildcard bound should be a subtype of variable superclass
118
					this.superclass = wildcard.bound.isArrayType() ? substitutedVariableSuperclass : (ReferenceBinding) substitutedWildcardBound;
118
					// it may occur that the bound is less specific, then consider glb (202404)
119
					if (capturedWildcardBound.isArrayType() || capturedWildcardBound == this) {
120
						this.superclass = substitutedVariableSuperclass;
121
					} else {
122
						this.superclass = (ReferenceBinding) capturedWildcardBound;
123
						if (this.superclass.isSuperclassOf(substitutedVariableSuperclass)) {
124
							this.superclass = substitutedVariableSuperclass;
125
						}
126
					}
119
					this.superInterfaces = substitutedVariableInterfaces;
127
					this.superInterfaces = substitutedVariableInterfaces;
120
				}
128
				}
121
				this.firstBound =  substitutedWildcardBound;
129
				this.firstBound =  capturedWildcardBound;
122
				if ((substitutedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
130
				if ((capturedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
123
					this.tagBits &= ~TagBits.HasTypeVariable;
131
					this.tagBits &= ~TagBits.HasTypeVariable;
124
				break;
132
				break;
125
			case Wildcard.UNBOUND :
133
			case Wildcard.UNBOUND :
(-)src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java (-28 / +48 lines)
Lines 21182-21192 Link Here
21182
		"	Store<? extends Key<T>> store1;\n" + 
21182
		"	Store<? extends Key<T>> store1;\n" + 
21183
		"	                    ^\n" + 
21183
		"	                    ^\n" + 
21184
		"Bound mismatch: The type T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" + 
21184
		"Bound mismatch: The type T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" + 
21185
		"----------\n" + 
21186
		"2. ERROR in X.java (at line 6)\n" + 
21187
		"	Store<? extends Key<? extends T>> store2;\n" + 
21188
		"	                    ^^^^^^^^^^^\n" + 
21189
		"Bound mismatch: The type ? extends T is not a valid substitute for the bounded parameter <E extends Key<E>> of the type Key<E>\n" + 
21190
		"----------\n");
21185
		"----------\n");
21191
}	
21186
}	
21192
//check fault tolerance, in spite of bound mismatch, still pass param type for further resolving message send
21187
//check fault tolerance, in spite of bound mismatch, still pass param type for further resolving message send
Lines 33911-33933 Link Here
33911
		"Type mismatch: cannot convert from capture#4-of ? extends S to capture#1-of ? extends Long\n" + 
33906
		"Type mismatch: cannot convert from capture#4-of ? extends S to capture#1-of ? extends Long\n" + 
33912
		"----------\n");
33907
		"----------\n");
33913
}
33908
}
33914
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159214
33909
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159214 - variation
33915
public void test1044() {
33910
public void test1044() {
33916
	this.runNegativeTest(
33911
	this.runConformTest(
33917
		new String[] {
33912
		new String[] {
33918
			"X.java",
33913
			"X.java",
33919
			"class X<T extends Number> {\n" + 
33914
			"class X<T extends Number> {\n" + 
33920
			"    X<? extends Object> x;\n" + 
33915
			"    X<? extends Object> x;\n" + 
33921
			"}", // =================
33916
			"}", // =================
33922
		}, 
33917
		}, 
33923
		"----------\n" + 
33918
		"");
33924
		"1. ERROR in X.java (at line 2)\n" + 
33925
		"	X<? extends Object> x;\n" + 
33926
		"	  ^^^^^^^^^^^^^^^^\n" + 
33927
		"Bound mismatch: The type ? extends Object is not a valid substitute for the bounded parameter <T extends Number> of the type X<T>\n" + 
33928
		"----------\n");
33929
}
33919
}
33930
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159214
33920
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=159214 - variation
33931
public void test1045() {
33921
public void test1045() {
33932
	this.runConformTest(
33922
	this.runConformTest(
33933
		new String[] {
33923
		new String[] {
Lines 38712-38734 Link Here
38712
			"}\n", // =================
38702
			"}\n", // =================
38713
		},
38703
		},
38714
		"----------\n" + 
38704
		"----------\n" + 
38715
		"1. ERROR in X.java (at line 10)\n" + 
38705
		"1. ERROR in X.java (at line 11)\n" + 
38716
		"	D<?, ? extends A> d2 = null;\n" + 
38717
		"	     ^^^^^^^^^^^\n" + 
38718
		"Bound mismatch: The type ? extends A is not a valid substitute for the bounded parameter <V extends U> of the type D<U,V>\n" + 
38719
		"----------\n" + 
38720
		"2. ERROR in X.java (at line 11)\n" + 
38721
		"	D<B, C> d3 = null;\n" + 
38706
		"	D<B, C> d3 = null;\n" + 
38722
		"	     ^\n" + 
38707
		"	     ^\n" + 
38723
		"Bound mismatch: The type C is not a valid substitute for the bounded parameter <V extends U> of the type D<U,V>\n" + 
38708
		"Bound mismatch: The type C is not a valid substitute for the bounded parameter <V extends U> of the type D<U,V>\n" + 
38724
		"----------\n"		
38709
		"----------\n"
38725
//		TODO should be:
38726
//		"----------\n" + 
38727
//		"1. ERROR in X.java (at line 11)\n" + 
38728
//		"	D<B, C> d3 = null;\n" + 
38729
//		"	     ^\n" + 
38730
//		"Bound mismatch: The type C is not a valid substitute for the bounded parameter <V extends U> of the type D<U,V>\n" + 
38731
//		"----------\n"
38732
		);
38710
		);
38733
}
38711
}
38734
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38712
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
Lines 38940-38943 Link Here
38940
		"The final field X<T>.mObj cannot be assigned\n" + 
38918
		"The final field X<T>.mObj cannot be assigned\n" + 
38941
		"----------\n");
38919
		"----------\n");
38942
}
38920
}
38921
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38922
public void test1165() {
38923
	this.runNegativeTest(
38924
		new String[] {
38925
			"X.java",
38926
			" interface A {}\n" + 
38927
			" class B implements A {}\n" + 
38928
			" class C implements A{}\n" + 
38929
			" \n" + 
38930
			" class D<U extends A, V extends U> {}\n" + 
38931
			"\n" + 
38932
			"public class X {\n" + 
38933
			"	void foo() {\n" + 
38934
			"		D<?, ? super A> d1 = null;\n" + 
38935
			"		D<?, ? extends A> d2 = null;\n" + 
38936
			"		D<B, C> d3 = null;\n" + 
38937
			"		D<?, ?> d4 = null;\n" + 
38938
			"	}\n" + 
38939
			"}\n", // =================
38940
		},
38941
		"----------\n" + 
38942
		"1. ERROR in X.java (at line 11)\n" + 
38943
		"	D<B, C> d3 = null;\n" + 
38944
		"	     ^\n" + 
38945
		"Bound mismatch: The type C is not a valid substitute for the bounded parameter <V extends U> of the type D<U,V>\n" + 
38946
		"----------\n"
38947
		);
38948
}
38949
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203318
38950
public void test1166() {
38951
	this.runConformTest(
38952
		new String[] {
38953
			"X.java",
38954
			"public class X<T extends Number> {\n" + 
38955
			"	T get() {	return null; };\n" + 
38956
			"    void foo(X<? extends Object> x) {\n" + 
38957
			"		x.get().intValue();    	\n" + 
38958
			"    }\n" + 
38959
			"}\n", // =================
38960
		},
38961
		"");
38962
}
38943
}
38963
}

Return to bug 202404