Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove left overs from implementing version 0.7.0 of the JSR 305 spec #819

Merged
merged 1 commit into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ private ReferenceBinding findGroundTargetType(BlockScope blockScope, TypeBinding
freshInferenceContext.cleanUp();
}
} else {
return findGroundTargetTypeForElidedLambda(blockScope, withWildCards);
return withWildCards.getNonWildcardParameterization(blockScope);
}
}
if (targetType instanceof ReferenceBinding)
Expand All @@ -542,15 +542,6 @@ private ReferenceBinding findGroundTargetType(BlockScope blockScope, TypeBinding
return null;
}

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, withWildCards.enclosingType());
}

@Override
public boolean argumentsTypeElided() {
return (this.arguments.length > 0 && this.arguments[0].hasElidedType()) || this.argumentsTypeVar;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public static ReferenceBinding findGroundTargetType(InferenceContext18 inference
LambdaExpression lambda, ParameterizedTypeBinding targetTypeWithWildCards)
{
if (lambda.argumentsTypeElided()) {
return lambda.findGroundTargetTypeForElidedLambda(scope, targetTypeWithWildCards);
return targetTypeWithWildCards.getNonWildcardParameterization(scope);
} else {
SuspendedInferenceRecord previous = inferenceContext.enterLambda(lambda);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -761,21 +761,39 @@ public ReferenceBinding inferFunctionalInterfaceParameterization(LambdaExpressio
{
TypeBinding[] q = createBoundsForFunctionalInterfaceParameterizationInference(targetTypeWithWildCards);
if (q == null || q.length != lambda.arguments().length) {
// fail TODO: can this still happen here?
return null;
} 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);
// If F<A'1, ..., A'm> is a well-formed type, ...
ParameterizedTypeBinding ptb = blockScope.environment().createParameterizedType(genericType, aprime, targetTypeWithWildCards.enclosingType());
TypeVariableBinding[] vars = ptb.genericType().typeVariables();
ParameterizedTypeBinding captured = ptb.capture(blockScope, lambda.sourceStart, lambda.sourceEnd);
// If F<A'1, ..., A'm> is not a well-formed type, ...
ParameterizedTypeBinding f_aprime = blockScope.environment().createParameterizedType(genericType, aprime, targetTypeWithWildCards.enclosingType());
TypeVariableBinding[] vars = f_aprime.genericType().typeVariables();
boolean hasWildcard = false;
for (int i = 0; i < vars.length; i++) {
if (vars[i].boundCheck(captured, aprime[i], blockScope, lambda) == BoundCheckStatus.MISMATCH)
return null;
if (vars[i].boundCheck(f_aprime, aprime[i], blockScope, lambda) == BoundCheckStatus.MISMATCH)
return null; // ... no valid parameterization exists
hasWildcard |= aprime[i].kind() == Binding.WILDCARD_TYPE;
}
/* as per spec we should do the following:
*
* // or if F<A'1, ..., A'm> is not a subtype of F<A1, ..., Am>
* if (!f_aprime.isSubtypeOf(targetTypeWithWildCards, false))
* return null; // ... no valid parameterization exists
*
* but that would surface as
* "The target type of this expression is not a well formed parameterized type due to bound(s) mismatch"
* whereas the ill-formed type only emerged during inference.
* So let final checks detect the incompatibility for a better error message.
*/
// ... the inferred parameterization is either F<A'1, ..., A'm>, if all the type arguments are types,
// or the non-wildcard parameterization (§9.9) of F<A'1, ..., A'm>, if one or more type arguments are still wildcards.
if (hasWildcard) {
return f_aprime.getNonWildcardParameterization(blockScope);
} else {
return f_aprime;
}
return ptb;
}
}
return targetTypeWithWildCards;
Expand All @@ -792,38 +810,17 @@ TypeBinding[] createBoundsForFunctionalInterfaceParameterizationInference(Parame
TypeBinding[] a = functionalInterface.arguments;
if (a == null)
return null;
InferenceVariable[] alpha = addInitialTypeVariableSubstitutions(a);
addInitialTypeVariableSubstitutions(a);

createAdditionalBounds(a, alpha);
TypeBinding falpha = substitute(functionalInterface);
return falpha.getSingleAbstractMethod(this.scope, true).parameters;
}

private void createAdditionalBounds(TypeBinding[] a, InferenceVariable[] alpha) {
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, this.environment);
}
}

/**
* from 18.5.3:
* Otherwise, a set of constraint formulas is formed with, for all i (1 ≤ i ≤ n), ‹Pi = Qi›.
* This constraint formula set is reduced to form the bound set B.
*/
public boolean reduceWithEqualityConstraints(TypeBinding[] p, TypeBinding[] q) {
if (p != null) {
for (int i = 0; i < p.length; i++) {
Expand Down Expand Up @@ -1823,6 +1820,13 @@ public static ParameterizedTypeBinding parameterizedWithWildcard(TypeBinding typ
return null;
}

/**
* From 18.5.3:
* <ul>
* <li>If B contains an instantiation (§18.1.3) for αi, T, then A'i = T.
* <li>Otherwise, A'i = Ai.
* </ul>
*/
public TypeBinding[] getFunctionInterfaceArgumentSolutions(TypeBinding[] a) {
int m = a.length;
TypeBinding[] aprime = new TypeBinding[m];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,7 @@ public RecordComponentBinding[] unResolvedComponents() {
@Override
protected MethodBinding[] getInterfaceAbstractContracts(Scope scope, boolean replaceWildcards, boolean filterDefaultMethods) throws InvalidInputException {
if (replaceWildcards) {
TypeBinding[] types = getNonWildcardParameterization(scope);
TypeBinding[] types = getNonWildcardParameters(scope);
if (types == null)
return new MethodBinding[] { new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType) };
for (int i = 0; i < types.length; i++) {
Expand Down Expand Up @@ -1732,7 +1732,7 @@ public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceW
ParameterizedTypeBinding declaringType = null;
TypeBinding [] types = this.arguments;
if (replaceWildcards) {
types = getNonWildcardParameterization(scope);
types = getNonWildcardParameters(scope);
if (types == null)
return this.singleAbstractMethod[index] = new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType);
} else if (types == null) {
Expand Down Expand Up @@ -1764,8 +1764,8 @@ public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceW
return this.singleAbstractMethod[index];
}

// from JLS 9.8
public TypeBinding[] getNonWildcardParameterization(Scope scope) {
// from JLS 9.9
public TypeBinding[] getNonWildcardParameters(Scope scope) {
// precondition: isValidBinding()
TypeBinding[] typeArguments = this.arguments; // A1 ... An
if (typeArguments == null)
Expand Down Expand Up @@ -1833,6 +1833,16 @@ public TypeBinding[] getNonWildcardParameterization(Scope scope) {
}
return types;
}

public ReferenceBinding getNonWildcardParameterization(BlockScope blockScope) {
// non-wildcard parameterization (9.9) of the target type
TypeBinding[] types = getNonWildcardParameters(blockScope);
if (types == null)
return null;
ReferenceBinding genericType = genericType();
return blockScope.environment().createParameterizedType(genericType, types, enclosingType());
}

@Override
public long updateTagBits() {
if (this.arguments != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2953,7 +2953,7 @@ public void testBug430296() {
"2. ERROR in AnnotationCollector.java (at line 9)\n" +
" return persons.collect(Collectors.toMap((Person p) -> p.getLastName(),\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Type mismatch: cannot convert from Function<Person,? extends K> to Function<? super T,? extends K>\n" +
"Type mismatch: cannot convert from Function<Person,K> to Function<? super T,? extends K>\n" +
"----------\n" +
"3. ERROR in AnnotationCollector.java (at line 10)\n" +
" Function::identity,\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8601,12 +8601,12 @@ public void test428177() {
"4. ERROR in X.java (at line 36)\n" +
" if(\"1\" == \"\") { return stream.collect(Collectors.toList()).stream(); // ERROR\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Type mismatch: cannot convert from Stream<capture#24-of ? extends String> to Stream<String>\n" +
"Type mismatch: cannot convert from Stream<capture#14-of ? extends String> to Stream<String>\n" +
"----------\n" +
"5. ERROR in X.java (at line 38)\n" +
" return stream.collect(Collectors.toList()); // NO ERROR\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Type mismatch: cannot convert from List<capture#27-of ? extends String> to Stream<String>\n" +
"Type mismatch: cannot convert from List<capture#17-of ? extends String> to Stream<String>\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=428795, - [1.8]Internal compiler error: java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.ast.MessageSend.analyseCode
Expand Down Expand Up @@ -9884,7 +9884,7 @@ public void testGroundTargetTypeWithWithWildcards() {
"1. ERROR in X.java (at line 10)\n" +
" return m((X x1, X x2) -> { return new Y(); });\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Type mismatch: cannot convert from I<X,X,? extends C> to I<? extends A,? extends B,? extends C>\n" +
"Type mismatch: cannot convert from I<X,X,C> to I<? extends A,? extends B,? extends C>\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=474522, [1.8][compiler] ecj doesn't handle captured final fields correctly in lambdas
Expand Down
Loading