@@ -557,6 +557,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
557557
558558 debug.println(s " bases of ${tp1.show}: " + bases1)
559559 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))
560562
561563 val noClassConflict =
562564 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 {
595597 * Otherwise, return NoType.
596598 *
597599 */
598- def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
600+ def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
599601 // 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 {
601603 def expose (tp : TypeRef ): Type = {
602604 val lo = this (tp.info.loBound)
603605 val hi = this (tp.info.hiBound)
@@ -613,7 +615,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
613615 exposed
614616 }
615617
616- override def mapOver (tp : Type ): Type = tp match {
618+ def apply (tp : Type ): Type = tp match {
617619 case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
618620 // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
619621 expose(tp)
@@ -634,28 +636,31 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
634636 exposed
635637
636638 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 =>
652639 mapOver(tp)
653640 }
654641 }
655642
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+ }
659664 }
660665
661666 // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
@@ -672,24 +677,24 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
672677 )
673678
674679 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)
676681
677682 // If parent contains a reference to an abstract type, then we should
678683 // refine subtype checking to eliminate abstract types according to
679684 // variance. As this logic is only needed in exhaustivity check,
680685 // we manually patch subtyping check instead of changing TypeComparer.
681- // See tests/patmat/3645b .scala
686+ // See tests/patmat/i3645b .scala
682687 def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
683688 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)
685690 }
686691
687692 if (protoTp1 <:< tp2) {
688693 if (isFullyDefined(protoTp1, force)) protoTp1
689694 else instUndetMap.apply(protoTp1)
690695 }
691696 else {
692- val protoTp2 = parentTypeMap .apply(tp2)
697+ val protoTp2 = maxTypeMap .apply(tp2)
693698 if (protoTp1 <:< protoTp2 || parentQualify) {
694699 if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
695700 else instUndetMap.apply(protoTp1)
0 commit comments