diff options
author | Stephan Herrmann | 2013-12-05 22:26:14 +0000 |
---|---|---|
committer | Stephan Herrmann | 2013-12-05 22:26:14 +0000 |
commit | 160d5d061fcfc93582f0fe36646007e32719bbb7 (patch) | |
tree | 203f6c604fb663851c757f4ec06aaabace0388bc | |
parent | 35cbca7e1c2b3f9e91f39afaa6acf75948770ff1 (diff) | |
download | eclipse.jdt.core-160d5d061fcfc93582f0fe36646007e32719bbb7.tar.gz eclipse.jdt.core-160d5d061fcfc93582f0fe36646007e32719bbb7.tar.xz eclipse.jdt.core-160d5d061fcfc93582f0fe36646007e32719bbb7.zip |
Fix GenericsRegressionTest.testBug413958_2(): avoid CaptureBinding18 as
intersection with inconsistent parameterization (was causing
non-determinism).
Also handle multiple upper bounds in more situations
2 files changed, 98 insertions, 2 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java index 0af93f39b5..b3c2d8f086 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java @@ -25,13 +25,24 @@ public class CaptureBinding18 extends CaptureBinding { super(contextType, sourceName, 0, captureID, environment); } - public void setUpperBounds(TypeBinding[] upperBounds, ReferenceBinding javaLangObject) { + public boolean setUpperBounds(TypeBinding[] upperBounds, ReferenceBinding javaLangObject) { this.upperBounds = upperBounds; if (upperBounds.length > 0) this.firstBound = upperBounds[0]; int numReferenceInterfaces = 0; for (int i = 0; i < upperBounds.length; i++) { TypeBinding aBound = upperBounds[i]; + if (!aBound.isWildcard() && !aBound.isTypeVariable() && aBound.isProperType(false)) { + // check for inconsistency between any two real types: + for (int j = 0; j < upperBounds.length; j++) { + if (i == j) continue; + TypeBinding otherBound = upperBounds[j]; + if (!otherBound.isWildcard() && !otherBound.isTypeVariable() && otherBound.isProperType(false)) + if (aBound.erasure().isCompatibleWith(otherBound.erasure())) + if (!aBound.isCompatibleWith(otherBound)) + return false; + } + } if (aBound instanceof ReferenceBinding) { if (this.superclass == null && aBound.isClass()) this.superclass = (ReferenceBinding) upperBounds[i]; @@ -49,6 +60,7 @@ public class CaptureBinding18 extends CaptureBinding { } if (this.superclass == null) this.superclass = javaLangObject; + return true; } public TypeBinding clone(TypeBinding enclosingType) { @@ -61,6 +73,17 @@ public class CaptureBinding18 extends CaptureBinding { return super.getMethods(selector); } + public TypeBinding erasure() { + if (this.upperBounds != null && this.upperBounds.length > 1) { + ReferenceBinding[] erasures = new ReferenceBinding[this.upperBounds.length]; + for (int i = 0; i < this.upperBounds.length; i++) { + erasures[i] = (ReferenceBinding) this.upperBounds[i].erasure(); // FIXME cast? + } + return new IntersectionCastTypeBinding(erasures, this.environment); + } + return super.erasure(); + } + /** * @see TypeBinding#isEquivalentTo(TypeBinding) */ @@ -102,6 +125,78 @@ public class CaptureBinding18 extends CaptureBinding { return super.isCompatibleWith(otherType, captureScope); } + public TypeBinding findSuperTypeOriginatingFrom(TypeBinding otherType) { + if (this.upperBounds != null && this.upperBounds.length > 1) { + for (int i = 0; i < this.upperBounds.length; i++) { + TypeBinding candidate = this.upperBounds[i].findSuperTypeOriginatingFrom(otherType); + if (candidate != null) + return candidate; + // TODO: do we need explicit handling of cases where several upperBounds produce a non-null candidate? + } + } + return super.findSuperTypeOriginatingFrom(otherType); + } + + TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) { + if (this.inRecursiveFunction) return this; + this.inRecursiveFunction = true; + try { + boolean haveSubstitution = false; + ReferenceBinding currentSuperclass = this.superclass; + if (currentSuperclass != null) { + currentSuperclass = (ReferenceBinding) currentSuperclass.substituteInferenceVariable(var, substituteType); + haveSubstitution |= TypeBinding.notEquals(currentSuperclass, this.superclass); + } + ReferenceBinding[] currentSuperInterfaces = null; + if (this.superInterfaces != null) { + int length = this.superInterfaces.length; + if (haveSubstitution) + System.arraycopy(this.superInterfaces, 0, currentSuperInterfaces=new ReferenceBinding[length], 0, length); + for (int i = 0; i < length; i++) { + ReferenceBinding currentSuperInterface = this.superInterfaces[i]; + if (currentSuperInterface != null) { + currentSuperInterface = (ReferenceBinding) currentSuperInterface.substituteInferenceVariable(var, substituteType); + if (TypeBinding.notEquals(currentSuperInterface, this.superInterfaces[i])) { + if (currentSuperInterfaces == null) + System.arraycopy(this.superInterfaces, 0, currentSuperInterfaces=new ReferenceBinding[length], 0, length); + currentSuperInterfaces[i] = currentSuperInterface; + haveSubstitution = true; + } + } + } + } + TypeBinding[] currentUpperBounds = null; + if (this.upperBounds != null) { + int length = this.upperBounds.length; + if (haveSubstitution) + System.arraycopy(this.upperBounds, 0, currentUpperBounds=new TypeBinding[length], 0, length); + for (int i = 0; i < length; i++) { + TypeBinding currentBound = this.upperBounds[i]; + if (currentBound != null) { + currentBound = currentBound.substituteInferenceVariable(var, substituteType); + if (TypeBinding.notEquals(currentBound, this.upperBounds[i])) { + if (currentUpperBounds == null) + System.arraycopy(this.upperBounds, 0, currentUpperBounds=new TypeBinding[length], 0, length); + currentUpperBounds[i] = currentBound; + haveSubstitution = true; + } + } + } + } + if (haveSubstitution) { + CaptureBinding18 newCapture = (CaptureBinding18) clone(enclosingType()); + newCapture.superclass = currentSuperclass; + newCapture.superInterfaces = currentSuperInterfaces; + newCapture.upperBounds = currentUpperBounds; + newCapture.tagBits = this.tagBits; + return newCapture; + } + return this; + } finally { + this.inRecursiveFunction = false; + } + } + boolean isProperType(boolean admitCapture18) { return admitCapture18; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index 5ed8e7e788..8694c4102a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -546,7 +546,8 @@ public class InferenceContext18 { TypeBinding[] glbs = Scope.greaterLowerBound(substitutedUpperBounds, this.scope, this.environment); if (glbs == null) return false; - typeVariable.setUpperBounds(glbs, this.object); + if (!typeVariable.setUpperBounds(glbs, this.object)) + return false; } return true; } |