View | Details | Raw Unified | Return to bug 184293
Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java (-6 / +1 lines)
Lines 31605-31616 Link Here
31605
				"}", // =================			
31605
				"}", // =================			
31606
			},
31606
			},
31607
			"----------\n" + 
31607
			"----------\n" + 
31608
			"1. ERROR in X.java (at line 7)\n" + 
31608
			"1. ERROR in X.java (at line 11)\n" + 
31609
			"	abstract class GLinkElementView<M,CM> extends AbstractLinkView<M> {}\n" + 
31610
			"	               ^^^^^^^^^^^^^^^^\n" + 
31611
			"The return type is incompatible with ILinkViewElement.getViewer(), AbstractEditPart.getViewer(), AbstractLinkView<M>.getViewer()\n" + 
31612
			"----------\n" + 
31613
			"2. ERROR in X.java (at line 11)\n" + 
31614
			"	public SheetViewer getViewer() { return null; }	\n" + 
31609
			"	public SheetViewer getViewer() { return null; }	\n" + 
31615
			"	       ^^^^^^^^^^^\n" + 
31610
			"	       ^^^^^^^^^^^\n" + 
31616
			"The return type is incompatible with AbstractEditPart.getViewer()\n" + 
31611
			"The return type is incompatible with AbstractEditPart.getViewer()\n" + 
(-)src/org/eclipse/jdt/core/tests/compiler/regression/MethodVerifyTest.java (-13 / +178 lines)
Lines 708-734 Link Here
708
			new String[] {
708
			new String[] {
709
				"A.java",
709
				"A.java",
710
				"abstract class A implements I {}\n" +
710
				"abstract class A implements I {}\n" +
711
				"interface I extends J { Object foo(); }\n" +
711
				"interface I extends J { Object foo(); }\n" + // with javac only this type gets an error
712
				"interface J { String foo(); }\n",
712
				"interface J { String foo(); }\n",
713
				"X.java",
713
				"X.java",
714
				"abstract class X2 extends A implements J {}\n"
714
				"abstract class X2 extends A implements J {}\n"
715
			},
715
			},
716
			"----------\n" + 
716
			"----------\n" + 
717
			"1. ERROR in A.java (at line 1)\n" + 
717
			"1. ERROR in A.java (at line 2)\n" + 
718
			"	abstract class A implements I {}\n" + 
719
			"	               ^\n" + 
720
			"The return type is incompatible with J.foo(), I.foo()\n" + 
721
			"----------\n" + 
722
			"2. ERROR in A.java (at line 2)\n" + 
723
			"	interface I extends J { Object foo(); }\n" + 
718
			"	interface I extends J { Object foo(); }\n" + 
724
			"	                        ^^^^^^\n" + 
719
			"	                        ^^^^^^\n" + 
725
			"The return type is incompatible with J.foo()\n" + 
720
			"The return type is incompatible with J.foo()\n" + 
726
			"----------\n" + 
727
			"----------\n" + 
728
			"1. ERROR in X.java (at line 1)\n" + 
729
			"	abstract class X2 extends A implements J {}\n" + 
730
			"	               ^^\n" + 
731
			"The return type is incompatible with I.foo(), J.foo()\n" + 
732
			"----------\n"
721
			"----------\n"
733
		);
722
		);
734
	}
723
	}
Lines 7592-7595 Link Here
7592
		"----------\n"
7581
		"----------\n"
7593
	);
7582
	);
7594
}
7583
}
7584
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7585
public void test134() {
7586
	this.runNegativeTest(
7587
		new String[] {
7588
			"X.java",
7589
			"interface I {\n" + 
7590
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
7591
			"}\n" + 
7592
			"interface J extends I {\n" + 
7593
			"  A foo(Number n);\n" +  // warning: overrides <T>foo(java.lang.Number) in I; return type requires unchecked conversion
7594
			"}\n" + 
7595
			"abstract class A extends Exception implements Cloneable {}"
7596
		},
7597
		"----------\n" + 
7598
		"1. WARNING in X.java (at line 5)\n" + 
7599
		"	A foo(Number n);\n" + 
7600
		"	^\n" + 
7601
		"Type safety: The return type A for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
7602
		"----------\n"
7603
	);
7604
}
7605
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7606
public void test135() {
7607
	this.runNegativeTest(
7608
		new String[] {
7609
			"X.java",
7610
			"abstract class X implements J {}\n" + 
7611
			"class X2 implements J {\n" + 
7612
			"  public A foo(Number n) { return null; }\n" +
7613
			"}\n" + 
7614
			"abstract class Y extends X {}\n" + 
7615
			"interface I {\n" + 
7616
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
7617
			"}\n" + 
7618
			"interface J extends I {\n" + 
7619
			"  A foo(Number n);\n" +  // warning: overrides <T>foo(java.lang.Number) in I; return type requires unchecked conversion
7620
			"}\n" + 
7621
			"abstract class A extends Exception implements Cloneable {}"
7622
		},
7623
		"----------\n" + 
7624
		"1. WARNING in X.java (at line 10)\n" + 
7625
		"	A foo(Number n);\n" + 
7626
		"	^\n" + 
7627
		"Type safety: The return type A for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
7628
		"----------\n"
7629
	);
7630
}
7631
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7632
public void test136() {
7633
	this.runNegativeTest(
7634
		new String[] {
7635
			"X.java",
7636
			"public abstract class X extends E {}\n" + 
7637
			"class X2 extends E {\n" + 
7638
			"  @Override public A foo(Number n) { return null; }\n" +
7639
			"}\n" + 
7640
			"abstract class Y extends X {}\n" + 
7641
			"abstract class D {\n" + 
7642
			"  abstract <T extends Exception & Cloneable> T foo(Number n);\n" + 
7643
			"}\n" + 
7644
			"abstract class E extends D {\n" + 
7645
			"  @Override abstract A foo(Number n);\n" +  // warning: overrides <T>foo(java.lang.Number) in I; return type requires unchecked conversion
7646
			"}\n" + 
7647
			"abstract class A extends Exception implements Cloneable {}"
7648
		},
7649
		"----------\n" + 
7650
		"1. WARNING in X.java (at line 10)\n" + 
7651
		"	@Override abstract A foo(Number n);\n" + 
7652
		"	                   ^\n" + 
7653
		"Type safety: The return type A for foo(Number) from the type E needs unchecked conversion to conform to T from the type D\n" + 
7654
		"----------\n"
7655
		// javac reports warnings against X AND Y about E.foo(), as well as reporting the warning on E.foo() twice
7656
	);
7657
}
7658
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7659
public void test137() {
7660
	this.runNegativeTest(
7661
		new String[] {
7662
			"X.java",
7663
			"public abstract class X implements J {}\n" + 
7664
			"interface I {\n" + 
7665
			"  <T extends Y<T> & Cloneable> T foo(Number n);\n" + 
7666
			"}\n" + 
7667
			"interface J extends I {\n" + 
7668
			"  XX foo(Number n);\n" + 
7669
			"}\n" + 
7670
			"class Z { }\n" +
7671
			"class Y <U> extends Z { }" +
7672
			"abstract class XX extends Y<XX> implements Cloneable {}"
7673
		},
7674
		"----------\n" + 
7675
		"1. WARNING in X.java (at line 6)\n" + 
7676
		"	XX foo(Number n);\n" + 
7677
		"	^^\n" + 
7678
		"Type safety: The return type XX for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
7679
		"----------\n"
7680
	);
7681
}
7682
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7683
public void test138() {
7684
	this.runNegativeTest(
7685
		new String[] {
7686
			"X.java",
7687
			"public abstract class X implements J {}\n" + 
7688
			"interface I {\n" + 
7689
			"  <T extends Exception & Cloneable> A<T> foo(Number n);\n" +
7690
			"}\n" +
7691
			"interface J extends I {\n" +
7692
			"  A<XX> foo(Number n);\n" +
7693
			"}\n" + 
7694
			"class A<T> { }" +			
7695
			"abstract class XX extends Exception implements Cloneable {}"
7696
		},
7697
		"----------\n" + 
7698
		"1. WARNING in X.java (at line 6)\n" + 
7699
		"	A<XX> foo(Number n);\n" + 
7700
		"	^\n" + 
7701
		"Type safety: The return type A<XX> for foo(Number) from the type J needs unchecked conversion to conform to A<T> from the type I\n" + 
7702
		"----------\n"
7703
	);
7704
}
7705
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7706
public void test139() {
7707
	this.runNegativeTest(
7708
		new String[] {
7709
			"X.java",
7710
			"public abstract class X implements J {\n" + 
7711
			"  void foo() {}\n" + 
7712
			"  public XX foo(Number n) { return null; }\n" + 
7713
			"}\n" + 
7714
			"interface I {\n" + 
7715
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
7716
			"}\n" + 
7717
			"interface J extends I {\n" + 
7718
			"  XX foo(Number n);\n" + 
7719
			"}\n" + 
7720
			"abstract class XX extends Exception implements Cloneable {}"
7721
		},
7722
		"----------\n" + 
7723
		"1. WARNING in X.java (at line 9)\n" + 
7724
		"	XX foo(Number n);\n" + 
7725
		"	^^\n" + 
7726
		"Type safety: The return type XX for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
7727
		"----------\n"
7728
	);
7729
}
7730
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
7731
public void test140() {
7732
	this.runNegativeTest(
7733
		new String[] {
7734
			"X.java",
7735
			"public abstract class X implements J, K {}\n" + 
7736
			"interface I {\n" + 
7737
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
7738
			"}\n" + 
7739
			"interface J extends I {\n" + 
7740
			"  XX foo(Number n);\n" + 
7741
			"}\n" + 
7742
			"interface K {\n" + 
7743
			"  NullPointerException foo(Number n);\n" + 
7744
			"}\n" + 
7745
			"abstract class XX extends Exception implements Cloneable {}"
7746
		},
7747
		"----------\n" + 
7748
		"1. ERROR in X.java (at line 1)\n" + 
7749
		"	public abstract class X implements J, K {}\n" + 
7750
		"	                      ^\n" + 
7751
		"The return type is incompatible with K.foo(Number), J.foo(Number)\n" + 
7752
		"----------\n" + 
7753
		"2. WARNING in X.java (at line 6)\n" + 
7754
		"	XX foo(Number n);\n" + 
7755
		"	^^\n" + 
7756
		"Type safety: The return type XX for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
7757
		"----------\n"
7758
	);
7759
}
7595
}
7760
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/AmbiguousMethodTest.java (-149 / +2 lines)
Lines 1456-1610 Link Here
1456
		},
1456
		},
1457
		"");
1457
		"");
1458
}
1458
}
1459
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1459
//tests 32-34 were moved to MethodVerityTest 134-140
1460
public void test032() {
1460
1461
	this.runConformTest(
1462
		new String[] {
1463
			"X.java",
1464
			"interface I {\n" + 
1465
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
1466
			"}\n" + 
1467
			"interface J extends I {\n" + 
1468
			"  XX foo(Number n);\n" + 
1469
			"}\n" + 
1470
			"public abstract class X implements J {\n" + 
1471
			"}\n" + 
1472
			"abstract class XX extends Exception implements Cloneable {}"
1473
		},
1474
		"");
1475
}
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
1478
// check
1479
public void test032a() {
1480
	this.runConformTest(
1481
		new String[] {
1482
			"X.java",
1483
			"class Z { }\n" +
1484
			"class Y <U> extends Z { }" +
1485
			"interface I {\n" + 
1486
			"  <T extends Y<T> & Cloneable> T foo(Number n);\n" + 
1487
			"}\n" + 
1488
			"interface J extends I {\n" + 
1489
			"  XX foo(Number n);\n" + 
1490
			"}\n" + 
1491
			"public abstract class X implements J {\n" + 
1492
			"}\n" + 
1493
			"abstract class XX extends Y<XX> implements Cloneable {}"
1494
		},
1495
		"");
1496
}
1497
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
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
1556
public void test033() {
1557
	this.runConformTest(
1558
		new String[] {
1559
			"X.java",
1560
			"interface I {\n" + 
1561
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
1562
			"}\n" + 
1563
			"interface J extends I {\n" + 
1564
			"  XX foo(Number n);\n" + 
1565
			"}\n" + 
1566
			"public abstract class X implements J {\n" + 
1567
			"  void foo() {\n" + 
1568
			"  }\n" + 
1569
			"  public XX foo(Number n) {\n" + 
1570
			"    return null;\n" + 
1571
			"  }\n" + 
1572
			"}\n" + 
1573
			"abstract class XX extends Exception implements Cloneable {}"
1574
		},
1575
		"");
1576
}
1577
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162073
1578
// variant that rightly complains
1579
public void test034() {
1580
	this.runNegativeTest(
1581
		new String[] {
1582
			"X.java",
1583
			"interface I {\n" + 
1584
			"  <T extends Exception & Cloneable> T foo(Number n);\n" + 
1585
			"}\n" + 
1586
			"interface J extends I {\n" + 
1587
			"  XX foo(Number n);\n" + 
1588
			"}\n" + 
1589
			"interface K {\n" + 
1590
			"  NullPointerException foo(Number n);\n" + 
1591
			"}\n" + 
1592
			"public abstract class X implements J, K {\n" + 
1593
			"}\n" + 
1594
			"abstract class XX extends Exception implements Cloneable {}"
1595
		},
1596
		"----------\n" + 
1597
		"1. WARNING in X.java (at line 5)\n" + 
1598
		"	XX foo(Number n);\n" + 
1599
		"	^^\n" + 
1600
		"Type safety: The return type XX for foo(Number) from the type J needs unchecked conversion to conform to T from the type I\n" + 
1601
		"----------\n" + 
1602
		"2. ERROR in X.java (at line 10)\n" + 
1603
		"	public abstract class X implements J, K {\n" + 
1604
		"	                      ^\n" + 
1605
		"The return type is incompatible with K.foo(Number), J.foo(Number)\n" + 
1606
		"----------\n");
1607
}
1608
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162065
1461
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=162065
1609
// variant - the inheriting class implements foo
1462
// variant - the inheriting class implements foo
1610
public void test035() {
1463
public void test035() {
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (-112 / +4 lines)
Lines 344-399 Link Here
344
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
344
boolean checkInheritedReturnTypes(MethodBinding[] methods, int length) {
345
	if (methods[0].declaringClass.isClass())
345
	if (methods[0].declaringClass.isClass())
346
		return super.checkInheritedReturnTypes(methods, length);
346
		return super.checkInheritedReturnTypes(methods, length);
347
	if (length <= 1) {
348
		return true; // no need to continue since only 1 inherited method is left
349
	}
350
	// get rid of overriden methods coming from interfaces - if any
351
	MethodBinding methodsToCheck[] = new MethodBinding[length];	// must not nullify methods slots in place
352
	int count = length;
353
	for (int i = 0; i < length; i++) {
354
		methodsToCheck[i] = methods[i];
355
	}
356
	for (int i = 0; i < length; i++) {
357
		MethodBinding existingMethod;
358
		if ((existingMethod = methodsToCheck[i]) != null) {
359
			for (int j = 0; j < length; j++) {
360
				MethodBinding inheritedMethod;
361
				if (i != j && (inheritedMethod = methodsToCheck[j]) != null &&
362
						existingMethod.declaringClass.implementsInterface(inheritedMethod.declaringClass, true)) {
363
					MethodBinding substitute = computeSubstituteMethod(inheritedMethod, existingMethod);
364
					if (substitute != null && 
365
							doesSubstituteMethodOverride(existingMethod, substitute) &&
366
							(existingMethod.returnType.isCompatibleWith(substitute.returnType) ||
367
									isReturnTypeSubstituable(substitute, existingMethod))) {
368
						count--;
369
						methodsToCheck[j] = null;
370
					}
371
				}
372
			}
373
		}
374
	}
375
	if (count < length) {
376
		if (count == 1) { 
377
			return true; // no need to continue since only 1 inherited method is left
378
		}
379
		for (int i = 0, j = 0; j < count; i++) {
380
			if (methodsToCheck[i] != null) {
381
				methodsToCheck[j++] = methodsToCheck[i];
382
			}
383
		}
384
		methods = methodsToCheck;
385
		length = count;
386
	} // else keep methods unchanged for further checks
387
347
388
	// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C
348
	// its possible in 1.5 that A is compatible with B & C, but B is not compatible with C
389
	for (int i = 0, l = length - 1; i < l;) {
349
	for (int i = 0, l = length - 1; i < l;) {
390
		MethodBinding method = methods[i++];
350
		MethodBinding method = methods[i++];
391
		for (int j = i; j <= l; j++) {
351
		nextMethod : for (int j = i; j <= l; j++) {
392
			if (!areReturnTypesCompatible(method, methods[j])) {
352
			if (!areReturnTypesCompatible(method, methods[j])) {
393
				if (this.type.isInterface())
353
				if (this.type.isInterface())
394
					for (int m = length; --m >= 0;)
354
					for (int m = length; --m >= 0;)
395
						if (methods[m].declaringClass.id == TypeIds.T_JavaLangObject)
355
						if (methods[m].declaringClass.id == TypeIds.T_JavaLangObject)
396
							return false; // do not complain since the super interface already got blamed
356
							continue nextMethod; // do not complain since the super interface already got blamed
397
				problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
357
				problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
398
				return false;
358
				return false;
399
			}
359
			}
Lines 621-704 Link Here
621
	// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod()
581
	// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod()
622
	return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
582
	return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
623
}
583
}
624
// caveat: returns false if a method is implemented but needs that a bridge 
584
// caveat: returns false if a method is implemented that needs a bridge method
625
//         method be generated
626
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
585
boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
627
	if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface())
586
	if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface())
628
		return false; // must hold onto ParameterizedMethod to see if a bridge method is necessary
587
		return false; // must hold onto ParameterizedMethod to see if a bridge method is necessary
629
588
630
	inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod);
589
	inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod);
631
	return inheritedMethod != null
590
	return inheritedMethod != null
632
		&& inheritedMethod.returnType == existingMethod.returnType
591
		&& inheritedMethod.returnType == existingMethod.returnType // keep around to produce bridge methods
633
		&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
592
		&& super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
634
}
593
}
635
/**
636
 * Return true iff the return type of existingMethod is a valid replacement for
637
 * the one of substituteMethod in a method declaration, in the context specified 
638
 * thereafter. It is expected that substituteMethod is the result of the 
639
 * substitution of the type parameters of an inheritedMethod method according to 
640
 * the type parameters of existingMethod and the inheritance relationship 
641
 * between existingMethod's declaring type and inheritedMethod's declaring type,
642
 * where inheritedMethod is a method inherited by existingMethod's declaring 
643
 * type which is override compatible with existingMethod, except maybe for
644
 * their respective return types. If those conditions are not met, the result is
645
 * unspecified.
646
 * @param substituteMethod a proper substitute of a method inherited by existingMethod 
647
 * @param existingMethod the existing method under examination
648
 * @return true if the return type of existingMethod is a valid substitute for
649
 *         the one of substituteMethod
650
 */
651
boolean isReturnTypeSubstituable(MethodBinding substituteMethod, MethodBinding existingMethod) {
652
	class ReturnTypeSubstitution implements Substitution {
653
		TypeBinding replaced, replacer;
654
		ReturnTypeSubstitution(TypeBinding replaced, TypeBinding replacer) {
655
			this.replaced = replaced;
656
			this.replacer = replacer;
657
		}
658
		public LookupEnvironment environment() { 
659
			return environment; 
660
		}
661
		public boolean isRawSubstitution() { 
662
			return false; 
663
		}
664
		public TypeBinding substitute(TypeVariableBinding typeVariable) {
665
			return typeVariable == replaced ? replacer : typeVariable;
666
		}
667
	}
668
	if (substituteMethod.returnType instanceof TypeVariableBinding) {
669
		return ((TypeVariableBinding) substituteMethod.returnType).
670
			boundCheck(
671
				new ReturnTypeSubstitution(substituteMethod.returnType, existingMethod.returnType),
672
				existingMethod.returnType)  == TypeConstants.OK;
673
	} else if (substituteMethod.returnType instanceof ParameterizedTypeBinding) {
674
		if (! (existingMethod.returnType instanceof ParameterizedTypeBinding)) {
675
			return false;
676
		}
677
		ParameterizedTypeBinding substituteReturnType = (ParameterizedTypeBinding) substituteMethod.returnType,
678
			existingReturnType = (ParameterizedTypeBinding) existingMethod.returnType;
679
		if (substituteReturnType.actualType() != existingReturnType.actualType())
680
			return false;
681
		for (int i = 0; i < substituteReturnType.arguments.length; i++) {
682
			TypeBinding substituteArgumentType, existingArgumentType;
683
			if (! (existingArgumentType = existingReturnType.arguments[i]).isCompatibleWith(
684
					substituteArgumentType = substituteReturnType.arguments[i])) {
685
				if (substituteArgumentType instanceof TypeVariableBinding) {
686
					if (((TypeVariableBinding) substituteArgumentType).
687
							boundCheck(
688
								new ReturnTypeSubstitution(substituteArgumentType, existingArgumentType),
689
								// we do not address the most general pattern of multiple type variables, nor the recursive case either
690
								existingArgumentType) != TypeConstants.OK) {
691
						return false;
692
					}
693
				} else {
694
					return false;
695
				}
696
			}
697
		}
698
		return true;
699
	}
700
	return false;
701
}
702
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
594
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
703
	ReferenceBinding[] interfacesToVisit = null;
595
	ReferenceBinding[] interfacesToVisit = null;
704
	int nextPosition = 0;
596
	int nextPosition = 0;
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java (-41 / +91 lines)
Lines 141-188 Link Here
141
		return; // do not repoort against subsequent inherited methods
141
		return; // do not repoort against subsequent inherited methods
142
	}
142
	}
143
	CompilerOptions options = type.scope.compilerOptions();
143
	CompilerOptions options = type.scope.compilerOptions();
144
	// need to find the overridden methods to avoid blaming this type for issues which are already reported against a supertype
145
	// but cannot ignore an overridden inherited method completely when it comes to checking for bridge methods
146
	int[] overriddenInheritedMethods = findOverriddenInheritedMethods(methods, length);
144
	nextMethod : for (int i = length; --i >= 0;) {
147
	nextMethod : for (int i = length; --i >= 0;) {
145
		MethodBinding inheritedMethod = methods[i];
148
		MethodBinding inheritedMethod = methods[i];
146
		if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
149
		if (overriddenInheritedMethods == null || overriddenInheritedMethods[i] == 0) {
147
			problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
150
			if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
148
			continue nextMethod;
151
				problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
149
		}
152
				continue nextMethod;
150
153
			}
151
		// want to tag currentMethod even if return types are not equal
154
	
152
		if (inheritedMethod.isAbstract()) {
155
			// want to tag currentMethod even if return types are not equal
153
			if (inheritedMethod.declaringClass.isInterface()) {
156
			if (inheritedMethod.isAbstract()) {
154
				currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing;
157
				if (inheritedMethod.declaringClass.isInterface()) {
158
					currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing;
159
				} else {
160
					currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding;
161
				}
162
//			with the above change an abstract method is tagged as implementing the inherited abstract method
163
//			if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
164
//				if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
165
//					currentMethod.modifiers |= CompilerModifiers.AccImplementing;
155
			} else {
166
			} else {
156
				currentMethod.modifiers |= ExtraCompilerModifiers.AccImplementing | ExtraCompilerModifiers.AccOverriding;
167
				currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
157
			}
168
			}
158
// with the above change an abstract method is tagged as implementing the inherited abstract method
169
	
159
//		if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
170
			if (!areReturnTypesCompatible(currentMethod, inheritedMethod))
160
//			if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
171
				if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod))
161
//				currentMethod.modifiers |= CompilerModifiers.AccImplementing;
172
					continue nextMethod;
162
		} else {
173
	
163
			currentMethod.modifiers |= ExtraCompilerModifiers.AccOverriding;
174
			if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS)
164
		}
175
				checkExceptions(currentMethod, inheritedMethod);
165
176
			if (inheritedMethod.isFinal())
166
		if (!areReturnTypesCompatible(currentMethod, inheritedMethod))
177
				problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
167
			if (reportIncompatibleReturnTypeError(currentMethod, inheritedMethod))
178
			if (!isAsVisible(currentMethod, inheritedMethod))
168
				continue nextMethod;
179
				problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
169
180
			if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) {
170
		if (currentMethod.thrownExceptions != Binding.NO_EXCEPTIONS)
181
				if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) {
171
			checkExceptions(currentMethod, inheritedMethod);
182
					// check against the other inherited methods to see if they hide this inheritedMethod
172
		if (inheritedMethod.isFinal())
183
					ReferenceBinding declaringClass = inheritedMethod.declaringClass;
173
			problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
184
					if (declaringClass.isInterface())
174
		if (!isAsVisible(currentMethod, inheritedMethod))
185
						for (int j = length; --j >= 0;)
175
			problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
186
							if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
176
		if (options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) {
187
								continue nextMethod;
177
			if (!currentMethod.isViewedAsDeprecated() || options.reportDeprecationInsideDeprecatedCode) {
188
	
178
				// check against the other inherited methods to see if they hide this inheritedMethod
189
					problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
179
				ReferenceBinding declaringClass = inheritedMethod.declaringClass;
190
				}
180
				if (declaringClass.isInterface())
181
					for (int j = length; --j >= 0;)
182
						if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
183
							continue nextMethod;
184
185
				problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
186
			}
191
			}
187
		}
192
		}
188
		checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
193
		checkForBridgeMethod(currentMethod, inheritedMethod, allInheritedMethods);
Lines 231-236 Link Here
231
	// no op before 1.5
236
	// no op before 1.5
232
}
237
}
233
void checkInheritedMethods(MethodBinding[] methods, int length) {
238
void checkInheritedMethods(MethodBinding[] methods, int length) {
239
	int[] overriddenInheritedMethods = findOverriddenInheritedMethods(methods, length);
240
	if (overriddenInheritedMethods != null) {
241
		// detected some overridden methods that can be ignored when checking return types
242
		int index = 0;
243
		MethodBinding[] closestMethods = new MethodBinding[length];
244
		for (int i = 0; i < length; i++)
245
			if (overriddenInheritedMethods[i] == 0)
246
				closestMethods[index++] = methods[i];
247
		methods = closestMethods;
248
		length = index;
249
	}
250
234
	if (!checkInheritedReturnTypes(methods, length))
251
	if (!checkInheritedReturnTypes(methods, length))
235
		return;
252
		return;
236
253
Lines 573-578 Link Here
573
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
590
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
574
	return areParametersEqual(method, inheritedMethod);
591
	return areParametersEqual(method, inheritedMethod);
575
}
592
}
593
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
594
	return null; // noop in 1.4
595
}
596
int[] findOverriddenInheritedMethods(MethodBinding[] methods, int length) {
597
	int[] toSkip = null;
598
	if (length > 1) {
599
		nextMethod : for (int i = 0; i < length; i++) {
600
			if (toSkip != null && toSkip[i] == -1) continue nextMethod;
601
			ReferenceBinding declaringClass = methods[i].declaringClass;
602
			if (declaringClass.isInterface()) {
603
				for (int j = 0; j < length; j++) {
604
					if (i == j) continue;
605
					ReferenceBinding declaringClass2 = methods[j].declaringClass;
606
					if (declaringClass2.isInterface() && declaringClass2.implementsInterface(declaringClass, true)) {
607
						if (toSkip == null)
608
							toSkip = new int[length];
609
						toSkip[i] = -1;
610
						continue nextMethod;
611
					}
612
				}
613
			} else { 
614
				for (int j = 0; j < length; j++) {
615
					if (i == j) continue;
616
					ReferenceBinding declaringClass2 = methods[j].declaringClass;
617
					if (!declaringClass2.isInterface() && declaringClass.isSuperclassOf(declaringClass2)) {
618
						if (toSkip == null)
619
							toSkip = new int[length];
620
						toSkip[i] = -1;
621
						continue nextMethod;
622
					}
623
				}
624
			}
625
		}
626
	}
627
	return toSkip;
628
}
576
boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
629
boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
577
	if (inheritedMethod.modifiers == newMethod.modifiers) return true;
630
	if (inheritedMethod.modifiers == newMethod.modifiers) return true;
578
631
Lines 624-632 Link Here
624
		reporter.referenceContext = currentMethod.sourceMethod();
677
		reporter.referenceContext = currentMethod.sourceMethod();
625
	return reporter;
678
	return reporter;
626
}
679
}
627
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
628
	return null; // noop in 1.4
629
}
630
/**
680
/**
631
 * Return true and report an incompatibleReturnType error if currentMethod's
681
 * Return true and report an incompatibleReturnType error if currentMethod's
632
 * return type is strictly incompatible with inheritedMethod's, else return 
682
 * return type is strictly incompatible with inheritedMethod's, else return 

Return to bug 184293