Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 399263
Collapse All | Expand All

(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java (-2 / +2 lines)
Lines 364-374 Link Here
364
		}
364
		}
365
	}
365
	}
366
366
367
	// ==== minimal set of utility methods previously from MethodVerifier15: ====
367
	// ==== minimal set of utility methods previously from MethodVerifier15: ====
368
	
368
	
369
	boolean areParametersEqual(MethodBinding one, MethodBinding two) {
369
	static boolean areParametersEqual(MethodBinding one, MethodBinding two) {
370
		TypeBinding[] oneArgs = one.parameters;
370
		TypeBinding[] oneArgs = one.parameters;
371
		TypeBinding[] twoArgs = two.parameters;
371
		TypeBinding[] twoArgs = two.parameters;
372
		if (oneArgs == twoArgs) return true;
372
		if (oneArgs == twoArgs) return true;
373
373
374
		int length = oneArgs.length;
374
		int length = oneArgs.length;
Lines 408-418 Link Here
408
				return false; // no remaining parameter can be a Parameterized type (if one has been converted then all RAW types must be converted)
408
				return false; // no remaining parameter can be a Parameterized type (if one has been converted then all RAW types must be converted)
409
			}
409
			}
410
		}
410
		}
411
		return true;
411
		return true;
412
	}
412
	}
413
	boolean areTypesEqual(TypeBinding one, TypeBinding two) {
413
	static boolean areTypesEqual(TypeBinding one, TypeBinding two) {
414
		if (one == two) return true;
414
		if (one == two) return true;
415
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329584
415
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329584
416
		switch(one.kind()) {
416
		switch(one.kind()) {
417
			case Binding.TYPE:
417
			case Binding.TYPE:
418
				switch (two.kind()) {
418
				switch (two.kind()) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java (-99 / +137 lines)
Lines 65-77 Link Here
65
	this.environment = environment;
65
	this.environment = environment;
66
	this.allowCompatibleReturnTypes =
66
	this.allowCompatibleReturnTypes =
67
		environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5
67
		environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5
68
			&& environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5;
68
			&& environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5;
69
}
69
}
70
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
70
//boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
71
	return isParameterSubsignature(one, two) && areReturnTypesCompatible(one, two);
71
//	return isParameterSubsignature(one, two) && areReturnTypesCompatible(one, two);
72
//}
73
74
static boolean areMethodsCompatible(MethodBinding one, MethodBinding two, LookupEnvironment localEnvironment) {
75
	// use the original methods to test compatibility, but do not check visibility, etc
76
	one = one.original();
77
	two = one.findOriginalInheritedMethod(two);
78
79
	if (two == null)
80
		return false; // method's declaringClass does not inherit from inheritedMethod's
81
82
	return isParameterSubsignature(one, two, localEnvironment);
72
}
83
}
84
85
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
86
	return areMethodsCompatible(one, two, this.environment);
87
}
88
73
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
89
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
74
	if (one.returnType == two.returnType) return true;
90
	if (one.returnType == two.returnType) return true;
75
91
76
	if (areTypesEqual(one.returnType, two.returnType)) return true;
92
	if (areTypesEqual(one.returnType, two.returnType)) return true;
77
93
Lines 465-554 Link Here
465
					compare concrete's exceptions against each abstract method
481
					compare concrete's exceptions against each abstract method
466
				else
482
				else
467
					complain about missing implementation only if type is NOT an interface or abstract
483
					complain about missing implementation only if type is NOT an interface or abstract
468
*/
484
*/
469
abstract void checkMethods();
485
abstract void checkMethods();
470
private void _unusedCheckMethods() {
471
	boolean mustImplementAbstractMethods = mustImplementAbstractMethods();
472
	boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); // have a single concrete superclass so only check overridden methods
473
	boolean isOrEnclosedByPrivateType = this.type.isOrEnclosedByPrivateType();
474
	char[][] methodSelectors = this.inheritedMethods.keyTable;
475
	nextSelector : for (int s = methodSelectors.length; --s >= 0;) {
476
		if (methodSelectors[s] == null) continue nextSelector;
477
478
		MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
479
		MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
480
		
481
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
482
		// inherited methods of super classes are too. current != null case handled below.
483
		if (current == null && !isOrEnclosedByPrivateType) {
484
			int length = inherited.length;
485
			for (int i = 0; i < length; i++){
486
				inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
487
			}
488
		}
489
490
		if (current == null && skipInheritedMethods)
491
			continue nextSelector;
492
493
		if (inherited.length == 1 && current == null) { // handle the common case
494
			if (mustImplementAbstractMethods && inherited[0].isAbstract())
495
				checkAbstractMethod(inherited[0]);
496
			continue nextSelector;
497
		}
498
499
		int index = -1;
500
		MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
501
		if (current != null) {
502
			for (int i = 0, length1 = current.length; i < length1; i++) {
503
				MethodBinding currentMethod = current[i];
504
				for (int j = 0, length2 = inherited.length; j < length2; j++) {
505
					MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod);
506
					if (inheritedMethod != null) {
507
						if (isParameterSubsignature(currentMethod, inheritedMethod)) {
508
							matchingInherited[++index] = inheritedMethod;
509
							inherited[j] = null; // do not want to find it again
510
						}
511
					}
512
				}
513
				if (index >= 0) {
514
					checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1, inherited); // pass in the length of matching
515
					while (index >= 0) matchingInherited[index--] = null; // clear the contents of the matching methods
516
				}
517
			}
518
		}
519
520
		for (int i = 0, length = inherited.length; i < length; i++) {
521
			MethodBinding inheritedMethod = inherited[i];
522
			if (inheritedMethod == null) continue;
523
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed,
524
			// inherited methods of super classes are too. current == null case handled already.
525
			if (!isOrEnclosedByPrivateType && current != null) {
526
				inheritedMethod.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
527
			}
528
			matchingInherited[++index] = inheritedMethod;
529
			for (int j = i + 1; j < length; j++) {
530
				MethodBinding otherInheritedMethod = inherited[j];
531
				if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod))
532
					continue;
533
				otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
534
				if (otherInheritedMethod != null) {
535
					if (isParameterSubsignature(inheritedMethod, otherInheritedMethod)) {
536
						matchingInherited[++index] = otherInheritedMethod;
537
						inherited[j] = null; // do not want to find it again
538
					}
539
				}
540
			}
541
			if (index == -1) continue;
542
			if (index > 0)
543
				checkInheritedMethods(matchingInherited, index + 1, null/*FIXME: required value not provided*/); // pass in the length of matching
544
			else if (mustImplementAbstractMethods && matchingInherited[0].isAbstract())
545
				checkAbstractMethod(matchingInherited[0]);
546
			while (index >= 0) matchingInherited[index--] = null; // clear the contents of the matching methods
547
		}
548
	}
549
}
550
486
551
void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
487
void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
552
	// check that the inherited abstract method (package private visibility) is implemented within the same package
488
	// check that the inherited abstract method (package private visibility) is implemented within the same package
553
	PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage;
489
	PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage;
554
	if (necessaryPackage == this.type.fPackage) return; // not a problem
490
	if (necessaryPackage == this.type.fPackage) return; // not a problem
Lines 755-766 Link Here
755
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
691
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
756
	if (inheritedMethod == null) return null;
692
	if (inheritedMethod == null) return null;
757
	if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match
693
	if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match
758
	return inheritedMethod;
694
	return inheritedMethod;
759
}
695
}
696
static MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod, LookupEnvironment localEnvironment) {
697
	if (inheritedMethod == null) return null;
698
	if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match
760
699
761
boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
700
	// due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved
701
	if (currentMethod.declaringClass instanceof BinaryTypeBinding)
702
		((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod);
703
	if (inheritedMethod.declaringClass instanceof BinaryTypeBinding)
704
		((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod);
705
706
	TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables;
707
	int inheritedLength = inheritedTypeVariables.length;
708
	if (inheritedLength == 0) return inheritedMethod; // no substitution needed
709
	TypeVariableBinding[] typeVariables = currentMethod.typeVariables;
710
	int length = typeVariables.length;
711
	if (length == 0)
712
		return inheritedMethod.asRawMethod(localEnvironment);
713
	if (length != inheritedLength)
714
		return inheritedMethod; // no match JLS 8.4.2
715
716
	// interface I { <T> void foo(T t); }
717
	// class X implements I { public <T extends I> void foo(T t) {} }
718
	// for the above case, we do not want to answer the substitute method since its not a match
719
	TypeBinding[] arguments = new TypeBinding[length];
720
	System.arraycopy(typeVariables, 0, arguments, 0, length);
721
	ParameterizedGenericMethodBinding substitute =
722
		localEnvironment.createParameterizedGenericMethod(inheritedMethod, arguments);
723
	for (int i = 0; i < inheritedLength; i++) {
724
		TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i];
725
		TypeBinding argument = arguments[i];
726
		if (argument instanceof TypeVariableBinding) {
727
			TypeVariableBinding typeVariable = (TypeVariableBinding) argument;
728
			if (typeVariable.firstBound == inheritedTypeVariable.firstBound) {
729
				if (typeVariable.firstBound == null)
730
					continue; // both are null
731
			} else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) {
732
				if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass())
733
					return inheritedMethod; // not a match
734
			}
735
			if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass)
736
				return inheritedMethod; // not a match
737
			int interfaceLength = inheritedTypeVariable.superInterfaces.length;
738
			ReferenceBinding[] interfaces = typeVariable.superInterfaces;
739
			if (interfaceLength != interfaces.length)
740
				return inheritedMethod; // not a match
741
			next : for (int j = 0; j < interfaceLength; j++) {
742
				TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]);
743
				for (int k = 0; k < interfaceLength; k++)
744
					if (superType == interfaces[k])
745
						continue next;
746
				return inheritedMethod; // not a match
747
			}
748
		} else if (inheritedTypeVariable.boundCheck(substitute, argument) != TypeConstants.OK) {
749
	    	return inheritedMethod;
750
		}
751
	}
752
   return substitute;
753
}
754
static boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
762
	if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector))
755
	if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector))
763
		return false;
756
		return false;
764
	if (method == inheritedMethod || method.isStatic() || inheritedMethod.isStatic())
757
	if (method == inheritedMethod || method.isStatic() || inheritedMethod.isStatic())
765
		return false;
758
		return false;
766
	if (inheritedMethod.isPrivate())
759
	if (inheritedMethod.isPrivate())
Lines 774-796 Link Here
774
			return false;
767
			return false;
775
	}
768
	}
776
	return true;
769
	return true;
777
}
770
}
778
771
779
// Answer whether the method overrides the inheritedMethod
772
780
// Check the necessary visibility rules & inheritance from the inheritedMethod's declaringClass
773
public static boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod, LookupEnvironment localEnvironment) {
781
// See isMethodSubsignature() for parameter comparisons
774
	return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod, localEnvironment);
775
}
776
782
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
777
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
783
	if (!couldMethodOverride(method, inheritedMethod))
778
	return doesMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod, this.environment);
784
		return false;
785
786
	inheritedMethod = inheritedMethod.original();
787
	TypeBinding match = method.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass);
788
	if (!(match instanceof ReferenceBinding))
789
		return false; // method's declaringClass does not inherit from inheritedMethod's
790
791
	return isParameterSubsignature(method, inheritedMethod);
792
}
779
}
793
780
794
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
781
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
795
	return null; // noop in 1.4
782
	return null; // noop in 1.4
796
}
783
}
Lines 881-896 Link Here
881
	return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true);
868
	return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true);
882
}
869
}
883
870
884
public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
871
public boolean isMethodSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
885
	return org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)
872
	return org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)
886
		&& isParameterSubsignature(method, inheritedMethod);
873
		&& isParameterSubsignature(method, inheritedMethod, this.environment);
887
}
874
}
888
875
static boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod, LookupEnvironment localEnvironment) {
889
boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
876
	MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method, localEnvironment);
890
	return areParametersEqual(method, inheritedMethod);
877
	return substitute != null && isSubstituteParameterSubsignature(method, substitute, localEnvironment);
891
}
878
}
879
//boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
880
//	return areParametersEqual(method, inheritedMethod);
881
//}
892
882
893
boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
883
boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
894
	do {
884
	do {
895
		if (testClass == superclass) return true;
885
		if (testClass == superclass) return true;
896
	} while ((testClass = testClass.superclass()) != null);
886
	} while ((testClass = testClass.superclass()) != null);
Lines 986-991 Link Here
986
	buffer.append('\n');
976
	buffer.append('\n');
987
	buffer.append("\t-inherited methods: "); //$NON-NLS-1$
977
	buffer.append("\t-inherited methods: "); //$NON-NLS-1$
988
	buffer.append(this.inheritedMethods);
978
	buffer.append(this.inheritedMethods);
989
	return buffer.toString();
979
	return buffer.toString();
990
}
980
}
981
982
protected static boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod, LookupEnvironment environment) {
983
	if (!areParametersEqual(method, substituteMethod)) {
984
		// method can still override substituteMethod in cases like :
985
		// <U extends Number> void c(U u) {}
986
		// @Override void c(Number n) {}
987
		// but method cannot have a "generic-enabled" parameter type
988
		if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod))
989
			return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method);
990
991
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836
992
		if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType())
993
			if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters())
994
				return areMethodsCompatible(method, substituteMethod, environment);
995
996
		return false;
997
	}
998
999
	if (substituteMethod instanceof ParameterizedGenericMethodBinding) {
1000
		if (method.typeVariables != Binding.NO_TYPE_VARIABLES)
1001
			return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw;
1002
		// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does
1003
		return !hasGenericParameter(method);
1004
	}
1005
1006
	// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod()
1007
	return method.typeVariables == Binding.NO_TYPE_VARIABLES;
1008
}
1009
1010
protected boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) {
1011
	return isSubstituteParameterSubsignature(method, substituteMethod, this.environment);
1012
}
1013
1014
static boolean hasGenericParameter(MethodBinding method) {
1015
	if (method.genericSignature() == null) return false;
1016
1017
	// may be only the return type that is generic, need to check parameters
1018
	TypeBinding[] params = method.parameters;
1019
	for (int i = 0, l = params.length; i < l; i++) {
1020
		TypeBinding param = params[i].leafComponentType();
1021
		if (param instanceof ReferenceBinding) {
1022
			int modifiers = ((ReferenceBinding) param).modifiers;
1023
			if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1024
				return true;
1025
		}
1026
	}
1027
	return false;
1028
}
991
}
1029
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java (-118 / +5 lines)
Lines 38-57 Link Here
38
class MethodVerifier15 extends MethodVerifier {
38
class MethodVerifier15 extends MethodVerifier {
39
39
40
MethodVerifier15(LookupEnvironment environment) {
40
MethodVerifier15(LookupEnvironment environment) {
41
	super(environment);
41
	super(environment);
42
}
42
}
43
boolean areMethodsCompatible(MethodBinding one, MethodBinding two) {
44
	// use the original methods to test compatibility, but do not check visibility, etc
45
	one = one.original();
46
	two = one.findOriginalInheritedMethod(two);
47
43
48
	if (two == null)
49
		return false; // method's declaringClass does not inherit from inheritedMethod's
50
51
	return isParameterSubsignature(one, two);
52
}
53
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
44
boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) {
54
	if (one.returnType == two.returnType) return true;
45
	if (one.returnType == two.returnType) return true;
55
	if (this.type.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
46
	if (this.type.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
56
		return areReturnTypesCompatible0(one, two);
47
		return areReturnTypesCompatible0(one, two);
57
	} else {
48
	} else {
Lines 598-608 Link Here
598
			skip[idx] = true;
589
			skip[idx] = true;
599
			isOverridden[idx] = true;
590
			isOverridden[idx] = true;
600
			return true;
591
			return true;
601
		}
592
		}
602
	} else if (specificIsInterface == generalIsInterface) { 
593
	} else if (specificIsInterface == generalIsInterface) { 
603
		if (isParameterSubsignature(specific, general)) {
594
		if (isParameterSubsignature(specific, general, this.environment)) {
604
			skip[idx] = true;
595
			skip[idx] = true;
605
			isOverridden[idx] = specific.declaringClass.isCompatibleWith(general.declaringClass);
596
			isOverridden[idx] = specific.declaringClass.isCompatibleWith(general.declaringClass);
606
			return true;
597
			return true;
607
		}
598
		}
608
	}
599
	}
Lines 680-746 Link Here
680
			}
671
			}
681
		}
672
		}
682
	}
673
	}
683
}
674
}
684
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
675
MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
685
	if (inheritedMethod == null) return null;
676
	return computeSubstituteMethod(inheritedMethod, currentMethod, this.environment);
686
	if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match
687
688
	// due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved
689
	if (currentMethod.declaringClass instanceof BinaryTypeBinding)
690
		((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod);
691
	if (inheritedMethod.declaringClass instanceof BinaryTypeBinding)
692
		((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod);
693
694
	TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables;
695
	int inheritedLength = inheritedTypeVariables.length;
696
	if (inheritedLength == 0) return inheritedMethod; // no substitution needed
697
	TypeVariableBinding[] typeVariables = currentMethod.typeVariables;
698
	int length = typeVariables.length;
699
	if (length == 0)
700
		return inheritedMethod.asRawMethod(this.environment);
701
	if (length != inheritedLength)
702
		return inheritedMethod; // no match JLS 8.4.2
703
704
	// interface I { <T> void foo(T t); }
705
	// class X implements I { public <T extends I> void foo(T t) {} }
706
	// for the above case, we do not want to answer the substitute method since its not a match
707
	TypeBinding[] arguments = new TypeBinding[length];
708
	System.arraycopy(typeVariables, 0, arguments, 0, length);
709
	ParameterizedGenericMethodBinding substitute =
710
		this.environment.createParameterizedGenericMethod(inheritedMethod, arguments);
711
	for (int i = 0; i < inheritedLength; i++) {
712
		TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i];
713
		TypeBinding argument = arguments[i];
714
		if (argument instanceof TypeVariableBinding) {
715
			TypeVariableBinding typeVariable = (TypeVariableBinding) argument;
716
			if (typeVariable.firstBound == inheritedTypeVariable.firstBound) {
717
				if (typeVariable.firstBound == null)
718
					continue; // both are null
719
			} else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) {
720
				if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass())
721
					return inheritedMethod; // not a match
722
			}
723
			if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass)
724
				return inheritedMethod; // not a match
725
			int interfaceLength = inheritedTypeVariable.superInterfaces.length;
726
			ReferenceBinding[] interfaces = typeVariable.superInterfaces;
727
			if (interfaceLength != interfaces.length)
728
				return inheritedMethod; // not a match
729
			next : for (int j = 0; j < interfaceLength; j++) {
730
				TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]);
731
				for (int k = 0; k < interfaceLength; k++)
732
					if (superType == interfaces[k])
733
						continue next;
734
				return inheritedMethod; // not a match
735
			}
736
		} else if (inheritedTypeVariable.boundCheck(substitute, argument) != TypeConstants.OK) {
737
	    	return inheritedMethod;
738
		}
739
	}
740
   return substitute;
741
}
677
}
678
742
boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) {
679
boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) {
743
	if (!inherited.areParameterErasuresEqual(otherInherited))
680
	if (!inherited.areParameterErasuresEqual(otherInherited))
744
		return false;
681
		return false;
745
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=322001
682
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=322001
746
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=323693
683
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=323693
Lines 797-809 Link Here
797
	original = inherited.original();  // For error reporting use, inherited.original()
734
	original = inherited.original();  // For error reporting use, inherited.original()
798
	problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original, severity);
735
	problemReporter(current).methodNameClash(current, inherited.declaringClass.isRawType() ? inherited : original, severity);
799
	if (severity == ProblemSeverities.Warning) return false;
736
	if (severity == ProblemSeverities.Warning) return false;
800
	return true;
737
	return true;
801
}
738
}
802
public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
739
803
	return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod);
804
}
805
boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
740
boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
806
	// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod()
741
	// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod()
807
	return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
742
	return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
808
}
743
}
809
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
744
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
Lines 873-897 Link Here
873
			}
808
			}
874
		}
809
		}
875
	}
810
	}
876
	return copy;
811
	return copy;
877
}
812
}
878
boolean hasGenericParameter(MethodBinding method) {
879
	if (method.genericSignature() == null) return false;
880
881
	// may be only the return type that is generic, need to check parameters
882
	TypeBinding[] params = method.parameters;
883
	for (int i = 0, l = params.length; i < l; i++) {
884
		TypeBinding param = params[i].leafComponentType();
885
		if (param instanceof ReferenceBinding) {
886
			int modifiers = ((ReferenceBinding) param).modifiers;
887
			if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
888
				return true;
889
		}
890
	}
891
	return false;
892
}
893
boolean isAcceptableReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
813
boolean isAcceptableReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
894
	// called when currentMethod's return type is compatible with inheritedMethod's return type
814
	// called when currentMethod's return type is compatible with inheritedMethod's return type
895
815
896
	if (inheritedMethod.declaringClass.isRawType())
816
	if (inheritedMethod.declaringClass.isRawType())
897
		return true; // since the inheritedMethod comes from a raw type, the return type is always acceptable
817
		return true; // since the inheritedMethod comes from a raw type, the return type is always acceptable
Lines 931-974 Link Here
931
	// need to switch back to the original if the method is from a ParameterizedType
851
	// need to switch back to the original if the method is from a ParameterizedType
932
	if (method.declaringClass.isParameterizedType())
852
	if (method.declaringClass.isParameterizedType())
933
		method = method.original();
853
		method = method.original();
934
854
935
	MethodBinding inheritedOriginal = method.findOriginalInheritedMethod(inheritedMethod);
855
	MethodBinding inheritedOriginal = method.findOriginalInheritedMethod(inheritedMethod);
936
	return isParameterSubsignature(method, inheritedOriginal == null ? inheritedMethod : inheritedOriginal);
856
	return isParameterSubsignature(method, inheritedOriginal == null ? inheritedMethod : inheritedOriginal, this.environment);
937
}
938
boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) {
939
	MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method);
940
	return substitute != null && isSubstituteParameterSubsignature(method, substitute);
941
}
942
// if method "overrides" substituteMethod then we can skip over substituteMethod while resolving a message send
943
// if it does not then a name clash error is likely
944
boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) {
945
	if (!areParametersEqual(method, substituteMethod)) {
946
		// method can still override substituteMethod in cases like :
947
		// <U extends Number> void c(U u) {}
948
		// @Override void c(Number n) {}
949
		// but method cannot have a "generic-enabled" parameter type
950
		if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod))
951
			return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method);
952
953
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836
954
		if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType())
955
			if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters())
956
				return areMethodsCompatible(method, substituteMethod);
957
958
		return false;
959
	}
960
961
	if (substituteMethod instanceof ParameterizedGenericMethodBinding) {
962
		if (method.typeVariables != Binding.NO_TYPE_VARIABLES)
963
			return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw;
964
		// since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does
965
		return !hasGenericParameter(method);
966
	}
967
968
	// if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod()
969
	return method.typeVariables == Binding.NO_TYPE_VARIABLES;
970
}
857
}
971
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
858
boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) {
972
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
859
	// called when currentMethod's return type is NOT compatible with inheritedMethod's return type
973
860
974
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
861
	// JLS 3 �8.4.5: more are accepted, with an unchecked conversion
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java (+1 lines)
Lines 26-31 Link Here
26
	final int ParameterizedMethodTypeMismatch = 12; // for generic method
26
	final int ParameterizedMethodTypeMismatch = 12; // for generic method
27
	final int TypeArgumentsForRawGenericMethod = 13; // for generic method
27
	final int TypeArgumentsForRawGenericMethod = 13; // for generic method
28
	final int InvalidTypeForStaticImport = 14;
28
	final int InvalidTypeForStaticImport = 14;
29
	final int InvalidTypeForAutoManagedResource = 15;
29
	final int InvalidTypeForAutoManagedResource = 15;
30
	final int VarargsElementTypeNotVisible = 16;
30
	final int VarargsElementTypeNotVisible = 16;
31
	final int NoSuchSingleAbstractMethod = 17;
31
}
32
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (+14 lines)
Lines 1572-1577 Link Here
1572
		if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i]))
1572
		if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i]))
1573
			return TypeIds.BitWrapperCloseable;
1573
			return TypeIds.BitWrapperCloseable;
1574
	}	
1574
	}	
1575
	return 0;
1575
	return 0;
1576
}
1576
}
1577
1578
public MethodBinding getSingleAbstractMethod() {
1579
	if (this.isInterface()) {
1580
		MethodBinding [] methodArray = methods();
1581
		if(methodArray != null && methodArray.length == 1){
1582
			return methodArray[0];
1583
		}
1584
		else
1585
			return new ProblemMethodBinding(CharOperation.NO_CHAR, null, ProblemReasons.NoSuchSingleAbstractMethod);
1586
	}
1587
	else 
1588
		return null;
1589
1590
}
1577
}
1591
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java (-2 / +2 lines)
Lines 1369-1379 Link Here
1369
						// BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
1369
						// BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
1370
						for (int j = 0, max = found.size; j < max; j++) {
1370
						for (int j = 0, max = found.size; j < max; j++) {
1371
							MethodBinding matchingMethod = (MethodBinding) found.elementAt(j);
1371
							MethodBinding matchingMethod = (MethodBinding) found.elementAt(j);
1372
							MethodBinding matchingOriginal = matchingMethod.original();
1372
							MethodBinding matchingOriginal = matchingMethod.original();
1373
							MethodBinding currentOriginal = matchingOriginal.findOriginalInheritedMethod(currentMethod);
1373
							MethodBinding currentOriginal = matchingOriginal.findOriginalInheritedMethod(currentMethod);
1374
							if (currentOriginal != null && verifier.isParameterSubsignature(matchingOriginal, currentOriginal)) {
1374
							if (currentOriginal != null && verifier.isParameterSubsignature(matchingOriginal, currentOriginal, this.environment())) {
1375
								if (isCompliant15) {
1375
								if (isCompliant15) {
1376
									if (matchingMethod.isBridge() && !currentMethod.isBridge())
1376
									if (matchingMethod.isBridge() && !currentMethod.isBridge())
1377
										continue nextMethod; // keep inherited methods to find concrete method over a bridge method
1377
										continue nextMethod; // keep inherited methods to find concrete method over a bridge method
1378
								}
1378
								}
1379
								currentLength--;
1379
								currentLength--;
Lines 3944-3954 Link Here
3944
3944
3945
						original2 = original.findOriginalInheritedMethod(original2);
3945
						original2 = original.findOriginalInheritedMethod(original2);
3946
						if (original2 == null)
3946
						if (original2 == null)
3947
							continue nextSpecific; // current's declaringClass is not a subtype of next's declaringClass
3947
							continue nextSpecific; // current's declaringClass is not a subtype of next's declaringClass
3948
						if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) {
3948
						if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) {
3949
							if (!environment().methodVerifier().isParameterSubsignature(original, original2))
3949
							if (!environment().methodVerifier().isParameterSubsignature(original, original2, environment()))
3950
								continue nextSpecific; // current does not override next
3950
								continue nextSpecific; // current does not override next
3951
						}
3951
						}
3952
					} else if (receiverType != null) { // should not be null if original isAbstract, but be safe
3952
					} else if (receiverType != null) { // should not be null if original isAbstract, but be safe
3953
						TypeBinding superType = receiverType.findSuperTypeOriginatingFrom(original.declaringClass.erasure());
3953
						TypeBinding superType = receiverType.findSuperTypeOriginatingFrom(original.declaringClass.erasure());
3954
						if (original.declaringClass == superType || !(superType instanceof ReferenceBinding)) {
3954
						if (original.declaringClass == superType || !(superType instanceof ReferenceBinding)) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java (+4 lines)
Lines 1223-1228 Link Here
1223
}
1223
}
1224
1224
1225
public TypeVariableBinding[] typeVariables() {
1225
public TypeVariableBinding[] typeVariables() {
1226
	return Binding.NO_TYPE_VARIABLES;
1226
	return Binding.NO_TYPE_VARIABLES;
1227
}
1227
}
1228
1229
public MethodBinding getSingleAbstractMethod() {
1230
	return null;
1231
}
1228
}
1232
}

Return to bug 399263