Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2013-11-28 16:03:36 +0000
committerStephan Herrmann2013-11-28 18:57:45 +0000
commit8aacdef17884eddfbe4320c6f762917685361bbf (patch)
treef192f24f4b10479ab8588ba2fb2a4a2084bb74bf
parente85410de79e3d5d97acffcb7c908ab174f98aad3 (diff)
downloadeclipse.jdt.core-8aacdef17884eddfbe4320c6f762917685361bbf.tar.gz
eclipse.jdt.core-8aacdef17884eddfbe4320c6f762917685361bbf.tar.xz
eclipse.jdt.core-8aacdef17884eddfbe4320c6f762917685361bbf.zip
Make the code look even more like the spec, explicitly using boundset b1
rather then left-over currentBounds. Disable fallback to old inference on one path. Let unsatisfiable glb simply cause inference failure (was: NPE).
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java160
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java13
2 files changed, 89 insertions, 84 deletions
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 1c3c3c10d9..616c8da05e 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
@@ -146,81 +146,89 @@ public class InferenceContext18 {
ConstraintExpressionFormula.inferInvocationApplicability(this, method, arguments);
}
- /** JLS 18.5.2 Invocation Type Inference */
- public BoundSet inferInvocationType(TypeBinding expectedType, InvocationSite invocationSite, MethodBinding method, int checkKind)
+ /** JLS 18.5.2 Invocation Type Inference
+ * @param b1 "the bound set produced by reduction in order to demonstrate that m is applicable in 18.5.1"
+ */
+ public BoundSet inferInvocationType(BoundSet b1, TypeBinding expectedType, InvocationSite invocationSite, MethodBinding method, int checkKind)
throws InferenceFailureException
{
- // bullets 1&2: definitions only.
- if (expectedType != null
- && expectedType != TypeBinding.VOID
- && invocationSite instanceof Expression
- && ((Expression)invocationSite).isPolyExpression(method))
- {
- // 3. bullet: special treatment for poly expressions
- if (!ConstraintExpressionFormula.inferPolyInvocationType(this, invocationSite, expectedType, method)) {
- return null;
- }
- }
- // 4. bullet: assemble C:
- TypeBinding[] fs;
- Expression[] arguments = this.invocationArguments;
- Set c = new HashSet();
- if (arguments != null) {
- int k = arguments.length;
- int p = method.parameters.length;
- switch (checkKind) {
- case CHECK_STRICT:
- case CHECK_LOOSE:
- fs = method.parameters;
- break;
- case CHECK_VARARG:
- fs = varArgTypes(method.parameters, k);
- break;
- default:
- throw new IllegalStateException("Unexpected checkKind "+checkKind); //$NON-NLS-1$
- }
- for (int i = 0; i < k; i++) {
- TypeBinding substF = substitute(fs[Math.min(i, p-1)]);
- // For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
- if (!arguments[i].isPertinentToApplicability()) {
- c.add(new ConstraintExpressionFormula(arguments[i], substF, ReductionResult.COMPATIBLE));
+ BoundSet previous = this.currentBounds;
+ this.currentBounds = b1;
+ try {
+ // bullets 1&2: definitions only.
+ if (expectedType != null
+ && expectedType != TypeBinding.VOID
+ && invocationSite instanceof Expression
+ && ((Expression)invocationSite).isPolyExpression(method))
+ {
+ // 3. bullet: special treatment for poly expressions
+ if (!ConstraintExpressionFormula.inferPolyInvocationType(this, invocationSite, expectedType, method)) {
+ return null;
}
- c.add(new ConstraintExceptionFormula(arguments[i], substF));
}
- }
- // 5. bullet: determine B3 from C
- while (!c.isEmpty()) {
- // *
- Set bottomSet = findBottomSet(c, allOutputVariables(c));
- if (bottomSet.isEmpty()) {
- bottomSet.add(pickFromCycle(c));
- }
- // *
- c.removeAll(bottomSet);
- // * The union of the input variables of all the selected constraints, α1, ..., αm, ...
- Set allInputs = new HashSet();
- Iterator bottomIt = bottomSet.iterator();
- while (bottomIt.hasNext()) {
- allInputs.addAll(((ConstraintFormula)bottomIt.next()).inputVariables(this));
+ // 4. bullet: assemble C:
+ TypeBinding[] fs;
+ Expression[] arguments = this.invocationArguments;
+ Set c = new HashSet();
+ if (arguments != null) {
+ int k = arguments.length;
+ int p = method.parameters.length;
+ switch (checkKind) {
+ case CHECK_STRICT:
+ case CHECK_LOOSE:
+ fs = method.parameters;
+ break;
+ case CHECK_VARARG:
+ fs = varArgTypes(method.parameters, k);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected checkKind "+checkKind); //$NON-NLS-1$
+ }
+ for (int i = 0; i < k; i++) {
+ TypeBinding substF = substitute(fs[Math.min(i, p-1)]);
+ // For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
+ if (!arguments[i].isPertinentToApplicability()) {
+ c.add(new ConstraintExpressionFormula(arguments[i], substF, ReductionResult.COMPATIBLE));
+ }
+ c.add(new ConstraintExceptionFormula(arguments[i], substF));
+ }
}
- InferenceVariable[] variablesArray = (InferenceVariable[]) allInputs.toArray(new InferenceVariable[allInputs.size()]);
- // ... is resolved
- BoundSet solution = resolve();
- // * ~ apply substitutions to all constraints:
- bottomIt = bottomSet.iterator();
- while (bottomIt.hasNext()) {
- ConstraintFormula constraint = ((ConstraintFormula)bottomIt.next());
- constraint.applySubstitution(solution, variablesArray);
- // * reduce and incorporate
- if (!this.currentBounds.reduceOneConstraint(this, constraint))
- return null;
+ // 5. bullet: determine B3 from C
+ while (!c.isEmpty()) {
+ // *
+ Set bottomSet = findBottomSet(c, allOutputVariables(c));
+ if (bottomSet.isEmpty()) {
+ bottomSet.add(pickFromCycle(c));
+ }
+ // *
+ c.removeAll(bottomSet);
+ // * The union of the input variables of all the selected constraints, α1, ..., αm, ...
+ Set allInputs = new HashSet();
+ Iterator bottomIt = bottomSet.iterator();
+ while (bottomIt.hasNext()) {
+ allInputs.addAll(((ConstraintFormula)bottomIt.next()).inputVariables(this));
+ }
+ InferenceVariable[] variablesArray = (InferenceVariable[]) allInputs.toArray(new InferenceVariable[allInputs.size()]);
+ // ... is resolved
+ BoundSet solution = resolve();
+ // * ~ apply substitutions to all constraints:
+ bottomIt = bottomSet.iterator();
+ while (bottomIt.hasNext()) {
+ ConstraintFormula constraint = ((ConstraintFormula)bottomIt.next());
+ constraint.applySubstitution(solution, variablesArray);
+ // * reduce and incorporate
+ if (!this.currentBounds.reduceOneConstraint(this, constraint))
+ return null;
+ }
}
+ // 6. bullet: solve
+ BoundSet solution = solve();
+ if (solution == null || !isResolved(solution))
+ return null;
+ return solution;
+ } finally {
+ this.currentBounds = previous;
}
- // 6. bullet: solve
- BoundSet solution = solve(true);
- if (solution == null || !isResolved(solution))
- return null;
- return solution;
}
private Object pickFromCycle(Set c) {
missingImplementation("Breaking a dependency cycle NYI");
@@ -269,17 +277,13 @@ public class InferenceContext18 {
* @return a bound set representing the solution, or null if inference failed
* @throws InferenceFailureException a compile error has been detected during inference
*/
- public /*@Nullable*/ BoundSet solve(boolean considerResolutionResult) throws InferenceFailureException {
+ public /*@Nullable*/ BoundSet solve() throws InferenceFailureException {
if (!reduce())
return null;
if (!this.currentBounds.incorporate(this))
return null;
- BoundSet resolutionResult = resolve();
- if (resolutionResult == null)
- return null;
-
- return considerResolutionResult ? resolutionResult : this.currentBounds.copy();
+ return resolve();
}
/**
@@ -436,7 +440,8 @@ public class InferenceContext18 {
if (upperBounds != Binding.NO_TYPES) {
for (int k = 0; k < upperBounds.length; k++)
upperBounds[k] = Scope.substitute(theta, upperBounds[k]);
- setUpperBounds(zsj, upperBounds);
+ if (!setUpperBounds(zsj, upperBounds))
+ return null;
}
if (tmpBoundSet == this.currentBounds)
tmpBoundSet = tmpBoundSet.copy();
@@ -464,14 +469,17 @@ public class InferenceContext18 {
}
// === ===
- private void setUpperBounds(CaptureBinding18 typeVariable, TypeBinding[] substitutedUpperBounds) {
+ private boolean setUpperBounds(CaptureBinding18 typeVariable, TypeBinding[] substitutedUpperBounds) {
// 18.4: ... define the upper bound of Zi as glb(L1θ, ..., Lkθ)
if (substitutedUpperBounds.length == 1) {
typeVariable.setUpperBounds(substitutedUpperBounds, this.object); // shortcut
} else {
TypeBinding[] glbs = Scope.greaterLowerBound(substitutedUpperBounds, this.scope, this.environment);
+ if (glbs == null)
+ return false;
typeVariable.setUpperBounds(glbs, this.object);
}
+ return true;
}
/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index 783be5c75f..2e9c449e82 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -65,12 +65,12 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin
// 18.5.1 (Applicability):
infCtx18.inferInvocationApplicability(originalMethod, arguments);
try {
- BoundSet result = infCtx18.solve(false);
- if (result != null /*&& infCtx18.isResolved(result)*/) { // FIXME(stephan): second condition breaks BatchCompilerTest.test032
+ BoundSet provisionalResult = infCtx18.solve();
+ BoundSet result = infCtx18.currentBounds.copy(); // the result after reduction, without effects of resolve()
+ if (provisionalResult != null /*&& infCtx18.isResolved(result)*/) { // FIXME(stephan): second condition breaks BatchCompilerTest.test032
// 18.5.2 (Invocation type):
- BoundSet provisionalResult = result;
TypeBinding expectedType = invocationSite.expectedType();
- result = infCtx18.inferInvocationType(expectedType, invocationSite, originalMethod, checkKind);
+ result = infCtx18.inferInvocationType(result, expectedType, invocationSite, originalMethod, checkKind);
boolean hasReturnProblem = result == null;
if (hasReturnProblem)
result = provisionalResult; // we prefer a type error regarding the return type over reporting no match at all
@@ -84,11 +84,8 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin
}
return parameterizedMethod;
}
- // FIXME: return null also here?
-// return null;
- } else {
- return null;
}
+ return null;
} catch (InferenceFailureException e) {
scope.problemReporter().genericInferenceError(e.getMessage(), invocationSite);
}

Back to the top