Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2013-12-03 11:34:51 +0000
committerStephan Herrmann2013-12-03 11:34:51 +0000
commita6234b6d34f70b04dc8086b5971307bab5f2f8ed (patch)
treea410eb9689a6c8a2365d9aa9b5b8635d8a3703ae
parent564744a51fe27e3b0533ebc8bf859ffbedefd30b (diff)
downloadeclipse.jdt.core-a6234b6d34f70b04dc8086b5971307bab5f2f8ed.tar.gz
eclipse.jdt.core-a6234b6d34f70b04dc8086b5971307bab5f2f8ed.tar.xz
eclipse.jdt.core-a6234b6d34f70b04dc8086b5971307bab5f2f8ed.zip
Draft impl of reduction for lambda constraints.
- based on some new API in LE Improve LE.isPertinentToApplicability() to fix NLET.test401610d()
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java2
-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/ConstraintExceptionFormula.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java8
6 files changed, 80 insertions, 25 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 64b7a2379b..7de8492124 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -649,8 +649,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
this.expressionContext = context;
}
- public boolean isPertinentToApplicability(TypeBinding targetType) {
- return this.valueIfTrue.isPertinentToApplicability(targetType) && this.valueIfFalse.isPertinentToApplicability(targetType);
+ public boolean isPertinentToApplicability(TypeBinding targetType, MethodBinding method) {
+ return this.valueIfTrue.isPertinentToApplicability(targetType, method)
+ && this.valueIfFalse.isPertinentToApplicability(targetType, method);
}
public boolean isPolyExpression() throws UnsupportedOperationException {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 66d19e6b7f..d8199823b0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -949,7 +949,7 @@ public Constant optimizedBooleanConstant() {
return this.constant;
}
-public boolean isPertinentToApplicability(TypeBinding targetType) {
+public boolean isPertinentToApplicability(TypeBinding targetType, MethodBinding method) {
return true;
}
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 6feefbd72e..66e4c803e4 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
@@ -56,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
@@ -108,6 +109,10 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
return this.body;
}
+ public Expression[] resultExpressions() {
+ return this.resultExpressions;
+ }
+
public void setArrowPosition(int arrowPosition) {
this.arrowPosition = arrowPosition;
}
@@ -443,32 +448,37 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
}
}
- public boolean isPertinentToApplicability(TypeBinding targetType) {
- if (targetType == null)
- return true;
-
- // Add the rule about type variable of the generic method.
-
- final MethodBinding sam = targetType.getSingleAbstractMethod(this.enclosingScope); // cached/cheap call.
-
- if (sam == null || !sam.isValidBinding())
- return true;
-
- if (sam.parameters.length != this.argumentTypes.length)
+ public boolean isPertinentToApplicability(TypeBinding targetType, MethodBinding method) {
+ if (targetType == null) // assumed to signal another primary error
return true;
if (argumentsTypeElided())
return false;
+ if (targetType instanceof TypeVariableBinding && ((TypeVariableBinding)targetType).declaringElement == method)
+ return false;
+
Expression [] returnExpressions = this.resultExpressions;
for (int i = 0, length = returnExpressions.length; i < length; i++) {
- if (!returnExpressions[i].isPertinentToApplicability(targetType))
+ if (!returnExpressions[i].isPertinentToApplicability(targetType, method))
return false;
}
return true;
}
+ public boolean isVoidCompatible() {
+ if (!this.shapeAnalysisComplete)
+ throw new IllegalStateException("asking isVoidCompatible before shape analysis is complete");
+ return this.voidCompatible;
+ }
+
+ public boolean isValueCompatible() {
+ if (!this.shapeAnalysisComplete)
+ throw new IllegalStateException("asking isValueCompatible before shape analysis is complete");
+ return this.valueCompatible;
+ }
+
public StringBuffer printExpression(int tab, StringBuffer output) {
int parenthesesCount = (this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
String suffix = ""; //$NON-NLS-1$
@@ -561,7 +571,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
}
// Do not proceed with data/control flow analysis if resolve encountered errors.
if (type == null || !type.isValidBinding() || this.hasIgnoredMandatoryErrors || enclosingScopesHaveErrors()) {
- if (!isPertinentToApplicability(left))
+ if (!isPertinentToApplicability(left, null)) // FIXME is null OK?
return true;
return this.arguments.length == 0; // error not because of the target type imposition, but is inherent. Just say compatible since errors in body aren't to influence applicability.
}
@@ -578,7 +588,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
}
}
- if (!isPertinentToApplicability(left))
+ if (!isPertinentToApplicability(left, null)) // FIXME is null OK?
return true;
if (sam.returnType.id == TypeIds.T_void) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java
index 22bd7a7ca7..1bcb9b5988 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java
@@ -67,7 +67,8 @@ public class ConstraintExceptionFormula extends ConstraintFormula {
if (this.left instanceof LambdaExpression) {
// TODO find exceptions thrown by the lambda's body
// ((LambdaExpression)this.left).
- InferenceContext18.missingImplementation("NYI");
+// InferenceContext18.missingImplementation("NYI");
+ return TRUE;
} else {
ReferenceExpression referenceExpression = (ReferenceExpression)this.left;
// TODO: can we avoid this resolve() (which in turn may invoke inference)?
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 b4d8ce281a..34926ed6b3 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
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Set;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
@@ -88,7 +89,49 @@ class ConstraintExpressionFormula extends ConstraintFormula {
} else if (this.left instanceof ConditionalExpression) {
InferenceContext18.missingImplementation("NYI");
} else if (this.left instanceof LambdaExpression) {
- InferenceContext18.missingImplementation("NYI");
+ LambdaExpression lambda = (LambdaExpression) this.left;
+ Scope scope = inferenceContext.scope;
+ TypeBinding t = this.right;
+ if (!t.isFunctionalInterface(scope))
+ return FALSE;
+ MethodBinding functionType = t.getSingleAbstractMethod(scope);
+ if (functionType == null)
+ return FALSE;
+ TypeBinding[] parameters = functionType.parameters;
+ if (parameters.length != lambda.arguments().length)
+ return FALSE;
+ if (lambda.argumentsTypeElided())
+ for (int i = 0; i < parameters.length; i++)
+ if (!parameters[i].isProperType(true))
+ return FALSE;
+ // FIXME: force shape analysis:
+ lambda.isCompatibleWith(t, scope);
+ if (functionType.returnType == TypeBinding.VOID) {
+ if (!lambda.isVoidCompatible())
+ return FALSE;
+ } else {
+ if (!lambda.isValueCompatible())
+ return FALSE;
+ }
+ List result = new ArrayList();
+ if (!lambda.argumentsTypeElided()) {
+ Argument[] arguments = lambda.arguments();
+ for (int i = 0; i < parameters.length; i++)
+ result.add(new ConstraintTypeFormula(parameters[i], arguments[i].type.resolvedType, SAME));
+ }
+ if (functionType.returnType != TypeBinding.VOID) {
+ TypeBinding r = functionType.returnType;
+ if (lambda.body() instanceof Expression) {
+ result.add(new ConstraintExpressionFormula((Expression)lambda.body(), r, COMPATIBLE));
+ } else {
+ Expression[] exprs = lambda.resultExpressions();
+ for (int i = 0; i < exprs.length; i++)
+ result.add(new ConstraintExpressionFormula(exprs[i], r, COMPATIBLE));
+ }
+ }
+ if (result.size() == 0)
+ return TRUE;
+ return result.toArray(new ConstraintFormula[result.size()]);
} else if (this.left instanceof ReferenceExpression) {
return reduceReferenceExpressionCompatibility((ReferenceExpression) this.left, inferenceContext);
}
@@ -157,7 +200,7 @@ class ConstraintExpressionFormula extends ConstraintFormula {
int varArgPos = paramLength-1;
varArgsType = method.parameters[varArgPos];
}
- inferenceContext.createInitialConstraintsForParameters(parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType);
+ inferenceContext.createInitialConstraintsForParameters(parameters, checkType==InferenceContext18.CHECK_VARARG, varArgsType, method);
inferenceContext.addThrowsContraints(typeVariables, inferenceVariables, method.thrownExceptions);
}
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 e6f383db6e..ade0bead61 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
@@ -100,7 +100,7 @@ public class InferenceContext18 {
}
/** JLS 18.5.1: compute bounds from formal and actual parameters. */
- public void createInitialConstraintsForParameters(TypeBinding[] parameters, boolean checkVararg, TypeBinding varArgsType) {
+ public void createInitialConstraintsForParameters(TypeBinding[] parameters, boolean checkVararg, TypeBinding varArgsType, MethodBinding method) {
// TODO discriminate strict vs. loose invocations
if (this.invocationArguments == null)
return;
@@ -116,7 +116,7 @@ public class InferenceContext18 {
this.initialConstraints=new ConstraintFormula[maxConstraints], 0, numConstraints);
}
for (int i = 0; i < len; i++) {
- if (this.invocationArguments[i].isPertinentToApplicability(parameters[i])) {
+ if (this.invocationArguments[i].isPertinentToApplicability(parameters[i], method)) {
TypeBinding thetaF = substitute(parameters[i]);
this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.COMPATIBLE);
}
@@ -124,7 +124,7 @@ public class InferenceContext18 {
if (checkVararg && varArgsType instanceof ArrayBinding) {
TypeBinding thetaF = substitute(((ArrayBinding) varArgsType).elementsType());
for (int i = len; i < this.invocationArguments.length; i++) {
- if (this.invocationArguments[i].isPertinentToApplicability(varArgsType)) {
+ if (this.invocationArguments[i].isPertinentToApplicability(varArgsType, method)) {
this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.COMPATIBLE);
}
}
@@ -236,7 +236,7 @@ public class InferenceContext18 {
TypeBinding fsi = fs[Math.min(i, p-1)];
TypeBinding substF = substitute(fsi);
// For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
- if (!arguments[i].isPertinentToApplicability(fsi)) {
+ if (!arguments[i].isPertinentToApplicability(fsi, method)) {
c.add(new ConstraintExpressionFormula(arguments[i], substF, ReductionResult.COMPATIBLE));
}
c.add(new ConstraintExceptionFormula(arguments[i], substF));

Back to the top