Skip to content

Commit 7b35136

Browse files
committed
Refactor some TypeComparer code
- streamline comparisons of applied types - optimize sufficientEither to not try the second alternative if the first succeeds without narrowing the constraint.
1 parent 1ab76c1 commit 7b35136

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
157157

158158
/** Are we forbidden from recording GADT constraints? */
159159
private var frozenGadt = false
160-
private inline def inFrozenGadt[T](op: => T): T = {
160+
private inline def inFrozenGadt[T](inline op: T): T =
161+
inFrozenGadtIf(true)(op)
162+
163+
private inline def inFrozenGadtIf[T](cond: Boolean)(inline op: T): T = {
161164
val savedFrozenGadt = frozenGadt
162-
frozenGadt = true
165+
frozenGadt = cond
163166
try op finally frozenGadt = savedFrozenGadt
164167
}
165168

@@ -967,7 +970,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
967970
* corresponding arguments are subtypes relative to their variance (see `isSubArgs`).
968971
*/
969972
def isMatchingApply(tp1: Type): Boolean = tp1 match {
970-
case AppliedType(tycon1, args1) =>
973+
case tp1 as AppliedType(tycon1, args1) =>
971974
// We intentionally do not dealias `tycon1` or `tycon2` here.
972975
// `TypeApplications#appliedTo` already takes care of dealiasing type
973976
// constructors when this can be done without affecting type
@@ -977,6 +980,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
977980
//
978981
// Foo[?F, ?T] <:< Foo[[X] =>> (X, String), Int]
979982
//
983+
// where
984+
//
985+
// type Foo[F[_], T] = ErasedFoo[F[T]]
986+
//
980987
// Naturally, we'd like to infer:
981988
//
982989
// ?F := [X] => (X, String)
@@ -1016,10 +1023,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10161023
}
10171024

10181025
val res = (
1019-
tycon1sym == tycon2sym
1020-
&& isSubPrefix(tycon1.prefix, tycon2.prefix)
1021-
|| byGadtBounds(tycon1sym, tycon2, fromAbove = true)
1022-
|| byGadtBounds(tycon2sym, tycon1, fromAbove = false)
1026+
tycon1sym == tycon2sym && isSubPrefix(tycon1.prefix, tycon2.prefix)
1027+
|| byGadtBounds(tycon1sym, tycon2, fromAbove = true)
1028+
|| byGadtBounds(tycon2sym, tycon1, fromAbove = false)
10231029
) && {
10241030
// There are two cases in which we can assume injectivity.
10251031
// First we check if either sym is a class.
@@ -1031,11 +1037,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10311037
// must be instantiated, making the two tycons equal
10321038
val tyconIsInjective =
10331039
(tycon1sym.isClass || tycon2sym.isClass)
1034-
&& (if touchedGADTs then gadtIsInstantiated else true)
1035-
def checkSubArgs() = isSubArgs(args1, args2, tp1, tparams)
1036-
// we only record GADT constraints if *both* tycons are effectively injective
1037-
if (tyconIsInjective) checkSubArgs()
1038-
else inFrozenGadt { checkSubArgs() }
1040+
&& (!touchedGADTs || gadtIsInstantiated)
1041+
1042+
inFrozenGadtIf(!tyconIsInjective) {
1043+
isSubArgs(args1, args2, tp1, tparams)
1044+
}
10391045
}
10401046
if (res && touchedGADTs) GADTused = true
10411047
res
@@ -1544,19 +1550,19 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
15441550
* Method name comes from the notion that we are keeping a constraint which is sufficient to satisfy
15451551
* one of subtyping relationships.
15461552
*/
1547-
private def sufficientEither(op1: => Boolean, op2: => Boolean): Boolean = {
1553+
private def sufficientEither(op1: => Boolean, op2: => Boolean): Boolean =
15481554
val preConstraint = constraint
1549-
op1 && {
1550-
val leftConstraint = constraint
1551-
constraint = preConstraint
1552-
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
1553-
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
1554-
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1555-
constraint = leftConstraint
1556-
}
1555+
if op1 then
1556+
if constraint ne preConstraint then
1557+
// check whether `op2` generates a weaker constraint than `op1`
1558+
val leftConstraint = constraint
1559+
constraint = preConstraint
1560+
if !(op2 && subsumes(leftConstraint, constraint, preConstraint)) then
1561+
if constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint) then
1562+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
1563+
constraint = leftConstraint
15571564
true
1558-
} || op2
1559-
}
1565+
else op2
15601566

15611567
/** Returns true iff the result of evaluating either `op1` or `op2` is true, keeping the smaller constraint if any.
15621568
* E.g., if

0 commit comments

Comments
 (0)