@@ -146,12 +146,13 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
146146 */
147147 private [this ] var leftRoot : Type = _
148148
149- /** Are we forbidden from recording GADT constraints?
150- *
151- * This flag is set when we're already in [[Mode.GadtConstraintInference ]],
152- * to signify that we temporarily cannot record any GADT constraints.
153- */
149+ /** Are we forbidden from recording GADT constraints? */
154150 private var frozenGadt = false
151+ private inline def inFrozenGadt [T ](op : => T ): T = {
152+ val savedFrozenGadt = frozenGadt
153+ frozenGadt = true
154+ try op finally frozenGadt = savedFrozenGadt
155+ }
155156
156157 protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
157158 val savedApprox = approx
@@ -852,30 +853,31 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
852853 val tycon2sym = tycon2.symbol
853854
854855 var touchedGADTs = false
855- def gadtBoundsContain (sym : Symbol , tp : Type ): Boolean = {
856+ var gadtIsInstantiated = false
857+ def gadtBoundsContain (sym : Symbol , tp : Type , tpConSym : Symbol ): Boolean = {
856858 touchedGADTs = true
857859 val b = gadtBounds(sym)
858- b != null && inFrozenConstraint {
859- (b.lo =:= tp) && (b.hi =:= tp)
860+ def boundsDescr = if b == null then " null" else b.show
861+ b != null && inFrozenGadt { isSubType(b.hi, tp) } && {
862+ gadtIsInstantiated = b.isInstanceOf [TypeAlias ]
863+ true
860864 }
861865 }
862866
863867 val res = (
864- tycon1sym == tycon2sym ||
865- gadtBoundsContain(tycon1sym , tycon2) ||
866- gadtBoundsContain(tycon2sym, tycon1 )
867- ) &&
868- isSubType(tycon1.prefix, tycon2.prefix ) && {
868+ tycon1sym == tycon2sym
869+ && isSubType(tycon1.prefix , tycon2.prefix)
870+ || gadtBoundsContain(tycon1sym, tycon2, tycon2sym )
871+ || gadtBoundsContain(tycon2sym, tycon1, tycon1sym)
872+ ) && {
869873 // check both tycons to deal with the case when they are equal b/c of GADT constraint
870- val tyconIsInjective = tycon1sym.isClass || tycon2sym.isClass
874+ val tyconIsInjective =
875+ (tycon1sym.isClass || tycon2sym.isClass)
876+ && (if touchedGADTs then gadtIsInstantiated else true )
871877 def checkSubArgs () = isSubArgs(args1, args2, tp1, tparams)
872- // we only record GADT constraints if tycon is guaranteed to be injective
878+ // we only record GADT constraints if *both* tycons are effectively injective
873879 if (tyconIsInjective) checkSubArgs()
874- else {
875- val savedFrozenGadt = frozenGadt
876- frozenGadt = true
877- try checkSubArgs() finally frozenGadt = savedFrozenGadt
878- }
880+ else inFrozenGadt { checkSubArgs() }
879881 }
880882 if (res && touchedGADTs) GADTused = true
881883 res
0 commit comments