Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2014-02-22 00:52:39 +0000
committerStephan Herrmann2014-02-22 15:32:08 +0000
commit8bffc680730baeb75a0764c02d5d9479eee4502e (patch)
treea8cd90fbdb8671a95a0964e849c8ec8838ca35ff
parenta2a25daab3f792071cba7e3d51c3d2abf00c6c2a (diff)
downloadeclipse.jdt.core-8bffc680730baeb75a0764c02d5d9479eee4502e.tar.gz
eclipse.jdt.core-8bffc680730baeb75a0764c02d5d9479eee4502e.tar.xz
eclipse.jdt.core-8bffc680730baeb75a0764c02d5d9479eee4502e.zip
Bug 428786 - [1.8][compiler] Inference needs to compute the "ground
target type" when reducing a lambda compatibility constraint - preparatory refactoring
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java40
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java134
3 files changed, 100 insertions, 80 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index 8ac877d10f..377e41f1f2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -31,6 +31,7 @@
* Bug 420525 - [1.8] [compiler] Incorrect error "The type Integer does not define sum(Object, Object) that is applicable here"
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
* Bug 428294 - [1.8][compiler] Type mismatch: cannot convert from List<Object> to Collection<Object[]>
+ * Bug 428786 - [1.8][compiler] Inference needs to compute the "ground target type" when reducing a lambda compatibility constraint
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
*******************************************************************************/
@@ -128,6 +129,10 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
return this.arguments;
}
+ public TypeBinding[] argumentTypes() {
+ return this.argumentTypes;
+ }
+
public void setBody(Statement body) {
this.body = body == null ? NO_BODY : body;
}
@@ -414,32 +419,23 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
return null;
ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(targetType);
if (withWildCards != null) {
- ReferenceBinding genericType = withWildCards.genericType();
- if (!argumentTypesElided) {
- // invoke 18.5.3 Functional Interface Parameterization Inference
- InferenceContext18 ctx = new InferenceContext18(blockScope);
- TypeBinding[] q = ctx.createBoundsForFunctionalInterfaceParameterizationInference(withWildCards);
- if (q == null || q.length != this.arguments.length) {
- // fail TODO: can this still happen here?
- } else {
- if (ctx.reduceWithEqualityConstraints(this.argumentTypes, q)) {
- TypeBinding[] a = withWildCards.arguments; // a is not-null by construction of parameterizedWithWildcard()
- TypeBinding[] aprime = ctx.getFunctionInterfaceArgumentSolutions(a);
- // TODO If F<A'1, ..., A'm> is a well-formed type, ...
- return blockScope.environment().createParameterizedType(genericType, aprime, genericType.enclosingType());
- }
- }
- } else {
- // non-wildcard parameterization (9.8) of the target type
- TypeBinding[] types = withWildCards.getNonWildcardParameterization(blockScope);
- if (types == null)
- return null;
- return blockScope.environment().createParameterizedType(genericType, types, genericType.enclosingType());
- }
+ if (!argumentTypesElided)
+ return new InferenceContext18(blockScope).inferFunctionalInterfaceParameterization(this, blockScope, withWildCards);
+ else
+ return findGroundTargetTypeForElidedLambda(blockScope, withWildCards);
}
return targetType;
}
+ public ReferenceBinding findGroundTargetTypeForElidedLambda(BlockScope blockScope, ParameterizedTypeBinding withWildCards) {
+ // non-wildcard parameterization (9.8) of the target type
+ TypeBinding[] types = withWildCards.getNonWildcardParameterization(blockScope);
+ if (types == null)
+ return null;
+ ReferenceBinding genericType = withWildCards.genericType();
+ return blockScope.environment().createParameterizedType(genericType, types, genericType.enclosingType());
+ }
+
public boolean argumentsTypeElided() {
return this.arguments.length > 0 && this.arguments[0].hasElidedType();
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
index 147833153d..4140548a6e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java
@@ -33,7 +33,7 @@ import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.InvocationRecord;
+import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18.SuspendedInferenceRecord;
/**
* Implementation of 18.1.2 in JLS8, case:
@@ -114,7 +114,7 @@ class ConstraintExpressionFormula extends ConstraintFormula {
// avoid original(), since we only want to discard one level of instantiation
// (method type variables - not class type variables)!
method = previousMethod.shallowOriginal();
- InvocationRecord prevInvocation = inferenceContext.enterPolyInvocation(invocation, invocation.arguments());
+ SuspendedInferenceRecord prevInvocation = inferenceContext.enterPolyInvocation(invocation, invocation.arguments());
// Invocation Applicability Inference: 18.5.1 & Invocation Type Inference: 18.5.2
try {
@@ -282,7 +282,7 @@ class ConstraintExpressionFormula extends ConstraintFormula {
&& ((original.typeVariables() != Binding.NO_TYPE_VARIABLES && r.mentionsAny(original.typeVariables(), -1))
|| (original.isConstructor() && original.declaringClass.typeVariables() != Binding.NO_TYPE_VARIABLES && r.mentionsAny(original.declaringClass.typeVariables(), -1))))
{
- InvocationRecord prevInvocation = inferenceContext.enterPolyInvocation(reference, null/*no invocation arguments available*/);
+ SuspendedInferenceRecord prevInvocation = inferenceContext.enterPolyInvocation(reference, null/*no invocation arguments available*/);
// Invocation Applicability Inference: 18.5.1 & Invocation Type Inference: 18.5.2
try {
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 0cd9f4d311..eaae4c3ffd 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
@@ -204,12 +204,12 @@ public class InferenceContext18 {
public static final int CHECK_LOOSE = 2;
public static final int CHECK_VARARG = 3;
- static class InvocationRecord {
+ static class SuspendedInferenceRecord {
InvocationSite site;
Expression[] invocationArguments;
InferenceVariable[] inferenceVariables;
int inferenceKind;
- InvocationRecord(InvocationSite site, Expression[] invocationArguments, InferenceVariable[] inferenceVariables, int inferenceKind) {
+ SuspendedInferenceRecord(InvocationSite site, Expression[] invocationArguments, InferenceVariable[] inferenceVariables, int inferenceKind) {
this.site = site;
this.invocationArguments = invocationArguments;
this.inferenceVariables = inferenceVariables;
@@ -596,6 +596,80 @@ public class InferenceContext18 {
}
/**
+ * 18.5.3 Functional Interface Parameterization Inference
+ */
+ public ReferenceBinding inferFunctionalInterfaceParameterization(LambdaExpression lambda, BlockScope blockScope,
+ ParameterizedTypeBinding targetTypeWithWildCards)
+ {
+ TypeBinding[] q = createBoundsForFunctionalInterfaceParameterizationInference(targetTypeWithWildCards);
+ if (q == null || q.length != lambda.arguments().length) {
+ // fail TODO: can this still happen here?
+ } else {
+ if (reduceWithEqualityConstraints(lambda.argumentTypes(), q)) {
+ ReferenceBinding genericType = targetTypeWithWildCards.genericType();
+ TypeBinding[] a = targetTypeWithWildCards.arguments; // a is not-null by construction of parameterizedWithWildcard()
+ TypeBinding[] aprime = getFunctionInterfaceArgumentSolutions(a);
+ // TODO If F<A'1, ..., A'm> is a well-formed type, ...
+ return blockScope.environment().createParameterizedType(genericType, aprime, genericType.enclosingType());
+ }
+ }
+ return targetTypeWithWildCards;
+ }
+
+ /**
+ * Create initial bound set for 18.5.3 Functional Interface Parameterization Inference
+ * @param functionalInterface the functional interface F<A1,..Am>
+ * @return the parameter types Q1..Qk of the function type of the type F<α1, ..., αm>, or null
+ */
+ TypeBinding[] createBoundsForFunctionalInterfaceParameterizationInference(ParameterizedTypeBinding functionalInterface) {
+ if (this.currentBounds == null)
+ this.currentBounds = new BoundSet();
+ TypeBinding[] a = functionalInterface.arguments;
+ if (a == null)
+ return null;
+ InferenceVariable[] alpha = addInitialTypeVariableSubstitutions(a);
+
+ for (int i = 0; i < a.length; i++) {
+ TypeBound bound;
+ if (a[i].kind() == Binding.WILDCARD_TYPE) {
+ WildcardBinding wildcard = (WildcardBinding) a[i];
+ switch(wildcard.boundKind) {
+ case Wildcard.EXTENDS :
+ bound = new TypeBound(alpha[i], wildcard.allBounds(), ReductionResult.SUBTYPE);
+ break;
+ case Wildcard.SUPER :
+ bound = new TypeBound(alpha[i], wildcard.bound, ReductionResult.SUPERTYPE);
+ break;
+ case Wildcard.UNBOUND :
+ bound = new TypeBound(alpha[i], this.object, ReductionResult.SUBTYPE);
+ break;
+ default:
+ continue; // cannot
+ }
+ } else {
+ bound = new TypeBound(alpha[i], a[i], ReductionResult.SAME);
+ }
+ this.currentBounds.addBound(bound);
+ }
+ TypeBinding falpha = substitute(functionalInterface);
+ return falpha.getSingleAbstractMethod(this.scope, true).parameters;
+ }
+
+ public boolean reduceWithEqualityConstraints(TypeBinding[] p, TypeBinding[] q) {
+ if (p != null) {
+ for (int i = 0; i < p.length; i++) {
+ try {
+ if (!this.reduceAndIncorporate(new ConstraintTypeFormula(p[i], q[i], ReductionResult.SAME)))
+ return false;
+ } catch (InferenceFailureException e) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
* 18.5.4 More Specific Method Inference
*/
public boolean isMoreSpecificThan(MethodBinding m1, MethodBinding m2, boolean isVarArgs, boolean isVarArgs2) {
@@ -1260,8 +1334,8 @@ public class InferenceContext18 {
return types;
}
- public InvocationRecord enterPolyInvocation(InvocationSite invocation, Expression[] innerArguments) {
- InvocationRecord record = new InvocationRecord(this.currentInvocation, this.invocationArguments, this.inferenceVariables, this.inferenceKind);
+ public SuspendedInferenceRecord enterPolyInvocation(InvocationSite invocation, Expression[] innerArguments) {
+ SuspendedInferenceRecord record = new SuspendedInferenceRecord(this.currentInvocation, this.invocationArguments, this.inferenceVariables, this.inferenceKind);
this.inferenceVariables = null;
this.invocationArguments = innerArguments;
this.currentInvocation = invocation;
@@ -1271,7 +1345,7 @@ public class InferenceContext18 {
return record;
}
- public void leavePolyInvocation(InvocationRecord record) {
+ public void leavePolyInvocation(SuspendedInferenceRecord record) {
// merge inference variables:
if (this.inferenceVariables == null) { // no new ones, assume we aborted prematurely
this.inferenceVariables = record.inferenceVariables;
@@ -1530,56 +1604,6 @@ public class InferenceContext18 {
return null;
}
- /**
- * Create initial bound set for 18.5.3 Functional Interface Parameterization Inference
- * @param functionalInterface the functional interface F<A1,..Am>
- * @return the parameter types Q1..Qk of the function type of the type F<α1, ..., αm>, or null
- */
- public TypeBinding[] createBoundsForFunctionalInterfaceParameterizationInference(ParameterizedTypeBinding functionalInterface) {
- this.currentBounds = new BoundSet();
- TypeBinding[] a = functionalInterface.arguments;
- if (a == null)
- return null;
- InferenceVariable[] alpha = addInitialTypeVariableSubstitutions(a);
-
- for (int i = 0; i < a.length; i++) {
- TypeBound bound;
- if (a[i].kind() == Binding.WILDCARD_TYPE) {
- WildcardBinding wildcard = (WildcardBinding) a[i];
- switch(wildcard.boundKind) {
- case Wildcard.EXTENDS :
- bound = new TypeBound(alpha[i], wildcard.allBounds(), ReductionResult.SUBTYPE);
- break;
- case Wildcard.SUPER :
- bound = new TypeBound(alpha[i], wildcard.bound, ReductionResult.SUPERTYPE);
- break;
- case Wildcard.UNBOUND :
- bound = new TypeBound(alpha[i], this.object, ReductionResult.SUBTYPE);
- break;
- default:
- continue; // cannot
- }
- } else {
- bound = new TypeBound(alpha[i], a[i], ReductionResult.SAME);
- }
- this.currentBounds.addBound(bound);
- }
- TypeBinding falpha = substitute(functionalInterface);
- return falpha.getSingleAbstractMethod(this.scope, true).parameters;
- }
-
- public boolean reduceWithEqualityConstraints(TypeBinding[] p, TypeBinding[] q) {
- for (int i = 0; i < p.length; i++) {
- try {
- if (!this.reduceAndIncorporate(new ConstraintTypeFormula(p[i], q[i], ReductionResult.SAME)))
- return false;
- } catch (InferenceFailureException e) {
- return false;
- }
- }
- return true;
- }
-
public TypeBinding[] getFunctionInterfaceArgumentSolutions(TypeBinding[] a) {
int m = a.length;
TypeBinding[] aprime = new TypeBinding[m];

Back to the top