Skip to content

Commit 6f7152f

Browse files
Align inference resolution with javac by applying hints from Maurizio
See https://mail.openjdk.org/archives/list/compiler-dev@openjdk.org/message/GN6RTCGMME6I5JVLSFZRIR32XY6QKOI2/
1 parent ff9337d commit 6f7152f

2 files changed

Lines changed: 48 additions & 13 deletions

File tree

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,23 @@ public boolean hasOnlyTrivialExceptionBounds(InferenceVariable variable, TypeBin
10631063
return true;
10641064
}
10651065

1066+
public int rankIVar(InferenceVariable ivar) {
1067+
// implements the ranking of ivars according to their bounds as explained in
1068+
// https://mail.openjdk.org/archives/list/compiler-dev@openjdk.org/message/GN6RTCGMME6I5JVLSFZRIR32XY6QKOI2/
1069+
ThreeSets three = this.boundsPerVariable.get(ivar.prototype());
1070+
if (three != null) {
1071+
if (three.sameBounds != null)
1072+
for (TypeBound bound :three.sameBounds)
1073+
if (!(bound.right instanceof InferenceVariable))
1074+
return 1;
1075+
if (three.superBounds != null)
1076+
for (TypeBound bound :three.superBounds)
1077+
if (!(bound.right instanceof InferenceVariable))
1078+
return 2;
1079+
}
1080+
return 3;
1081+
}
1082+
10661083
/**
10671084
* JLS 18.1.3:
10681085
* Answer all upper bounds for the given inference variable as defined by any bounds in this set.

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.util.*;
1818
import java.util.Map.Entry;
19+
import java.util.stream.Collectors;
1920
import org.eclipse.jdt.core.compiler.CharOperation;
2021
import org.eclipse.jdt.internal.compiler.ast.*;
2122
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus;
@@ -1169,19 +1170,14 @@ public boolean reduceAndIncorporate(ConstraintFormula constraint) throws Inferen
11691170
// find a minimal set of dependent variables:
11701171
Set<InferenceVariable> variableSet;
11711172
boolean[] hasSkippedSuperBound = { false };
1172-
while ((variableSet = getSmallestVariableSet(tmpBoundSet, toResolveSet, maySkipSuperBound, hasSkippedSuperBound)) != null) {
1173+
while ((variableSet = getSmallestVariableSet(tmpBoundSet, toResolveSet, false, hasSkippedSuperBound)) != null) {
11731174
int oldNumUninstantiated = tmpBoundSet.numUninstantiatedVariables(this.inferenceVariables);
1174-
final int numVars = variableSet.size();
1175-
if (numVars > 0) {
1176-
final InferenceVariable[] variables = variableSet.toArray(new InferenceVariable[numVars]);
1177-
// NON-JLS: prioritize ivars in 'inThrows' as those may pull in new information by extra rule below (=RuntimeException)
1178-
BoundSet tSet = tmpBoundSet;
1179-
Arrays.sort(variables, (v1, v2) -> {
1180-
int r1 = tSet.inThrows.contains(v1) ? -1 : 0;
1181-
int r2 = tSet.inThrows.contains(v2) ? -1 : 0;
1182-
return r1 - r2;
1183-
});
1184-
//
1175+
List<InferenceVariable> ofRank;
1176+
while ((ofRank = pickIvarsByRank(variableSet, tmpBoundSet)) != null) {
1177+
final int numVars = ofRank.size();
1178+
if (numVars == 0)
1179+
continue;
1180+
final InferenceVariable[] variables = ofRank.toArray(new InferenceVariable[numVars]);
11851181
variables: if (!isRecordPatternTypeInference && !tmpBoundSet.hasCaptureBound(variableSet)) {
11861182
// try to instantiate this set of variables in a fresh copy of the bound set:
11871183
BoundSet prevBoundSet = tmpBoundSet;
@@ -1190,6 +1186,7 @@ public boolean reduceAndIncorporate(ConstraintFormula constraint) throws Inferen
11901186
InferenceVariable variable = variables[j];
11911187
if (tmpBoundSet.isInstantiated(variable)) { // NON-JLS: may happen when exception bound has been incorporated
11921188
toResolveSet.remove(variable);
1189+
variableSet.remove(variable);
11931190
continue;
11941191
}
11951192
// try lower bounds:
@@ -1236,11 +1233,13 @@ public boolean reduceAndIncorporate(ConstraintFormula constraint) throws Inferen
12361233
}
12371234
}
12381235
toResolveSet.remove(variable);
1236+
variableSet.remove(variable);
12391237
}
12401238
if (tmpBoundSet.incorporate(this))
12411239
continue;
12421240
tmpBoundSet = prevBoundSet;// clean-up for second attempt
12431241
}
1242+
12441243
if (maySkipSuperBound && hasSkippedSuperBound[0])
12451244
return resolve(toResolve, isRecordPatternTypeInference, false);
12461245
// Otherwise, a second attempt is made...
@@ -1348,6 +1347,7 @@ public TypeBinding substitute(TypeVariableBinding typeVariable) {
13481347
if (!typeboundCreated)
13491348
tmpBoundSet.addBound(new TypeBound(variable, zsj, ReductionResult.SAME), this.environment);
13501349
toResolveSet.remove(variable);
1350+
variableSet.remove(variable);
13511351
}
13521352
if (tmpBoundSet.incorporate(this)) {
13531353
if (tmpBoundSet.numUninstantiatedVariables(this.inferenceVariables) == oldNumUninstantiated)
@@ -1458,7 +1458,9 @@ public Set<InferenceVariable> getSmallestVariableSet(BoundSet bounds, Set<Infere
14581458
// "... and ii) there exists no non-empty proper subset of { α1, ..., αn } with this property."
14591459
// -> find a smallest among candidate sets:
14601460
if (set == null) {
1461-
return Collections.singleton(currentVariable);
1461+
set = new HashSet<>();
1462+
set.add(currentVariable);
1463+
return set;
14621464
}
14631465
for (Iterator<InferenceVariable> iter = set.iterator(); iter.hasNext();) {
14641466
InferenceVariable iv = iter.next();
@@ -1476,6 +1478,22 @@ public Set<InferenceVariable> getSmallestVariableSet(BoundSet bounds, Set<Infere
14761478
return result;
14771479
}
14781480

1481+
static List<InferenceVariable> pickIvarsByRank(Set<InferenceVariable> variableSet, BoundSet tmpBoundSet) {
1482+
// apply the ranking of ivars according to their bounds as explained in
1483+
// https://mail.openjdk.org/archives/list/compiler-dev@openjdk.org/message/GN6RTCGMME6I5JVLSFZRIR32XY6QKOI2/
1484+
Map<Integer, List<InferenceVariable>> byRank = variableSet.stream().collect(Collectors.groupingBy(tmpBoundSet::rankIVar));
1485+
for (int rank = 0; rank < 4; rank++) {
1486+
List<InferenceVariable> ofRank = byRank.get(rank);
1487+
if (ofRank == null)
1488+
continue;
1489+
final int numVars = ofRank.size();
1490+
if (numVars == 0)
1491+
continue;
1492+
return ofRank;
1493+
}
1494+
return null;
1495+
}
1496+
14791497
/**
14801498
* Collect dependencies of all our ivars based on TypeBounds of 'bounds'
14811499
* @param bounds consider all its TypeBounds

0 commit comments

Comments
 (0)