From 30aa050e3b322866408cbe9bcaa0e02eedd93923 Mon Sep 17 00:00:00 2001 From: fedejeanne Date: Thu, 21 Nov 2024 10:34:39 +0100 Subject: [PATCH] Bring back a simpler (cheaper) approach to BoundSet::incorporate #3227 This simple approach was faster than the new one but it didn't cover some very specific use cases, which is why the newer and more complex (slower) approach was introduced. This commit brings back the older, simpler, approach and falls back to the newer, more expensive, approach only when necessary. Fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3327 --- .../internal/compiler/lookup/BoundSet.java | 56 +++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java index d4d6ae852a2..cc1e1bfe68d 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java @@ -615,12 +615,23 @@ boolean incorporate(InferenceContext18 context, TypeBound [] first, TypeBound [] } } } + if (deriveTypeArgumentConstraints) { - for (ConstraintTypeFormula typeArgumentConstraint : deriveTypeArgumentConstraints(bound1, bound2, context)) { - if (!reduceOneConstraint(context, typeArgumentConstraint)) - return false; + // Try with a simpler (cheaper) approach first + for (ConstraintFormula cf : deriveTypeArgumentConstraintsSimple(bound1, bound2)) { + if (reduceOneConstraint(context, cf)) { + // No need to keep searching, the simple strategy worked + continue; + } + + // If the simple search failed, try with a more complex (and expensive) search + for (ConstraintTypeFormula cf2 : deriveTypeArgumentConstraints(bound1, bound2, context)) { + if (!reduceOneConstraint(context, cf2)) + return false; + } } } + if (iteration == 2) { TypeBound boundX = bound1; bound1 = bound2; @@ -939,6 +950,43 @@ private ConstraintTypeFormula combineWithProperTypes(Collection prope return ConstraintTypeFormula.create(left, right, boundRight.relation, isAnyLeftSoft||boundRight.isSoft); } + private List deriveTypeArgumentConstraintsSimple(TypeBound boundS, TypeBound boundT) { + /* From 18.4: + * If two bounds have the form α <: S and α <: T, and if for some generic class or interface, G, + * there exists a supertype (4.10) of S of the form G and a supertype of T of the form G, + * then for all i, 1 ≤ i ≤ n, if Si and Ti are types (not wildcards), the constraint ⟨Si = Ti⟩ is implied. + */ + // callers must ensure both relations are <: and both lefts are equal + TypeBinding[] supers = superTypesWithCommonGenericTypeSimple(boundS.right, boundT.right); + if (supers != null) + return typeArgumentEqualityConstraints(supers[0], supers[1], boundS.isSoft || boundT.isSoft); + return Collections.emptyList(); + } + + private TypeBinding[] superTypesWithCommonGenericTypeSimple(TypeBinding s, TypeBinding t) { + if (s == null || s.id == TypeIds.T_JavaLangObject || t == null || t.id == TypeIds.T_JavaLangObject) + return null; + if (TypeBinding.equalsEquals(s.original(), t.original())) { + return new TypeBinding[] { s, t }; + } + TypeBinding tSuper = t.findSuperTypeOriginatingFrom(s); + if (tSuper != null) { + return new TypeBinding[] {s, tSuper}; + } + TypeBinding[] result = superTypesWithCommonGenericTypeSimple(s.superclass(), t); + if (result != null) + return result; + ReferenceBinding[] superInterfaces = s.superInterfaces(); + if (superInterfaces != null) { + for (ReferenceBinding superInterface : superInterfaces) { + result = superTypesWithCommonGenericTypeSimple(superInterface, t); + if (result != null) + return result; + } + } + return null; + } + private List deriveTypeArgumentConstraints(TypeBound boundS, TypeBound boundT, InferenceContext18 context) { /* From 18.4: * If two bounds have the form α <: S and α <: T, and if for some generic class or interface, G, @@ -1263,7 +1311,7 @@ private boolean superOnlyRaw(TypeBinding g, TypeBinding s, LookupEnvironment env return false; } - protected List> allSuperPairsWithCommonGenericType(TypeBinding s, TypeBinding t) { + private List> allSuperPairsWithCommonGenericType(TypeBinding s, TypeBinding t) { if (s == null || s.id == TypeIds.T_JavaLangObject || t == null || t.id == TypeIds.T_JavaLangObject) return Collections.emptyList(); List> result = new ArrayList<>();