@@ -588,11 +588,13 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
588
588
if (tref.symbol.is(Module )) mapOver(tref)
589
589
else newTypeVar(TypeBounds .upper(tp.underlying))
590
590
case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
591
- // See tests/patmat/3645b.scala
591
+ // Note that the logic for contra- and co-variance is reverse of `typeParamMap`
592
+ // This is because we are checking the possibility of `tp1 <:< tp2`, thus we should
593
+ // minimize `tp1` while maximize `tp2`. See tests/patmat/3645b.scala
592
594
val exposed =
593
595
if (variance == 0 ) newTypeVar(tp.underlying.bounds)
594
- else if (variance == 1 ) mapOver(tp.underlying.hiBound )
595
- else mapOver(tp.underlying.loBound )
596
+ else if (variance == 1 ) mapOver(tp.underlying.loBound )
597
+ else mapOver(tp.underlying.hiBound )
596
598
597
599
debug.println(s " $tp exposed to =====> $exposed" )
598
600
exposed
@@ -634,7 +636,11 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
634
636
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
635
637
val protoTp1 = thisTypeMap(tp1.appliedTo(tvars))
636
638
637
- // tests/patmat/3645b.scala
639
+ // If parent contains a reference to an abstract type, then we should
640
+ // refine subtype checking to eliminate abstract types according to
641
+ // variance. As this logic is only needed in exhaustivity check, thus
642
+ // we manually patch subtyping check instead of changing TypeComparer.
643
+ // See tests/patmat/3645b.scala
638
644
def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
639
645
(parent.argInfos.nonEmpty || parent.abstractTypeMembers.nonEmpty) &&
640
646
instantiate(parent, tp2)(ctx.fresh.setNewTyperState()).exists
0 commit comments