Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2013-12-10 01:08:27 +0000
committerStephan Herrmann2013-12-10 11:24:38 +0000
commitd3de41afc4bae04cfee3367369f0e9174a3b79dd (patch)
treed0cbad2c94e470c7ff1f08d9ce32e15656bbd93c
parent854bd41c292a3f10302052623fca30040d1c56c7 (diff)
downloadeclipse.jdt.core-d3de41afc4bae04cfee3367369f0e9174a3b79dd.tar.gz
eclipse.jdt.core-d3de41afc4bae04cfee3367369f0e9174a3b79dd.tar.xz
eclipse.jdt.core-d3de41afc4bae04cfee3367369f0e9174a3b79dd.zip
WIP for Bug 419048
- tentative spec bug fix: 18.3 2nd list bullet 5 misses to apply theta! - improve our substitution to handle types that are not type variables
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java27
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java343
5 files changed, 233 insertions, 158 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
index 0a8960bbd5..200715895b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/LambdaExpressionsTest.java
@@ -22,7 +22,7 @@ import junit.framework.Test;
public class LambdaExpressionsTest extends AbstractRegressionTest {
static {
-// TESTS_NAMES = new String[] { "testLambdaInference2"};
+ TESTS_NAMES = new String[] { "testBug419048_1"};
// TESTS_NUMBERS = new int[] { 50 };
// TESTS_RANGE = new int[] { 11, -1 };
}
@@ -2006,6 +2006,31 @@ public void testLambdaInference2() {
"");
}
+public void testBug419048_1() {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.*;\n" +
+ "import java.util.stream.*;\n" +
+ "public class X {\n" +
+ " public void test() {\n" +
+ " List<Person> roster = new ArrayList<>();\n" +
+ " \n" +
+ " Map<String, Person> map = \n" +
+ " roster\n" +
+ " .stream()\n" +
+ " .collect(\n" +
+ " Collectors.toMap(\n" +
+ " p -> p.getLast(),\n" +
+ " p -> p\n" +
+ " ));\n" +
+ " }\n" +
+ "}\n" +
+ "class Person {\n" +
+ " public String getLast() { return null; }\n" +
+ "}\n"
+ });
+}
public static Class testClass() {
return LambdaExpressionsTest.class;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
index 7de5c75719..453aa27f82 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
@@ -456,7 +456,7 @@ class BoundSet {
}
}
} else {
- addBound(new TypeBound(alpha, ai, ReductionResult.SAME));
+ addBound(new TypeBound(alpha, context.substitute(ai), ReductionResult.SAME));
}
}
}
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 eb5e66cc04..cfd8703589 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
@@ -95,7 +95,8 @@ public class InferenceContext18 {
* Substitute any type variables mentioned in 'type' by the corresponding inference variable, if one exists.
*/
public TypeBinding substitute(TypeBinding type) {
- return Scope.substitute(new InferenceSubstitution(this.environment, this.inferenceVariables), type);
+ InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this.environment, this.inferenceVariables);
+ return inferenceSubstitution.substitute(inferenceSubstitution, type);
}
/** JLS 18.5.1: compute bounds from formal and actual parameters. */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
index 759f1ac995..0f345bdc75 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
@@ -17,7 +17,7 @@ package org.eclipse.jdt.internal.compiler.lookup;
/**
* A type variable substitution strategy based on inference variables (JLS8 18.1.1)
*/
-public class InferenceSubstitution implements Substitution {
+public class InferenceSubstitution extends Scope.Substitutor implements Substitution {
private LookupEnvironment environment;
private InferenceVariable[] variables;
@@ -26,6 +26,20 @@ public class InferenceSubstitution implements Substitution {
this.environment = environment;
this.variables = variables;
}
+
+ /**
+ * Override method {@link Scope.Substitutor#substitute(Substitution, TypeBinding)},
+ * to add substitution of types other than type variables.
+ */
+ public TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
+ for (int i = 0; i < this.variables.length; i++) {
+ InferenceVariable variable = this.variables[i];
+ if (TypeBinding.equalsEquals(variable.typeParameter, originalType))
+ return variable;
+ }
+
+ return super.substitute(substitution, originalType);
+ }
public TypeBinding substitute(TypeVariableBinding typeVariable) {
ReferenceBinding superclass = typeVariable.superclass;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index a9f44ae010..02b9c1a8c6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -385,24 +385,7 @@ public abstract class Scope {
* Only allocate an array if anything is different.
*/
public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
- if (originalTypes == null) return null;
- ReferenceBinding[] substitutedTypes = originalTypes;
- for (int i = 0, length = originalTypes.length; i < length; i++) {
- ReferenceBinding originalType = originalTypes[i];
- TypeBinding substitutedType = substitute(substitution, originalType);
- if (!(substitutedType instanceof ReferenceBinding)) {
- return null; // impossible substitution
- }
- if (substitutedType != originalType) { //$IDENTITY-COMPARISON$
- if (substitutedTypes == originalTypes) {
- System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
- }
- substitutedTypes[i] = (ReferenceBinding)substitutedType;
- } else if (substitutedTypes != originalTypes) {
- substitutedTypes[i] = originalType;
- }
- }
- return substitutedTypes;
+ return defaultSubstitutor.substitute(substitution, originalTypes);
}
/**
@@ -416,127 +399,7 @@ public abstract class Scope {
* of its type in the generic declaration corresponding to C."
*/
public static TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
- if (originalType == null) return null;
- switch (originalType.kind()) {
-
- case Binding.TYPE_PARAMETER:
- return substitution.substitute((TypeVariableBinding) originalType);
-
- case Binding.PARAMETERIZED_TYPE:
- ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
- ReferenceBinding originalEnclosing = originalType.enclosingType();
- ReferenceBinding substitutedEnclosing = originalEnclosing;
- if (originalEnclosing != null) {
- substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
- if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
- return originalParameterizedType.environment.createRawType(
- originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
- }
- TypeBinding[] originalArguments = originalParameterizedType.arguments;
- TypeBinding[] substitutedArguments = originalArguments;
- if (originalArguments != null) {
- if (substitution.isRawSubstitution()) {
- return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
- }
- substitutedArguments = substitute(substitution, originalArguments);
- }
- if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) { //$IDENTITY-COMPARISON$
- return originalParameterizedType.environment.createParameterizedType(
- originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
- }
- break;
-
- case Binding.ARRAY_TYPE:
- ArrayBinding originalArrayType = (ArrayBinding) originalType;
- TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
- TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type, TODO(Srikanth): need a test case.
- if (substitute != originalLeafComponentType) { //$IDENTITY-COMPARISON$
- return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions(), originalType.getTypeAnnotations());
- }
- break;
-
- case Binding.WILDCARD_TYPE:
- case Binding.INTERSECTION_TYPE:
- WildcardBinding wildcard = (WildcardBinding) originalType;
- if (wildcard.boundKind != Wildcard.UNBOUND) {
- TypeBinding originalBound = wildcard.bound;
- TypeBinding substitutedBound = substitute(substitution, originalBound);
- TypeBinding[] originalOtherBounds = wildcard.otherBounds;
- TypeBinding[] substitutedOtherBounds = substitute(substitution, originalOtherBounds);
- if (substitutedBound != originalBound || originalOtherBounds != substitutedOtherBounds) { //$IDENTITY-COMPARISON$
- if (originalOtherBounds != null) {
- /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=347145: the constituent intersecting types have changed
- in the last round of substitution. Reevaluate the composite intersection type, as there is a possibility
- of the intersection collapsing into one of the constituents, the other being fully subsumed.
- */
- TypeBinding [] bounds = new TypeBinding[1 + substitutedOtherBounds.length];
- bounds[0] = substitutedBound;
- System.arraycopy(substitutedOtherBounds, 0, bounds, 1, substitutedOtherBounds.length);
- TypeBinding[] glb = Scope.greaterLowerBound(bounds, null, substitution.environment()); // re-evaluate
- if (glb != null && glb != bounds) {
- substitutedBound = glb[0];
- if (glb.length == 1) {
- substitutedOtherBounds = null;
- } else {
- System.arraycopy(glb, 1, substitutedOtherBounds = new TypeBinding[glb.length - 1], 0, glb.length - 1);
- }
- }
- }
- return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind, wildcard.getTypeAnnotations());
- }
- }
- break;
-
- case Binding.TYPE:
- if (!originalType.isMemberType()) break;
- ReferenceBinding originalReferenceType = (ReferenceBinding) originalType;
- originalEnclosing = originalType.enclosingType();
- substitutedEnclosing = originalEnclosing;
- if (originalEnclosing != null) {
- substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
- if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
- }
-
- // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
- if (substitutedEnclosing != originalEnclosing) { //$IDENTITY-COMPARISON$
- return substitution.isRawSubstitution()
- ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations())
- : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing, originalType.getTypeAnnotations());
- }
- break;
- case Binding.GENERIC_TYPE:
- originalReferenceType = (ReferenceBinding) originalType;
- originalEnclosing = originalType.enclosingType();
- substitutedEnclosing = originalEnclosing;
- if (originalEnclosing != null) {
- substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
- if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
- }
-
- if (substitution.isRawSubstitution()) {
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
- }
- // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
- originalArguments = originalReferenceType.typeVariables();
- substitutedArguments = substitute(substitution, originalArguments);
- return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
- }
- return originalType;
- }
-
- private static boolean isMemberTypeOfRaw(TypeBinding originalType, ReferenceBinding substitutedEnclosing) {
- // 4.8:
- // "a raw type is defined to be one of:
- // ...
- // * A non-static member type of a raw type R that is not
- // inherited from a superclass or superinterface of R."
-
- // Due to staticness, e.g., Map.Entry<String,Object> is *not* considered as a raw type
-
- return (substitutedEnclosing != null && substitutedEnclosing.isRawType())
- && ((originalType instanceof ReferenceBinding) && !((ReferenceBinding)originalType).isStatic());
+ return defaultSubstitutor.substitute(substitution, originalType);
}
/**
@@ -544,21 +407,193 @@ public abstract class Scope {
* Only allocate an array if anything is different.
*/
public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
- if (originalTypes == null) return null;
- TypeBinding[] substitutedTypes = originalTypes;
- for (int i = 0, length = originalTypes.length; i < length; i++) {
- TypeBinding originalType = originalTypes[i];
- TypeBinding substitutedParameter = substitute(substitution, originalType);
- if (substitutedParameter != originalType) { //$IDENTITY-COMPARISON$
- if (substitutedTypes == originalTypes) {
- System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
- }
- substitutedTypes[i] = substitutedParameter;
- } else if (substitutedTypes != originalTypes) {
- substitutedTypes[i] = originalType;
- }
- }
- return substitutedTypes;
+ return defaultSubstitutor.substitute(substitution, originalTypes);
+ }
+
+ /** Bridge to non-static implementation in {@link Substitutor}, to make methods overridable. */
+ private static Substitutor defaultSubstitutor = new Substitutor();
+ public static class Substitutor {
+ /**
+ * Returns an array of types, where original types got substituted given a substitution.
+ * Only allocate an array if anything is different.
+ */
+ public ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
+ if (originalTypes == null) return null;
+ ReferenceBinding[] substitutedTypes = originalTypes;
+ for (int i = 0, length = originalTypes.length; i < length; i++) {
+ ReferenceBinding originalType = originalTypes[i];
+ TypeBinding substitutedType = substitute(substitution, originalType);
+ if (!(substitutedType instanceof ReferenceBinding)) {
+ return null; // impossible substitution
+ }
+ if (substitutedType != originalType) { //$IDENTITY-COMPARISON$
+ if (substitutedTypes == originalTypes) {
+ System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
+ }
+ substitutedTypes[i] = (ReferenceBinding)substitutedType;
+ } else if (substitutedTypes != originalTypes) {
+ substitutedTypes[i] = originalType;
+ }
+ }
+ return substitutedTypes;
+ }
+
+ /**
+ * Returns a type, where original type was substituted using the receiver
+ * parameterized type.
+ * In raw mode (see {@link Substitution#isRawSubstitution()}),
+ * all parameterized types are converted to raw types.
+ * Cf. 4.8: "The type of a constructor (8.8), instance method (8.4, 9.4),
+ * or non-static field (8.3) M of a raw type C that is not inherited from its
+ * superclasses or superinterfaces is the raw type that corresponds to the erasure
+ * of its type in the generic declaration corresponding to C."
+ */
+ public TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
+ if (originalType == null) return null;
+
+ switch (originalType.kind()) {
+
+ case Binding.TYPE_PARAMETER:
+ return substitution.substitute((TypeVariableBinding) originalType);
+
+ case Binding.PARAMETERIZED_TYPE:
+ ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+ ReferenceBinding originalEnclosing = originalType.enclosingType();
+ ReferenceBinding substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
+ if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
+ return originalParameterizedType.environment.createRawType(
+ originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ TypeBinding[] originalArguments = originalParameterizedType.arguments;
+ TypeBinding[] substitutedArguments = originalArguments;
+ if (originalArguments != null) {
+ if (substitution.isRawSubstitution()) {
+ return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ substitutedArguments = substitute(substitution, originalArguments);
+ }
+ if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) { //$IDENTITY-COMPARISON$
+ return originalParameterizedType.environment.createParameterizedType(
+ originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ break;
+
+ case Binding.ARRAY_TYPE:
+ ArrayBinding originalArrayType = (ArrayBinding) originalType;
+ TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
+ TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type, TODO(Srikanth): need a test case.
+ if (substitute != originalLeafComponentType) { //$IDENTITY-COMPARISON$
+ return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions(), originalType.getTypeAnnotations());
+ }
+ break;
+
+ case Binding.WILDCARD_TYPE:
+ case Binding.INTERSECTION_TYPE:
+ WildcardBinding wildcard = (WildcardBinding) originalType;
+ if (wildcard.boundKind != Wildcard.UNBOUND) {
+ TypeBinding originalBound = wildcard.bound;
+ TypeBinding substitutedBound = substitute(substitution, originalBound);
+ TypeBinding[] originalOtherBounds = wildcard.otherBounds;
+ TypeBinding[] substitutedOtherBounds = substitute(substitution, originalOtherBounds);
+ if (substitutedBound != originalBound || originalOtherBounds != substitutedOtherBounds) { //$IDENTITY-COMPARISON$
+ if (originalOtherBounds != null) {
+ /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=347145: the constituent intersecting types have changed
+ in the last round of substitution. Reevaluate the composite intersection type, as there is a possibility
+ of the intersection collapsing into one of the constituents, the other being fully subsumed.
+ */
+ TypeBinding [] bounds = new TypeBinding[1 + substitutedOtherBounds.length];
+ bounds[0] = substitutedBound;
+ System.arraycopy(substitutedOtherBounds, 0, bounds, 1, substitutedOtherBounds.length);
+ TypeBinding[] glb = Scope.greaterLowerBound(bounds, null, substitution.environment()); // re-evaluate
+ if (glb != null && glb != bounds) {
+ substitutedBound = glb[0];
+ if (glb.length == 1) {
+ substitutedOtherBounds = null;
+ } else {
+ System.arraycopy(glb, 1, substitutedOtherBounds = new TypeBinding[glb.length - 1], 0, glb.length - 1);
+ }
+ }
+ }
+ return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind, wildcard.getTypeAnnotations());
+ }
+ }
+ break;
+
+ case Binding.TYPE:
+ if (!originalType.isMemberType()) break;
+ ReferenceBinding originalReferenceType = (ReferenceBinding) originalType;
+ originalEnclosing = originalType.enclosingType();
+ substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
+ if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+
+ // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
+ if (substitutedEnclosing != originalEnclosing) { //$IDENTITY-COMPARISON$
+ return substitution.isRawSubstitution()
+ ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations())
+ : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ break;
+ case Binding.GENERIC_TYPE:
+ originalReferenceType = (ReferenceBinding) originalType;
+ originalEnclosing = originalType.enclosingType();
+ substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
+ if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+
+ if (substitution.isRawSubstitution()) {
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
+ originalArguments = originalReferenceType.typeVariables();
+ substitutedArguments = substitute(substitution, originalArguments);
+ return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
+ }
+ return originalType;
+ }
+
+ private static boolean isMemberTypeOfRaw(TypeBinding originalType, ReferenceBinding substitutedEnclosing) {
+ // 4.8:
+ // "a raw type is defined to be one of:
+ // ...
+ // * A non-static member type of a raw type R that is not
+ // inherited from a superclass or superinterface of R."
+
+ // Due to staticness, e.g., Map.Entry<String,Object> is *not* considered as a raw type
+
+ return (substitutedEnclosing != null && substitutedEnclosing.isRawType())
+ && ((originalType instanceof ReferenceBinding) && !((ReferenceBinding)originalType).isStatic());
+ }
+
+ /**
+ * Returns an array of types, where original types got substituted given a substitution.
+ * Only allocate an array if anything is different.
+ */
+ public TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
+ if (originalTypes == null) return null;
+ TypeBinding[] substitutedTypes = originalTypes;
+ for (int i = 0, length = originalTypes.length; i < length; i++) {
+ TypeBinding originalType = originalTypes[i];
+ TypeBinding substitutedParameter = substitute(substitution, originalType);
+ if (substitutedParameter != originalType) { //$IDENTITY-COMPARISON$
+ if (substitutedTypes == originalTypes) {
+ System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
+ }
+ substitutedTypes[i] = substitutedParameter;
+ } else if (substitutedTypes != originalTypes) {
+ substitutedTypes[i] = originalType;
+ }
+ }
+ return substitutedTypes;
+ }
}
/*

Back to the top