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

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java (-3 / +60 lines)
Lines 1457-1463 Link Here
1457
		"");
1457
		"");
1458
}
1458
}
1459
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1459
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1460
public void _test032() {
1460
public void test032() {
1461
	this.runConformTest(
1461
	this.runConformTest(
1462
		new String[] {
1462
		new String[] {
1463
			"X.java",
1463
			"X.java",
Lines 1476-1482 Link Here
1476
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1476
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1477
// variant that shows that the use of a substitution is needed during the bounds
1477
// variant that shows that the use of a substitution is needed during the bounds
1478
// check
1478
// check
1479
public void _test032a() {
1479
public void test032a() {
1480
	this.runConformTest(
1480
	this.runConformTest(
1481
		new String[] {
1481
		new String[] {
1482
			"X.java",
1482
			"X.java",
Lines 1496-1501 Link Here
1496
}
1496
}
1497
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1497
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1498
// variant
1498
// variant
1499
public void test032b() {
1500
	this.runConformTest(
1501
		new String[] {
1502
			"X.java",
1503
			"class A<T> { }" +			
1504
			"interface I {\n" + 
1505
			"  <T extends Exception & Cloneable> A<T> foo(Number n);\n" +
1506
			"}\n" +
1507
			"interface J extends I {\n" +
1508
			"  A<XX> foo(Number n);\n" +
1509
			"}\n" + 
1510
			"public abstract class X implements J {\n" + 
1511
			"}\n" + 
1512
			"abstract class XX extends Exception implements Cloneable {}"
1513
		},
1514
		"");
1515
}
1516
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1517
// variant
1518
public void test032c() {
1519
	this.runConformTest(
1520
		new String[] {
1521
			"X.java",
1522
			"class A<T> { }" +			
1523
			"interface I {\n" + 
1524
			"  <T extends Exception & Cloneable> A<T> foo(Number n);\n" +
1525
			"}\n" +
1526
			"interface J extends I {\n" +
1527
			"  <S extends XX>  A<S> foo(Number n);\n" +
1528
			"}\n" + 
1529
			"public abstract class X implements J {\n" + 
1530
			"}\n" + 
1531
			"abstract class XX extends Exception implements Cloneable {}"
1532
		},
1533
		"");
1534
}
1535
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1536
// variant
1537
public void test032d() {
1538
	this.runConformTest(
1539
		new String[] {
1540
			"X.java",
1541
			"class A<T> { }" +			
1542
			"interface I {\n" + 
1543
			"  A<XX> foo(Number n);\n" +
1544
			"}\n" +
1545
			"interface J extends I {\n" +
1546
			"  <T extends Exception & Cloneable> A<T> foo(Number n);\n" +
1547
			"}\n" + 
1548
			"public abstract class X implements J {\n" + 
1549
			"}\n" + 
1550
			"abstract class XX extends Exception implements Cloneable {}"
1551
		},
1552
		"");
1553
}
1554
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1555
// variant
1499
public void test033() {
1556
public void test033() {
1500
	this.runConformTest(
1557
	this.runConformTest(
1501
		new String[] {
1558
		new String[] {
Lines 1545-1551 Link Here
1545
		"2. ERROR in X.java (at line 10)\n" + 
1602
		"2. ERROR in X.java (at line 10)\n" + 
1546
		"	public abstract class X implements J, K {\n" + 
1603
		"	public abstract class X implements J, K {\n" + 
1547
		"	                      ^\n" + 
1604
		"	                      ^\n" + 
1548
		"The return type is incompatible with I.foo(Number), K.foo(Number), J.foo(Number)\n" + 
1605
		"The return type is incompatible with K.foo(Number), J.foo(Number)\n" + 
1549
		"----------\n");
1606
		"----------\n");
1550
}
1607
}
1551
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162065
1608
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162065
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (+108 lines)
Lines 316-321 Link Here
316
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
316
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
317
	if (methods[0].declaringClass.isClass())
317
	if (methods[0].declaringClass.isClass())
318
		return super.checkInheritedReturnTypes(methods, length);
318
		return super.checkInheritedReturnTypes(methods, length);
319
	if (length <= 1) {
320
		return true; // no need to continue since only 1 inherited method is left
321
	}
322
	// get rid of overriden methods coming from interfaces - if any
323
	MethodBinding methodsToCheck[] = new MethodBinding[length];	// must not nullify methods slots in place
324
	int count = length;
325
	for (int i = 0; i < length; i++) {
326
		methodsToCheck[i] = methods[i];
327
	}
328
	for (int i = 0; i < length; i++) {
329
		MethodBinding existingMethod;
330
		if ((existingMethod = methodsToCheck[i]) != null) {
331
			for (int j = 0; j < length; j++) {
332
				MethodBinding inheritedMethod;
333
				if (i != j && (inheritedMethod = methodsToCheck[j]) != null &&
334
						existingMethod.declaringClass.implementsInterface(inheritedMethod.declaringClass, true)) {
335
					MethodBinding substitute = computeSubstituteMethod(inheritedMethod, existingMethod);
336
					if (substitute != null && 
337
							doesSubstituteMethodOverride(existingMethod, substitute) &&
338
							(existingMethod.returnType.isCompatibleWith(substitute.returnType) ||
339
									isReturnTypeSubstituable(substitute, existingMethod))) {
340
						count--;
341
						methodsToCheck[j] = null;
342
					}
343
				}
344
			}
345
		}
346
	}
347
	if (count < length) {
348
		if (count == 1) { 
349
			return true; // no need to continue since only 1 inherited method is left
350
		}
351
		for (int i = 0, j = 0; j < count; i++) {
352
			if (methodsToCheck[i] != null) {
353
				methodsToCheck[j++] = methodsToCheck[i];
354
			}
355
		}
356
		methods = methodsToCheck;
357
		length = count;
358
	} // else keep methods unchanged for further checks
319
359
320
	// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C
360
	// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C
321
	for (int i = 0, l = length - 1; i < l;) {
361
	for (int i = 0, l = length - 1; i < l;) {
Lines 564-569 Link Here
564
		&& inheritedMethod.returnType == existingMethod.returnType
604
		&& inheritedMethod.returnType == existingMethod.returnType
565
		&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
605
		&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
566
}
606
}
607
/**
608
 * Return true iff the return type of existingMethod is a valid replacement for
609
 * the one of substituteMethod in a method declaration, in the context specified 
610
 * thereafter. It is expected that substituteMethod is the result of the 
611
 * substitution of the type parameters of an inheritedMethod method according to 
612
 * the type parameters of existingMethod and the inheritance relationship 
613
 * between existingMethod's declaring type and inheritedMethod's declaring type,
614
 * where inheritedMethod is a method inherited by existingMethod's declaring 
615
 * type which is override compatible with existingMethod, except maybe for
616
 * their respective return types. If those conditions are not met, the result is
617
 * unspecified.
618
 * @param substituteMethod a proper substitute of a method inherited by existingMethod 
619
 * @param existingMethod the existing method under examination
620
 * @return true if the return type of existingMethod is a valid substitute for
621
 *         the one of substituteMethod
622
 */
623
boolean isReturnTypeSubstituable(MethodBinding substituteMethod, MethodBinding existingMethod) {
624
	class ReturnTypeSubstitution implements Substitution {
625
		TypeBinding replaced, replacer;
626
		ReturnTypeSubstitution(TypeBinding replaced, TypeBinding replacer) {
627
			this.replaced = replaced;
628
			this.replacer = replacer;
629
		}
630
		public LookupEnvironment environment() { 
631
			return environment; 
632
		}
633
		public boolean isRawSubstitution() { 
634
			return false; 
635
		}
636
		public TypeBinding substitute(TypeVariableBinding typeVariable) {
637
			return typeVariable == replaced ? replacer : typeVariable;
638
		}
639
	}
640
	if (substituteMethod.returnType instanceof TypeVariableBinding) {
641
		return ((TypeVariableBinding) substituteMethod.returnType).
642
			boundCheck(
643
				new ReturnTypeSubstitution(substituteMethod.returnType, existingMethod.returnType),
644
				existingMethod.returnType)  == TypeConstants.OK;
645
	} else if (substituteMethod.returnType instanceof ParameterizedTypeBinding) {
646
		if (! (existingMethod.returnType instanceof ParameterizedTypeBinding)) {
647
			return false;
648
		}
649
		ParameterizedTypeBinding substituteReturnType = (ParameterizedTypeBinding) substituteMethod.returnType,
650
			existingReturnType = (ParameterizedTypeBinding) existingMethod.returnType;
651
		if (substituteReturnType.type != existingReturnType.type) {
652
			return false;
653
		}
654
		for (int i = 0; i < substituteReturnType.arguments.length; i++) {
655
			TypeBinding substituteArgumentType, existingArgumentType;
656
			if (! (existingArgumentType = existingReturnType.arguments[i]).isCompatibleWith(
657
					substituteArgumentType = substituteReturnType.arguments[i])) {
658
				if (substituteArgumentType instanceof TypeVariableBinding) {
659
					if (((TypeVariableBinding) substituteArgumentType).
660
							boundCheck(
661
								new ReturnTypeSubstitution(substituteArgumentType, existingArgumentType),
662
								// we do not address the most general pattern of multiple type variables, nor the recursive case either
663
								existingArgumentType) != TypeConstants.OK) {
664
						return false;
665
					}
666
				} else {
667
					return false;
668
				}
669
			}
670
		}
671
		return true;
672
	}
673
	return false;
674
}
567
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
675
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
568
	ReferenceBinding[] interfacesToVisit = null;
676
	ReferenceBinding[] interfacesToVisit = null;
569
	int nextPosition = 0;
677
	int nextPosition = 0;
(-)buildnotes_jdt-core.html (-1 / +3 lines)
Lines 172-178 Link Here
172
</li>
172
</li>
173
173
174
<h3>Problem Reports Fixed</h3>
174
<h3>Problem Reports Fixed</h3>
175
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=171066">171066</a>
175
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=162073">162073</a>
176
[compiler] extraneous interface compatibility error
177
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=171066">171066</a>
176
Provide TextEdit when sorting compilation unit
178
Provide TextEdit when sorting compilation unit
177
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=170318">170318</a>
179
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=170318">170318</a>
178
[1.5][compiler] improve message on nameclash when overriding method with "wildcard" parameter
180
[1.5][compiler] improve message on nameclash when overriding method with "wildcard" parameter

Return to bug 162073