@@ -557,6 +557,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
557
557
558
558
debug.println(s " bases of ${tp1.show}: " + bases1)
559
559
debug.println(s " bases of ${tp2.show}: " + bases2)
560
+ debug.println(s " ${tp1.show} <:< ${tp2.show} : " + (tp1 <:< tp2))
561
+ debug.println(s " ${tp2.show} <:< ${tp1.show} : " + (tp2 <:< tp1))
560
562
561
563
val noClassConflict =
562
564
bases1.forall(sym1 => sym1.is(Trait ) || bases2.forall(sym2 => sym2.is(Trait ) || sym1.isSubClass(sym2))) ||
@@ -595,9 +597,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
595
597
* Otherwise, return NoType.
596
598
*
597
599
*/
598
- def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
600
+ def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
599
601
// expose abstract type references to their bounds or tvars according to variance
600
- abstract class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
602
+ class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
601
603
def expose (tp : TypeRef ): Type = {
602
604
val lo = this (tp.info.loBound)
603
605
val hi = this (tp.info.hiBound)
@@ -613,7 +615,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
613
615
exposed
614
616
}
615
617
616
- override def mapOver (tp : Type ): Type = tp match {
618
+ def apply (tp : Type ): Type = tp match {
617
619
case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
618
620
// See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
619
621
expose(tp)
@@ -634,28 +636,31 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
634
636
exposed
635
637
636
638
case _ =>
637
- super .mapOver(tp)
638
- }
639
- }
640
-
641
- // We are checking the possibility of `tp1 <:< tp2`, thus we should
642
- // minimize `tp1` while maximizing `tp2`. See tests/patmat/3645b.scala
643
- def childTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false ) {
644
- def apply (t : Type ): Type = t.dealias match {
645
- // map `ThisType` of `tp1` to a type variable
646
- // precondition: `tp1` should have the same shape as `path.Child`, thus `ThisType` is always covariant
647
- case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
648
- if (tref.symbol.is(Module )) this (tref)
649
- else newTypeVar(TypeBounds .upper(tp.underlying))
650
-
651
- case tp =>
652
639
mapOver(tp)
653
640
}
654
641
}
655
642
656
- // replace type parameter references with bounds
657
- def parentTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true ) {
658
- def apply (tp : Type ): Type = mapOver(tp.dealias)
643
+ def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
644
+ def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
645
+
646
+ // Fix subtype checking for child instantiation,
647
+ // such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
648
+ // See tests/patmat/i3938.scala
649
+ def removeThisType (implicit ctx : Context ) = new TypeMap {
650
+ // is in tvarBounds? Don't create new tvars if true
651
+ private var tvarBounds : Boolean = false
652
+ def apply (tp : Type ): Type = tp match {
653
+ case ThisType (tref : TypeRef ) if ! tref.symbol.isStaticOwner =>
654
+ if (tref.symbol.is(Module ))
655
+ TermRef (this (tref.prefix), tref.symbol.sourceModule)
656
+ else if (tvarBounds)
657
+ this (tref)
658
+ else {
659
+ tvarBounds = true
660
+ newTypeVar(TypeBounds .upper(this (tref)))
661
+ }
662
+ case tp => mapOver(tp)
663
+ }
659
664
}
660
665
661
666
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
@@ -672,24 +677,24 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
672
677
)
673
678
674
679
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
675
- val protoTp1 = childTypeMap .apply(tp1.appliedTo(tvars) )
680
+ val protoTp1 = removeThisType .apply(tp1) .appliedTo(tvars)
676
681
677
682
// If parent contains a reference to an abstract type, then we should
678
683
// refine subtype checking to eliminate abstract types according to
679
684
// variance. As this logic is only needed in exhaustivity check,
680
685
// we manually patch subtyping check instead of changing TypeComparer.
681
- // See tests/patmat/3645b .scala
686
+ // See tests/patmat/i3645b .scala
682
687
def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
683
688
implicit val ictx = ctx.fresh.setNewTyperState()
684
- parent.argInfos.nonEmpty && childTypeMap .apply(parent) <:< parentTypeMap .apply(tp2)
689
+ parent.argInfos.nonEmpty && minTypeMap .apply(parent) <:< maxTypeMap .apply(tp2)
685
690
}
686
691
687
692
if (protoTp1 <:< tp2) {
688
693
if (isFullyDefined(protoTp1, force)) protoTp1
689
694
else instUndetMap.apply(protoTp1)
690
695
}
691
696
else {
692
- val protoTp2 = parentTypeMap .apply(tp2)
697
+ val protoTp2 = maxTypeMap .apply(tp2)
693
698
if (protoTp1 <:< protoTp2 || parentQualify) {
694
699
if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
695
700
else instUndetMap.apply(protoTp1)
0 commit comments