@@ -607,11 +607,13 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
607
607
if (tref.symbol.is(Module )) mapOver(tref)
608
608
else newTypeVar(TypeBounds .upper(tp.underlying))
609
609
case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
610
- // See tests/patmat/3645b.scala
610
+ // Note that the logic for contra- and co-variance is reverse of `typeParamMap`
611
+ // This is because we are checking the possibility of `tp1 <:< tp2`, thus we should
612
+ // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
611
613
val exposed =
612
614
if (variance == 0 ) newTypeVar(tp.underlying.bounds)
613
- else if (variance == 1 ) mapOver(tp.underlying.hiBound )
614
- else mapOver(tp.underlying.loBound )
615
+ else if (variance == 1 ) mapOver(tp.underlying.loBound )
616
+ else mapOver(tp.underlying.hiBound )
615
617
616
618
debug.println(s " $tp exposed to =====> $exposed" )
617
619
exposed
@@ -653,7 +655,11 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
653
655
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
654
656
val protoTp1 = thisTypeMap(tp1.appliedTo(tvars))
655
657
656
- // tests/patmat/3645b.scala
658
+ // If parent contains a reference to an abstract type, then we should
659
+ // refine subtype checking to eliminate abstract types according to
660
+ // variance. As this logic is only needed in exhaustivity check, thus
661
+ // we manually patch subtyping check instead of changing TypeComparer.
662
+ // See tests/patmat/3645b.scala
657
663
def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
658
664
(parent.argInfos.nonEmpty || parent.abstractTypeMembers.nonEmpty) &&
659
665
instantiate(parent, tp2)(ctx.fresh.setNewTyperState()).exists
0 commit comments