### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java,v retrieving revision 1.83 diff -u -r1.83 ParameterizedTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 22 Apr 2006 17:45:41 -0000 1.83 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 23 Jun 2006 23:18:58 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; @@ -120,7 +119,7 @@ * A = F corresponds to: F.collectSubstitutes(..., A, ..., 0) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., 2) */ - public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) { + public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; if (actualType == TypeBinding.NULL) return; @@ -144,7 +143,7 @@ // collect through enclosing type ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType(); if (formalEnclosingType != null) { - formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), substitutes, constraint); + formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), inferenceContext, constraint); } // collect through type arguments if (this.arguments == null) return; @@ -157,7 +156,9 @@ formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments; break; case Binding.RAW_TYPE : - substitutes.clear(); // clear all variables to indicate raw generic method in the end + if (!inferenceContext.checkRawSubstitution()) { + inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference + } return; default : return; @@ -171,19 +172,19 @@ actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments; break; case Binding.RAW_TYPE : - substitutes.clear(); // clear all variables to indicate raw generic method in the end - if (constraint == TypeConstants.CONSTRAINT_EQUAL) { - substitutes.put(TypeBinding.VOID, Binding.NO_TYPES); // marker for impossible inference + if (!inferenceContext.checkRawSubstitution()) { + inferenceContext.status = InferenceContext.FAILED; // marker for impossible inference } return; default : return; } + inferenceContext.depth++; for (int i = 0, length = formalArguments.length; i < length; i++) { TypeBinding formalArgument = formalArguments[i]; TypeBinding actualArgument = actualArguments[i]; if (formalArgument.isWildcard()) { - formalArgument.collectSubstitutes(scope, actualArgument, substitutes, constraint); + formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, constraint); continue; } else if (actualArgument.isWildcard()){ WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument; @@ -191,10 +192,10 @@ if (constraint == TypeConstants.CONSTRAINT_SUPER) { // JLS 15.12.7, p.459 switch(actualWildcardArgument.boundKind) { case Wildcard.EXTENDS : - formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, substitutes, TypeConstants.CONSTRAINT_SUPER); + formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); continue; case Wildcard.SUPER : - formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, substitutes, TypeConstants.CONSTRAINT_EXTENDS); + formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); continue; default : continue; // cannot infer anything further from unbound wildcard @@ -205,8 +206,9 @@ } } // by default, use EQUAL constraint - formalArgument.collectSubstitutes(scope, actualArgument, substitutes, TypeConstants.CONSTRAINT_EQUAL); + formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } + inferenceContext.depth--; } /** Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java,v retrieving revision 1.21 diff -u -r1.21 ParameterizedMethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java 19 Jun 2006 14:12:43 -0000 1.21 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java 23 Jun 2006 23:18:57 -0000 @@ -85,12 +85,12 @@ } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : - substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(JAVA_LANG_OBJECT, null); + substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); substitutedVariable.superInterfaces = substitutedInterfaces; break; default: if (substitutedSuperclass.isInterface()) { - substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(JAVA_LANG_OBJECT, null); + substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; @@ -174,12 +174,12 @@ } switch (substitutedSuperclass.kind()) { case Binding.ARRAY_TYPE : - substitutedVariable.superclass = environment.getResolvedType(JAVA_LANG_OBJECT, null); + substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); substitutedVariable.superInterfaces = substitutedInterfaces; break; default: if (substitutedSuperclass.isInterface()) { - substitutedVariable.superclass = environment.getResolvedType(JAVA_LANG_OBJECT, null); + substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null); int interfaceCount = substitutedInterfaces.length; System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount); substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java,v retrieving revision 1.82 diff -u -r1.82 MethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 14 Apr 2006 08:34:05 -0000 1.82 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 23 Jun 2006 23:18:56 -0000 @@ -17,7 +17,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; -public class MethodBinding extends Binding implements TypeConstants { +public class MethodBinding extends Binding { public int modifiers; public char[] selector; @@ -537,7 +537,7 @@ * Answer true if the receiver is a "public static void main(String[])" method */ public final boolean isMain() { - if (this.selector.length == 4 && CharOperation.equals(this.selector, MAIN) + if (this.selector.length == 4 && CharOperation.equals(this.selector, TypeConstants.MAIN) && ((this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0) && TypeBinding.VOID == this.returnType && this.parameters.length == 1) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java,v retrieving revision 1.48 diff -u -r1.48 ParameterizedGenericMethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java 14 Apr 2006 08:34:05 -0000 1.48 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java 23 Jun 2006 23:18:57 -0000 @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.HashMap; -import java.util.Map; import org.eclipse.jdt.internal.compiler.ast.MessageSend; /** @@ -28,7 +26,7 @@ public boolean wasInferred; // only set to true for instances resulting from method invocation inferrence public boolean isRaw; // set to true for method behaving as raw for substitution purpose private MethodBinding tiebreakMethod; - public boolean isUnchecked; // indicates whether inferred arguments used unchecked conversion during bound check or was raw + public boolean isUnchecked; // transient flag set during inference (warning: bindings are shared, so flag cannot be trusted beyond) /** * Perform inference of generic method type parameters and/or expected type @@ -54,19 +52,14 @@ // initializes the map of substitutes (var --> type[][]{ equal, extends, super} TypeBinding[] parameters = originalMethod.parameters; - int varLength = typeVariables.length; - Map collectedSubstitutes = new HashMap(varLength); - for (int i = 0; i < varLength; i++) - collectedSubstitutes.put(typeVariables[i], new TypeBinding[3][]); - - substitutes = new TypeBinding[varLength]; - methodSubstitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, collectedSubstitutes, substitutes); + InferenceContext inferenceContext = new InferenceContext(originalMethod); + methodSubstitute = inferFromArgumentTypes(scope, originalMethod, arguments, parameters, inferenceContext); if (methodSubstitute == null) return null; // substitutes may hold null to denote unresolved vars, but null arguments got replaced with respective original variable in param method // 15.12.2.8 - inferring unresolved type arguments - if (hasUnresolvedTypeArgument(substitutes)) { + if (inferenceContext.hasUnresolvedTypeArgument()) { TypeBinding expectedType = null; if (methodSubstitute.returnType != TypeBinding.VOID) { // if message invocation has expected type @@ -76,7 +69,7 @@ } if (expectedType == null) expectedType = scope.getJavaLangObject(); // assume Object by default } - methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, collectedSubstitutes, substitutes); + methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, inferenceContext); if (methodSubstitute == null) return null; } @@ -103,26 +96,13 @@ } } } - return methodSubstitute; } /** - * Returns true if any unresolved variable is detected, i.e. any variable is substituted with itself - */ - private static boolean hasUnresolvedTypeArgument(TypeBinding[] substitutes) { - for (int i = 0, varLength = substitutes.length; i :U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously - TypeBinding[][] variableSubstitutes = (TypeBinding[][]) collectedSubstitutes.get(current); - TypeBinding [] bounds = variableSubstitutes[CONSTRAINT_SUPER]; + TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_SUPER); if (bounds == null) continue nextTypeParameter; TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds); - if (mostSpecificSubstitute == null) - return null; // incompatible + if (mostSpecificSubstitute == null) { + return false; // incompatible + } if (mostSpecificSubstitute != TypeBinding.VOID) { substitutes[i] = mostSpecificSubstitute; } } } - if (considerEXTENDSConstraints && hasUnresolvedTypeArgument(substitutes)) { + if (considerEXTENDSConstraints && inferenceContext.hasUnresolvedTypeArgument()) { // check Tj<:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously - TypeBinding[][] variableSubstitutes = (TypeBinding[][]) collectedSubstitutes.get(current); - TypeBinding [] bounds = variableSubstitutes[CONSTRAINT_EXTENDS]; + TypeBinding [] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS); if (bounds == null) continue nextTypeParameter; TypeBinding[] glb = Scope.greaterLowerBound(bounds); TypeBinding mostSpecificSubstitute = null; @@ -271,7 +250,7 @@ } } } - return substitutes; + return true; } /** @@ -288,7 +267,6 @@ } this.isRaw = true; this.tagBits = originalMethod.tagBits; - this.isUnchecked = false; this.environment = environment; this.modifiers = originalMethod.modifiers; this.selector = originalMethod.selector; @@ -322,7 +300,6 @@ this.typeArguments = typeArguments; this.isRaw = false; this.tagBits = originalMethod.tagBits; - this.isUnchecked = false; this.originalMethod = originalMethod; this.parameters = Scope.substitute(this, originalMethod.parameters); this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions); @@ -383,15 +360,15 @@ * Given some type expectation, and type variable bounds, perform some inference. * Returns true if still had unresolved type variable at the end of the operation */ - private ParameterizedGenericMethodBinding inferFromExpectedType(Scope scope, TypeBinding expectedType, Map collectedSubstitutes, TypeBinding[] substitutes) { + private ParameterizedGenericMethodBinding inferFromExpectedType(Scope scope, TypeBinding expectedType, InferenceContext inferenceContext) { TypeVariableBinding[] originalVariables = this.originalMethod.typeVariables; // immediate parent (could be a parameterized method) int varLength = originalVariables.length; computeSubstitutes: { // infer from expected return type if (expectedType != null) { - this.returnType.collectSubstitutes(scope, expectedType, collectedSubstitutes, CONSTRAINT_SUPER); - if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution + this.returnType.collectSubstitutes(scope, expectedType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); + if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } // infer from bounds of type parameters for (int i = 0; i < varLength; i++) { @@ -400,31 +377,28 @@ boolean argAlreadyInferred = argument != originalVariable; if (originalVariable.firstBound == originalVariable.superclass) { TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass); - argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER); - if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution + argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); + if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution // JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference // e.g. given: > S test1(S param) // invocation: test1(new Vector()) will infer: S=Vector and with code below: E=String if (argAlreadyInferred) { - substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); - if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution + substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); + if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) { TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]); - argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER); - if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution + argument.collectSubstitutes(scope, substitutedBound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); + if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution // JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference if (argAlreadyInferred) { - substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); - if (collectedSubstitutes.get(TypeBinding.VOID) != null) return null; // impossible substitution + substitutedBound.collectSubstitutes(scope, argument, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); + if (inferenceContext.status == InferenceContext.FAILED) return null; // impossible substitution } } } - substitutes = resolveSubstituteConstraints(scope, originalVariables, substitutes, true/*consider Ti<:Uk*/, collectedSubstitutes); - if (substitutes == null) - return null; // incompatible - if (substitutes.length == 0) { + if (inferenceContext.status == InferenceContext.RAW_SUBSTITUTION) { // raw generic method inferred this.isRaw = true; this.isUnchecked = false; @@ -432,12 +406,14 @@ this.typeArguments[i] = originalVariables[i].upperBound(); } break computeSubstitutes; - } + } + if (!resolveSubstituteConstraints(scope, originalVariables, inferenceContext, true/*consider Ti<:Uk*/)) + return null; // incompatible // this.typeArguments = substitutes; - no op since side effects got performed during #resolveSubstituteConstraints for (int i = 0; i < varLength; i++) { - TypeBinding substitute = substitutes[i]; + TypeBinding substitute = inferenceContext.substitutes[i]; if (substitute != null) { - this.typeArguments[i] = substitutes[i]; + this.typeArguments[i] = inferenceContext.substitutes[i]; } else { // remaining unresolved variable are considered to be Object (or their bound actually) this.typeArguments[i] = originalVariables[i].upperBound(); Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java,v retrieving revision 1.51 diff -u -r1.51 ArrayBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java 20 Apr 2006 07:29:03 -0000 1.51 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java 23 Jun 2006 23:18:55 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.Constant; @@ -45,7 +44,7 @@ * A = F corresponds to: F.collectSubstitutes(..., A, ..., 0) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., 2) */ -public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) { +public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; if (actualType == TypeBinding.NULL) return; @@ -54,10 +53,10 @@ case Binding.ARRAY_TYPE : int actualDim = actualType.dimensions(); if (actualDim == this.dimensions) { - this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), substitutes, constraint); + this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), inferenceContext, constraint); } else if (actualDim > this.dimensions) { ArrayBinding actualReducedType = this.environment.createArrayType(actualType.leafComponentType(), actualDim - this.dimensions); - this.leafComponentType.collectSubstitutes(scope, actualReducedType, substitutes, constraint); + this.leafComponentType.collectSubstitutes(scope, actualReducedType, inferenceContext, constraint); } break; case Binding.TYPE_PARAMETER : Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java,v retrieving revision 1.74 diff -u -r1.74 TypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 9 Jun 2006 10:20:47 -0000 1.74 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 23 Jun 2006 23:18:59 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Wildcard; @@ -112,8 +111,7 @@ * A = F corresponds to: F.collectSubstitutes(..., A, ..., 0) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., 2) */ -public void collectSubstitutes(Scope scope, TypeBinding actualType, - Map substitutes, int constraint) { +public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { // no substitute by default } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java,v retrieving revision 1.53 diff -u -r1.53 TypeVariableBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 9 Jun 2006 10:19:26 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 23 Jun 2006 23:18:59 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -165,7 +164,7 @@ * A = F corresponds to: F.collectSubstitutes(..., A, ..., 0) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., 2) */ - public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) { + public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { // cannot infer anything from a null type switch (actualType.kind()) { @@ -195,31 +194,7 @@ variableConstraint =TypeConstants.CONSTRAINT_EXTENDS; break; } - TypeBinding[][] variableSubstitutes = (TypeBinding[][])substitutes.get(this); - if (variableSubstitutes != null) { - insertLoop: { - TypeBinding[] constraintSubstitutes = variableSubstitutes[variableConstraint]; - int length; - if (constraintSubstitutes == null) { - length = 0; - constraintSubstitutes = new TypeBinding[1]; - } else { - length = constraintSubstitutes.length; - for (int i = 0; i < length; i++) { - TypeBinding substitute = constraintSubstitutes[i]; - if (substitute == actualType) return; // already there - if (substitute == null) { - constraintSubstitutes[i] = actualType; - break insertLoop; - } - } - // no free spot found, need to grow by one - System.arraycopy(constraintSubstitutes, 0, constraintSubstitutes = new TypeBinding[length+1], 0, length); - } - constraintSubstitutes[length] = actualType; - variableSubstitutes[variableConstraint] = constraintSubstitutes; - } - } + inferenceContext.recordSubstitute(this, actualType, variableConstraint); } public char[] constantPoolName() { /* java/lang/Object */ Index: compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java,v retrieving revision 1.53 diff -u -r1.53 WildcardBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java 8 Jun 2006 13:08:56 -0000 1.53 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java 23 Jun 2006 23:18:59 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; -import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -90,7 +89,7 @@ * A = F corresponds to: F.collectSubstitutes(..., A, ..., 0) * A >> F corresponds to: F.collectSubstitutes(..., A, ..., 2) */ - public void collectSubstitutes(Scope scope, TypeBinding actualType, Map substitutes, int constraint) { + public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) { if ((this.tagBits & TagBits.HasTypeVariable) == 0) return; if (actualType == TypeBinding.NULL) return; @@ -124,16 +123,16 @@ case Wildcard.UNBOUND: // A={?} << F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} << F={? extends U} ---> V << U - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EXTENDS); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EXTENDS); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); } break; case Wildcard.SUPER: // A={? super V} << F={? extends U} ---> 0 break; } } else { // A=V << F={? extends U} ---> V << U - this.bound.collectSubstitutes(scope, actualType, substitutes, TypeConstants.CONSTRAINT_EXTENDS); + this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS); } break; case Wildcard.SUPER: // F={? super U} @@ -145,14 +144,14 @@ case Wildcard.EXTENDS: // A={? extends V} << F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} << F={? super U} ---> 0 - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; } } else { // A=V << F={? super U} ---> V >> U - this.bound.collectSubstitutes(scope, actualType, substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualType, inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; } @@ -180,9 +179,9 @@ case Wildcard.UNBOUND: // A={?} == F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} == F={? extends U} ---> V == U - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EQUAL); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EQUAL); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } break; case Wildcard.SUPER: // A={? super V} == F={? extends U} ---> 0 @@ -200,9 +199,9 @@ case Wildcard.EXTENDS: // A={? extends V} == F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} == F={? super U} ---> 0 - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_EQUAL); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_EQUAL); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_EQUAL); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_EQUAL); } break; } @@ -234,9 +233,9 @@ case Wildcard.UNBOUND: // A={?} >> F={? extends U} --> 0 break; case Wildcard.EXTENDS: // A={? extends V} >> F={? extends U} ---> V >> U - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; case Wildcard.SUPER: // A={? super V} >> F={? extends U} ---> 0 @@ -254,9 +253,9 @@ case Wildcard.EXTENDS: // A={? extends V} >> F={? super U} ---> 0 break; case Wildcard.SUPER: // A={? super V} >> F={? super U} ---> V >> U - this.bound.collectSubstitutes(scope, actualWildcard.bound, substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER); for (int i = 0, length = actualWildcard.otherBounds == null ? 0 : actualWildcard.otherBounds.length; i < length; i++) { - this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], substitutes, TypeConstants.CONSTRAINT_SUPER); + this.bound.collectSubstitutes(scope, actualWildcard.otherBounds[i], inferenceContext, TypeConstants.CONSTRAINT_SUPER); } break; } Index: compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java,v retrieving revision 1.71 diff -u -r1.71 ASTNode.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 11 May 2006 10:22:12 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 23 Jun 2006 23:18:55 -0000 @@ -172,28 +172,32 @@ // for null reference analysis public static final int IsNonNull = Bit18; + + // constants used when checking invocation arguments + public static final int INVOCATION_ARGUMENT_OK = 0; + public static final int INVOCATION_ARGUMENT_UNCHECKED = 1; + public static final int INVOCATION_ARGUMENT_WILDCARD = 2; + public ASTNode() { super(); } - private static boolean checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) { + private static int checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType, TypeBinding originalParameterType) { argument.computeConversion(scope, parameterType, argumentType); if (argumentType != TypeBinding.NULL && parameterType.isWildcard()) { WildcardBinding wildcard = (WildcardBinding) parameterType; if (wildcard.boundKind != Wildcard.SUPER && wildcard.otherBounds == null) // lub wildcards are tolerated - return true; // unsafeWildcardInvocation + return INVOCATION_ARGUMENT_WILDCARD; } TypeBinding checkedParameterType = originalParameterType == null ? parameterType : originalParameterType; - if (argumentType != checkedParameterType) { - if (argumentType.needsUncheckedConversion(checkedParameterType)) { - scope.problemReporter().unsafeTypeConversion(argument, argumentType, checkedParameterType); - } + if (argumentType != checkedParameterType && argumentType.needsUncheckedConversion(checkedParameterType)) { + scope.problemReporter().unsafeTypeConversion(argument, argumentType, checkedParameterType); + return INVOCATION_ARGUMENT_UNCHECKED; } - return false; + return INVOCATION_ARGUMENT_OK; } public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) { - boolean unsafeWildcardInvocation = false; TypeBinding[] params = method.parameters; int paramLength = params.length; boolean isRawMemberInvocation = !method.isStatic() @@ -210,15 +214,21 @@ } } } - if (arguments != null) { + int invocationStatus = INVOCATION_ARGUMENT_OK; + if (arguments == null) { + if (method.isVarargs()) { + TypeBinding parameterType = ((ArrayBinding) params[paramLength-1]).elementsType(); // no element was supplied for vararg parameter + if (!parameterType.isReifiable()) { + scope.problemReporter().unsafeGenericArrayForVarargs(parameterType, (ASTNode)invocationSite); + } + } + } else { if (method.isVarargs()) { // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2}) int lastIndex = paramLength - 1; for (int i = 0; i < lastIndex; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; - if (checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam)) { - unsafeWildcardInvocation = true; - } + invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i] , argumentTypes[i], originalRawParam); } int argLength = arguments.length; if (lastIndex < argLength) { // vararg argument was provided @@ -233,8 +243,7 @@ originalRawParam = rawOriginalGenericMethod == null ? null : ((ArrayBinding)rawOriginalGenericMethod.parameters[lastIndex]).elementsType(); } for (int i = lastIndex; i < argLength; i++) { - if (checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam)) - unsafeWildcardInvocation = true; + invocationStatus |= checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i], originalRawParam); } } @@ -262,15 +271,14 @@ } else { for (int i = 0; i < paramLength; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; - if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i], originalRawParam)) - unsafeWildcardInvocation = true; + invocationStatus |= checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i], originalRawParam); } } if (argsContainCast) { CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite); } } - if (unsafeWildcardInvocation) { + if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) { scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes); } else if (!method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) { scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method); Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v retrieving revision 1.257 diff -u -r1.257 Main.java --- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 21 Jun 2006 17:04:31 -0000 1.257 +++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 23 Jun 2006 23:18:54 -0000 @@ -535,7 +535,7 @@ if (localErrorCount == 0) { this.printlnErr("----------"); //$NON-NLS-1$ } - this.printlnErr(problem.isError() ? + this.printErr(problem.isError() ? Main.bind( "requestor.error", //$NON-NLS-1$ Integer.toString(globalErrorCount), @@ -546,7 +546,7 @@ new String(problem.getOriginatingFileName()))); try { final String errorReportSource = ((DefaultProblem) problem).errorReportSource(unitSource); - if (errorReportSource.length() != 0) this.printlnErr(errorReportSource); + this.printlnErr(errorReportSource); this.printlnErr(problem.getMessage()); } catch (Exception e) { this.printlnErr(Main.bind( Index: compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java =================================================================== RCS file: compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java diff -N compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.lookup; + +/** + * Context used during type inference for a generic method invocation + */ +public class InferenceContext { + + private TypeBinding[][][] collectedSubstitutes; + MethodBinding genericMethod; + int argumentIndex; + int depth; + int status; + TypeBinding[] substitutes; + final static int FAILED = 1; + final static int RAW_SUBSTITUTION = 2; + +public InferenceContext(MethodBinding genericMethod) { + this.genericMethod = genericMethod; + TypeVariableBinding[] typeVariables = genericMethod.typeVariables; + int varLength = typeVariables.length; + this.collectedSubstitutes = new TypeBinding[varLength][3][]; + this.argumentIndex = -1; + this.substitutes = new TypeBinding[varLength]; +} + +public boolean checkRawSubstitution() { + // only at first level, during inference from arguments + if (depth > 0) return false; +// if (this.argumentIndex < 0 || this.depth != 0) { +// return false; +// } + this.status = RAW_SUBSTITUTION; + return true; +} + +public TypeBinding[] getSubstitutes(TypeVariableBinding typeVariable, int constraint) { + return this.collectedSubstitutes[typeVariable.rank][constraint]; +} + +/** + * Returns true if any unresolved variable is detected, i.e. any variable is substituted with itself + */ +public boolean hasUnresolvedTypeArgument() { + for (int i = 0, varLength = this.substitutes.length; i :"); //$NON-NLS-1$ + break; + } + buffer.append(constraintCollected[k]); + } + } + } + } + buffer.append("}]");//$NON-NLS-1$ + buffer.append("\n\t[inferred=");//$NON-NLS-1$ + int count = 0; + for (int i = 0, length = this.substitutes == null ? 0 : this.substitutes.length; i < length; i++) { + if (this.substitutes[i] == null) continue; + count++; + buffer.append('{').append(this.genericMethod.typeVariables[i].sourceName); + buffer.append("=").append(this.substitutes[i]).append('}'); //$NON-NLS-1$ + } + if (count == 0) buffer.append("{}"); //$NON-NLS-1$ + buffer.append(']'); + return buffer.toString(); +} +} #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java,v retrieving revision 1.503 diff -u -r1.503 GenericTypeTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 22 Jun 2006 11:18:44 -0000 1.503 +++ src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 23 Jun 2006 23:19:23 -0000 @@ -11903,7 +11903,7 @@ } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=78467 - public void _test0412() { + public void testONLY_0412() { this.runNegativeTest( new String[] { "X.java", @@ -11924,7 +11924,47 @@ " Zork z;\n" + "}", }, - "should warn about unchecked array conversion for T[]"); + "----------\n" + + "1. ERROR in X.java (at line 15)\n" + + " Zork z;\n" + + " ^^^^\n" + + "Zork cannot be resolved to a type\n" + + "----------\n"); + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=78467 - variation + public void testONLY_0412a() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "public class X {\n" + + "\n" + + " public static T first(T... args) {\n" + + " return args[0];\n" + + " }\n" + + " \n" + + " public static void main(String[] args) {\n" + + " if (false) { \n" + + " List ls = first(); \n" + + " int i; \n" + + " i++; \n" + + " }\n" + + " System.out.println(first(\"SUCCESS\", \"List\"));\n" + + " }\n" + + " Zork z;\n" + + "}", + }, + "----------\n" + + "1. WARNING in X.java (at line 10)\n" + + " List ls = first(); \n" + + " ^^^^^^^\n" + + "Type safety : A generic array of List is created for a varargs parameter\n" + + "----------\n" + + "2. ERROR in X.java (at line 16)\n" + + " Zork z;\n" + + " ^^^^\n" + + "Zork cannot be resolved to a type\n" + + "----------\n"); } public void test0413() { @@ -31782,18 +31822,470 @@ "public class GenericsProblem {\n" + " public void test(T val) {\n" + " GenericsProblem gp = new GenericsProblem();\n" + - " // this is fine with both\n" + " Class cl2 = gp.getClass();\n" + - " // This fails on Sun\'s compiler\n" + " Class cl = val.getClass();\n" + " }\n" + "}\n", }, "----------\n" + - "1. ERROR in GenericsProblem.java (at line 7)\n" + + "1. ERROR in GenericsProblem.java (at line 5)\n" + " Class cl = val.getClass();\n" + " ^^^^^^^^^^^^^^\n" + "Type mismatch: cannot convert from Class to Class\n" + "----------\n"); -} +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 +public void test1008() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(L l, C c) {\n" + + " X x = bar(l, c);\n" + + " }\n" + + " T bar(L l, C c) { \n" + + " return null;\n" + + " } \n" + + "}\n" + + "class C {}\n" + + "class L {}\n" + + "\n" + + "\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 2)\r\n" + + " void foo(L l, C c) {\r\n" + + " ^\n" + + "L is a raw type. References to generic type L should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 3)\r\n" + + " X x = bar(l, c);\r\n" + + " ^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(L, C) of the generic method bar(L, C) of type X\n" + + "----------\n" + + "3. ERROR in X.java (at line 3)\r\n" + + " X x = bar(l, c);\r\n" + + " ^^^^^^^^^\n" + + "Type mismatch: cannot convert from Object to X\n" + + "----------\n" + + "4. WARNING in X.java (at line 3)\r\n" + + " X x = bar(l, c);\r\n" + + " ^\n" + + "Type safety: The expression of type L needs unchecked conversion to conform to L\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1009() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.Map;\n" + + "public class X {\n" + + "\n" + + " void foo(Map map) {\n" + + " bar(map);\n" + + " }\n" + + " void bar(Map> map) {\n" + + " }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 4)\n" + + " void foo(Map map) {\n" + + " ^^^\n" + + "Map is a raw type. References to generic type Map should be parameterized\n" + + "----------\n" + + "2. ERROR in X.java (at line 5)\n" + + " bar(map);\n" + + " ^^^\n" + + "The method bar(Map>) in the type X is not applicable for the arguments (Map)\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1010() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.Map;\n" + + "public class X {\n" + + "\n" + + " void foo(Map map) {\n" + + " bar(map);\n" + + " }\n" + + " void bar(Map> map) {\n" + + " }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 4)\n" + + " void foo(Map map) {\n" + + " ^^^\n" + + "Map is a raw type. References to generic type Map should be parameterized\n" + + "----------\n" + + "2. ERROR in X.java (at line 5)\n" + + " bar(map);\n" + + " ^^^\n" + + "The method bar(Map>) in the type X is not applicable for the arguments (Map)\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1011() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "public class X {\n" + + " void foo(HashMap map, String s, Map map2) {\n" + + " bar(map, s, map2); //1\n" + + " bar(map2, s, map2); //2\n" + + " bar2(map, s, map2); //3\n" + + " bar3(map, s, map2); //4\n" + + " }\n" + + " void bar(Map map, U u, Map map2) {}\n" + + " void bar2(Map map, String s, Map map2) {}\n" + + " void bar3(Map map, U s, Map map2) {}\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 3)\n" + + " void foo(HashMap map, String s, Map map2) {\n" + + " ^^^^^^^\n" + + "HashMap is a raw type. References to generic type HashMap should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 4)\n" + + " bar(map, s, map2); //1\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(Map, Object, Map) of the generic method bar(Map, U, Map) of type X\n" + + "----------\n" + + "3. WARNING in X.java (at line 4)\n" + + " bar(map, s, map2); //1\n" + + " ^^^\n" + + "Type safety: The expression of type HashMap needs unchecked conversion to conform to Map\n" + + "----------\n" + + "4. WARNING in X.java (at line 6)\n" + + " bar2(map, s, map2); //3\n" + + " ^^^\n" + + "Type safety: The expression of type HashMap needs unchecked conversion to conform to Map\n" + + "----------\n" + + "5. WARNING in X.java (at line 7)\n" + + " bar3(map, s, map2); //4\n" + + " ^^^\n" + + "Type safety: The expression of type HashMap needs unchecked conversion to conform to Map\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1012() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(L l, C c) {\n" + + " X x = bar1(l, c);\n" + + " L lx = bar2(l, c);\n" + + " C cx = bar3(l, c);\n" + + " }\n" + + " T bar1(L l, C c) {\n" + + " return null;\n" + + " }\n" + + " L bar2(L l, C c) {\n" + + " return null;\n" + + " }\n" + + " C bar3(L l, C c) {\n" + + " return null;\n" + + " }\n" + + "}\n" + + "\n" + + "class C {}\n" + + "class L {}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 2)\r\n" + + " void foo(L l, C c) {\r\n" + + " ^\n" + + "L is a raw type. References to generic type L should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 3)\r\n" + + " X x = bar1(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar1(L, C) of the generic method bar1(L, C) of type X\n" + + "----------\n" + + "3. ERROR in X.java (at line 3)\r\n" + + " X x = bar1(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type mismatch: cannot convert from Object to X\n" + + "----------\n" + + "4. WARNING in X.java (at line 3)\r\n" + + " X x = bar1(l, c);\r\n" + + " ^\n" + + "Type safety: The expression of type L needs unchecked conversion to conform to L\n" + + "----------\n" + + "5. WARNING in X.java (at line 4)\r\n" + + " L lx = bar2(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar2(L, C) of the generic method bar2(L, C) of type X\n" + + "----------\n" + + "6. WARNING in X.java (at line 4)\r\n" + + " L lx = bar2(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type safety: The expression of type L needs unchecked conversion to conform to L\n" + + "----------\n" + + "7. WARNING in X.java (at line 4)\r\n" + + " L lx = bar2(l, c);\r\n" + + " ^\n" + + "Type safety: The expression of type L needs unchecked conversion to conform to L\n" + + "----------\n" + + "8. WARNING in X.java (at line 5)\r\n" + + " C cx = bar3(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar3(L, C) of the generic method bar3(L, C) of type X\n" + + "----------\n" + + "9. WARNING in X.java (at line 5)\r\n" + + " C cx = bar3(l, c);\r\n" + + " ^^^^^^^^^^\n" + + "Type safety: The expression of type C needs unchecked conversion to conform to C\n" + + "----------\n" + + "10. WARNING in X.java (at line 5)\r\n" + + " C cx = bar3(l, c);\r\n" + + " ^\n" + + "Type safety: The expression of type L needs unchecked conversion to conform to L\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1013() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "\n" + + "public class X {\n" + + " public static void main(String[] args) {\n" + + " List ls = new ArrayList();\n" + + " ls.add(\"foo\");\n" + + " List lx = new ArrayList();\n" + + " lx.add(new X());\n" + + " new X().foo(ls, lx);\n" + + " }\n" + + " void done() {\n" + + " System.out.println(\"[done]\");\n" + + " }\n" + + " void foo(List l1, List l2) {\n" + + " X x = bar1(l1, l2);\n" + + " x.done();\n" + + " List lx = bar2(l1, l2);\n" + + " lx.get(0).done();\n" + + " }\n" + + " T bar1(List l1, List l2) {\n" + + " return l1.get(0);\n" + + " }\n" + + " List bar2(List l1, List l2) {\n" + + " return l1;\n" + + " }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 14)\r\n" + + " void foo(List l1, List l2) {\r\n" + + " ^^^^\n" + + "List is a raw type. References to generic type List should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 15)\r\n" + + " X x = bar1(l1, l2);\r\n" + + " ^^^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar1(List, List) of the generic method bar1(List, List) of type X\n" + + "----------\n" + + "3. ERROR in X.java (at line 15)\r\n" + + " X x = bar1(l1, l2);\r\n" + + " ^^^^^^^^^^^^\n" + + "Type mismatch: cannot convert from Object to X\n" + + "----------\n" + + "4. WARNING in X.java (at line 15)\r\n" + + " X x = bar1(l1, l2);\r\n" + + " ^^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n" + + "5. WARNING in X.java (at line 17)\r\n" + + " List lx = bar2(l1, l2);\r\n" + + " ^^^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar2(List, List) of the generic method bar2(List, List) of type X\n" + + "----------\n" + + "6. WARNING in X.java (at line 17)\r\n" + + " List lx = bar2(l1, l2);\r\n" + + " ^^^^^^^^^^^^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n" + + "7. WARNING in X.java (at line 17)\r\n" + + " List lx = bar2(l1, l2);\r\n" + + " ^^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1014() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "\n" + + "public class X {\n" + + " void foo1(List l, List ls) {\n" + + " Set> mss1 = bar(l, ls).entrySet();\n" + + " String s = bar(l, ls).entrySet();\n" + + " }\n" + + " Map bar(List lu, List lv) { return null; }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 4)\n" + + " void foo1(List l, List ls) {\n" + + " ^^^^\n" + + "List is a raw type. References to generic type List should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 5)\n" + + " Set> mss1 = bar(l, ls).entrySet();\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(List, List) of the generic method bar(List, List) of type X\n" + + "----------\n" + + "3. WARNING in X.java (at line 5)\n" + + " Set> mss1 = bar(l, ls).entrySet();\n" + + " ^^^^^^^^^^^^^^^^^^^^^\n" + + "Type safety: The expression of type Set needs unchecked conversion to conform to Set>\n" + + "----------\n" + + "4. WARNING in X.java (at line 5)\n" + + " Set> mss1 = bar(l, ls).entrySet();\n" + + " ^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n" + + "5. WARNING in X.java (at line 6)\n" + + " String s = bar(l, ls).entrySet();\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(List, List) of the generic method bar(List, List) of type X\n" + + "----------\n" + + "6. ERROR in X.java (at line 6)\n" + + " String s = bar(l, ls).entrySet();\n" + + " ^^^^^^^^^^^^^^^^^^^^^\n" + + "Type mismatch: cannot convert from Set to String\n" + + "----------\n" + + "7. WARNING in X.java (at line 6)\n" + + " String s = bar(l, ls).entrySet();\n" + + " ^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1015() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "public class X {\n" + + " void foo1(List l, List ls) {\n" + + " List ls1 = bar(l, ls);\n" + + " String s = bar(l, ls);\n" + + " }\n" + + " List bar(List lu, List lv) { return null; }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 3)\n" + + " void foo1(List l, List ls) {\n" + + " ^^^^\n" + + "List is a raw type. References to generic type List should be parameterized\n" + + "----------\n" + + "2. WARNING in X.java (at line 4)\n" + + " List ls1 = bar(l, ls);\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(List, List) of the generic method bar(List, List) of type X\n" + + "----------\n" + + "3. WARNING in X.java (at line 4)\n" + + " List ls1 = bar(l, ls);\n" + + " ^^^^^^^^^^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n" + + "4. WARNING in X.java (at line 4)\n" + + " List ls1 = bar(l, ls);\n" + + " ^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n" + + "5. WARNING in X.java (at line 5)\n" + + " String s = bar(l, ls);\n" + + " ^^^^^^^^^^\n" + + "Type safety: Unchecked invocation bar(List, List) of the generic method bar(List, List) of type X\n" + + "----------\n" + + "6. ERROR in X.java (at line 5)\n" + + " String s = bar(l, ls);\n" + + " ^^^^^^^^^^\n" + + "Type mismatch: cannot convert from List to String\n" + + "----------\n" + + "7. WARNING in X.java (at line 5)\n" + + " String s = bar(l, ls);\n" + + " ^\n" + + "Type safety: The expression of type List needs unchecked conversion to conform to List\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1016() { + this.runNegativeTest( + new String[] { + "X.java", + "import java.util.*;\n" + + "public class X {\n" + + " void foo1() {\n" + + " List ls1 = bar(null);\n" + + " List ls2 = bar(null);\n" + + " String s = bar(null);\n" + + " }\n" + + " List bar(List lu) { return null; }\n" + + "}\n", // ================= + }, + "----------\n" + + "1. WARNING in X.java (at line 4)\n" + + " List ls1 = bar(null);\n" + + " ^^^^\n" + + "List is a raw type. References to generic type List should be parameterized\n" + + "----------\n" + + "2. ERROR in X.java (at line 6)\n" + + " String s = bar(null);\n" + + " ^^^^^^^^^\n" + + "Type mismatch: cannot convert from List to String\n" + + "----------\n"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=148061 - variation +public void test1017() { + this.runNegativeTest( + new String[] { + "SortedList.java", + "import java.util.*;\n" + + "\n" + + "public class SortedList extends LinkedList\n" + + "{\n" + + " public boolean add(E e){\n" + + " int index = Collections.binarySearch(this,e);\n" + + " if (index<0)\n" + + " super.add(-index-1,e);\n" + + " return true;\n" + + " }\n" + + "}", // ================= + }, + "----------\n" + + "1. WARNING in SortedList.java (at line 3)\n" + + " public class SortedList extends LinkedList\n" + + " ^^^^^^^^^^\n" + + "The serializable class SortedList does not declare a static final serialVersionUID field of type long\n" + + "----------\n" + + "2. WARNING in SortedList.java (at line 3)\n" + + " public class SortedList extends LinkedList\n" + + " ^^^^^^^^^^\n" + + "Comparable is a raw type. References to generic type Comparable should be parameterized\n" + + "----------\n" + + "3. WARNING in SortedList.java (at line 5)\n" + + " public boolean add(E e){\n" + + " ^^^^^^^^\n" + + "The method add(E) of type SortedList should be tagged with @Override since it actually overrides a superclass method\n" + + "----------\n" + + "4. ERROR in SortedList.java (at line 6)\n" + + " int index = Collections.binarySearch(this,e);\n" + + " ^^^^^^^^^^^^\n" + + "The method binarySearch(List>, T) in the type Collections is not applicable for the arguments (SortedList, E)\n" + + "----------\n"); +} } \ No newline at end of file