### 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.97 diff -u -r1.97 ParameterizedTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 31 Aug 2007 11:26:54 -0000 1.97 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java 12 Sep 2007 16:13:26 -0000 @@ -66,8 +66,10 @@ boolean hasErrors = false; TypeVariableBinding[] typeVariables = this.type.typeVariables(); if (this.arguments != null && typeVariables != null) { // arguments may be null in error cases + // JLS 4.5 - need to perform capture conversion before attempting to check bound compatibility + ParameterizedTypeBinding capturedParamType = (ParameterizedTypeBinding) this.capture(null /* no scope */, 0 /*use rank as a dummy position*/); for (int i = 0, length = typeVariables.length; i < length; i++) { - if (typeVariables[i].boundCheck(this, this.arguments[i]) != TypeConstants.OK) { + if (typeVariables[i].boundCheck(capturedParamType, capturedParamType.arguments[i]) != TypeConstants.OK) { hasErrors = true; scope.problemReporter().typeMismatchError(this.arguments[i], typeVariables[i], this.type, argumentReferences[i]); } @@ -85,6 +87,7 @@ /** * Perform capture conversion for a parameterized type with wildcard arguments * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#capture(Scope,int) + * @param scope - may be null */ public TypeBinding capture(Scope scope, int position) { if ((this.tagBits & TagBits.HasDirectWildcard) == 0) @@ -95,13 +98,13 @@ TypeBinding[] capturedArguments = new TypeBinding[length]; // Retrieve the type context for capture bindingKey - ReferenceBinding contextType = scope.enclosingSourceType(); + ReferenceBinding contextType = scope == null ? null : scope.enclosingSourceType(); if (contextType != null) contextType = contextType.outermostEnclosingType(); // maybe null when used programmatically by DOM for (int i = 0; i < length; i++) { TypeBinding argument = originalArguments[i]; if (argument.kind() == Binding.WILDCARD_TYPE && ((WildcardBinding)argument).otherBounds == null) { // no capture for intersection types - capturedArguments[i] = new CaptureBinding((WildcardBinding) argument, contextType, position, scope.compilationUnitScope().nextCaptureID()); + capturedArguments[i] = new CaptureBinding((WildcardBinding) argument, contextType, position, scope == null ? position : scope.compilationUnitScope().nextCaptureID()); } else { capturedArguments[i] = argument; } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java,v retrieving revision 1.312 diff -u -r1.312 Scope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java 21 Aug 2007 18:55:48 -0000 1.312 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java 12 Sep 2007 16:13:27 -0000 @@ -228,6 +228,17 @@ switch (originalType.kind()) { case Binding.TYPE_PARAMETER: + if (originalType.isCapture()) { +// CaptureBinding capture = (CaptureBinding) originalType; +// WildcardBinding originalWildcard = capture.wildcard; +// TypeBinding substitutedWildcard = substitute(substitution, originalWildcard); +// if (substitutedWildcard != originalWildcard) { +// CaptureBinding substitutedCapture = new CaptureBinding((WildcardBinding)substitutedWildcard, capture.sourceType, capture.position, capture.captureID); +// substitutedCapture.initializeBounds(((SourceTypeBinding)capture.sourceType).scope, (ParameterizedTypeBinding)substitution); +// return substitutedCapture; +// } + break; + } return substitution.substitute((TypeVariableBinding) originalType); case Binding.PARAMETERIZED_TYPE: @@ -246,18 +257,6 @@ substitutedArguments = substitute(substitution, originalArguments); } if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) { -// identicalVariables: { // if substituted with original variables, then answer the generic type itself -// if (substitutedEnclosing != null) { -// //if (!(substitutedEnclosing instanceof SourceTypeBinding)) break identicalVariables; -// if (substitutedEnclosing != originalEnclosing) break identicalVariables; -// } -// if (originalParameterizedType.type.isBinaryBinding()) break identicalVariables; // generic binary is never used as is, see 85262 -// TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables(); -// for (int i = 0, length = originalVariables.length; i < length; i++) { -// if (substitutedArguments[i] != originalVariables[i]) break identicalVariables; -// } -// return originalParameterizedType.type; -// } return originalParameterizedType.environment.createParameterizedType( originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing); } 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.84 diff -u -r1.84 TypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 11 Apr 2007 19:43:54 -0000 1.84 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java 12 Sep 2007 16:13:27 -0000 @@ -98,6 +98,7 @@ /** * Perform capture conversion on a given type (only effective on parameterized type with wildcards) + * @param scope - may be null */ public TypeBinding capture(Scope scope, int position) { return this; 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.60 diff -u -r1.60 TypeVariableBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 15 May 2007 14:39:22 -0000 1.60 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java 12 Sep 2007 16:13:27 -0000 @@ -60,62 +60,76 @@ if (this.superclass == null) return TypeConstants.OK; - if (argumentType.isWildcard() && !argumentType.isIntersectionType()) { - WildcardBinding wildcard = (WildcardBinding) argumentType; - switch(wildcard.boundKind) { - case Wildcard.EXTENDS : - TypeBinding wildcardBound = wildcard.bound; - if (wildcardBound == this) + switch(argumentType.kind()) { + case Binding.TYPE_PARAMETER : + if (argumentType.isCapture()) { + CaptureBinding capture = (CaptureBinding) argumentType; + if (capture.lowerBound != null) { + return boundCheck(substitution, capture.lowerBound); + } else if (capture.wildcard.boundKind == Wildcard.UNBOUND) { return TypeConstants.OK; - ReferenceBinding superclassBound = hasSubstitution ? (ReferenceBinding)Scope.substitute(substitution, this.superclass) : this.superclass; - boolean isArrayBound = wildcardBound.isArrayType(); - if (!wildcardBound.isInterface()) { - if (superclassBound.id != TypeIds.T_JavaLangObject) { - if (isArrayBound) { - if (!wildcardBound.isCompatibleWith(superclassBound)) - return TypeConstants.MISMATCH; - } else { - TypeBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeWithSameErasure(superclassBound); - if (match != null) { - if (!match.isIntersectingWith(superclassBound)) { - return TypeConstants.MISMATCH; + } + } + break; + case Binding.WILDCARD_TYPE : + if (!argumentType.isIntersectionType()) { + WildcardBinding wildcard = (WildcardBinding) argumentType; + switch(wildcard.boundKind) { + case Wildcard.EXTENDS : + TypeBinding wildcardBound = wildcard.bound; + if (wildcardBound == this) + return TypeConstants.OK; + ReferenceBinding superclassBound = hasSubstitution ? (ReferenceBinding)Scope.substitute(substitution, this.superclass) : this.superclass; + boolean isArrayBound = wildcardBound.isArrayType(); + if (!wildcardBound.isInterface()) { + if (superclassBound.id != TypeIds.T_JavaLangObject) { + if (isArrayBound) { + if (!wildcardBound.isCompatibleWith(superclassBound)) + return TypeConstants.MISMATCH; + } else { + TypeBinding match = ((ReferenceBinding)wildcardBound).findSuperTypeWithSameErasure(superclassBound); + if (match != null) { + if (!match.isIntersectingWith(superclassBound)) { + return TypeConstants.MISMATCH; + } + } else { + return TypeConstants.MISMATCH; + } } - } else { - return TypeConstants.MISMATCH; } } - } - } - ReferenceBinding[] superInterfaceBounds = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces) : this.superInterfaces; - int length = superInterfaceBounds.length; - boolean mustImplement = isArrayBound || ((ReferenceBinding)wildcardBound).isFinal(); - for (int i = 0; i < length; i++) { - TypeBinding superInterfaceBound = superInterfaceBounds[i]; - if (isArrayBound) { - if (!wildcardBound.isCompatibleWith(superInterfaceBound)) - return TypeConstants.MISMATCH; - } else { - TypeBinding match = wildcardBound.findSuperTypeWithSameErasure(superInterfaceBound); - if (match != null) { - if (!match.isIntersectingWith(superInterfaceBound)) { - return TypeConstants.MISMATCH; + ReferenceBinding[] superInterfaceBounds = hasSubstitution ? Scope.substitute(substitution, this.superInterfaces) : this.superInterfaces; + int length = superInterfaceBounds.length; + boolean mustImplement = isArrayBound || ((ReferenceBinding)wildcardBound).isFinal(); + for (int i = 0; i < length; i++) { + TypeBinding superInterfaceBound = superInterfaceBounds[i]; + if (isArrayBound) { + if (!wildcardBound.isCompatibleWith(superInterfaceBound)) + return TypeConstants.MISMATCH; + } else { + TypeBinding match = wildcardBound.findSuperTypeWithSameErasure(superInterfaceBound); + if (match != null) { + if (!match.isIntersectingWith(superInterfaceBound)) { + return TypeConstants.MISMATCH; + } + } else if (mustImplement) { + return TypeConstants.MISMATCH; // cannot be extended further to satisfy missing bounds + } } - } else if (mustImplement) { - return TypeConstants.MISMATCH; // cannot be extended further to satisfy missing bounds - } - } + } + break; + + case Wildcard.SUPER : + return boundCheck(substitution, wildcard.bound); + + case Wildcard.UNBOUND : + break; } - break; - - case Wildcard.SUPER : - return boundCheck(substitution, wildcard.bound); - - case Wildcard.UNBOUND : - break; - } - return TypeConstants.OK; + return TypeConstants.OK; + } } + boolean unchecked = false; if (this.superclass.id != TypeIds.T_JavaLangObject) { TypeBinding superType = this.superclass; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java,v retrieving revision 1.19 diff -u -r1.19 CaptureBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java 6 Jul 2006 11:20:36 -0000 1.19 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java 12 Sep 2007 16:13:26 -0000 @@ -79,6 +79,7 @@ /** * Initialize capture bounds using substituted supertypes * e.g. given X>, capture(X) = X, where capture extends X + * @param scope - may be null */ public void initializeBounds(Scope scope, ParameterizedTypeBinding capturedParameterizedType) { TypeVariableBinding wildcardVariable = wildcard.typeVariable(); @@ -101,7 +102,8 @@ switch (wildcard.boundKind) { case Wildcard.EXTENDS : // still need to capture bound supertype as well so as not to expose wildcards to the outside (111208) - TypeBinding substitutedWildcardBound = originalWildcardBound.capture(scope, this.position); + TypeBinding capturedWildcardBound = originalWildcardBound.capture(scope, this.position); + TypeBinding substitutedWildcardBound = Scope.substitute(capturedParameterizedType, capturedWildcardBound); if (wildcard.bound.isInterface()) { this.superclass = substitutedVariableSuperclass; // merge wildcard bound into variable superinterfaces using glb @@ -114,8 +116,16 @@ this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces); } } else { - // per construction the wildcard bound is a subtype of variable superclass - this.superclass = wildcard.bound.isArrayType() ? substitutedVariableSuperclass : (ReferenceBinding) substitutedWildcardBound; + // the wildcard bound should be a subtype of variable superclass + // it may occur that the bound is less specific, then consider glb (202404) + if (substitutedWildcardBound.isArrayType() || substitutedWildcardBound == this) { + this.superclass = substitutedVariableSuperclass; + } else { + this.superclass = (ReferenceBinding) substitutedWildcardBound; + if (this.superclass.isSuperclassOf(substitutedVariableSuperclass)) { + this.superclass = substitutedVariableSuperclass; + } + } this.superInterfaces = substitutedVariableInterfaces; } this.firstBound = substitutedWildcardBound; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java,v retrieving revision 1.106 diff -u -r1.106 BlockScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 6 Mar 2007 02:38:50 -0000 1.106 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 12 Sep 2007 16:13:26 -0000 @@ -111,8 +111,8 @@ this.subscopes[this.subscopeCount++] = childScope; } -/* Answer true if the receiver is suitable for assigning final blank fields. - * +/* + * Answer true if the receiver is suitable for assigning final blank fields. * in other words, it is inside an initializer, a constructor or a clinit */ public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {