@@ -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