@@ -597,9 +597,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
597597 * Otherwise, return NoType.
598598 *
599599 */
600- def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
600+ def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
601601 // expose abstract type references to their bounds or tvars according to variance
602- abstract class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
602+ class AbstractTypeMap (maximize : Boolean )(implicit ctx : Context ) extends TypeMap {
603603 def expose (tp : TypeRef ): Type = {
604604 val lo = this (tp.info.loBound)
605605 val hi = this (tp.info.hiBound)
@@ -615,7 +615,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
615615 exposed
616616 }
617617
618- override def mapOver (tp : Type ): Type = tp match {
618+ def apply (tp : Type ): Type = tp match {
619619 case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
620620 // See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
621621 expose(tp)
@@ -636,46 +636,33 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
636636 exposed
637637
638638 case _ =>
639- super . mapOver(tp)
639+ mapOver(tp)
640640 }
641641 }
642642
643+ def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
644+ def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
645+
643646 // Fix subtype checking for child instantiation,
644647 // such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
645648 // See tests/patmat/i3938.scala
646649 def removeThisType (implicit ctx : Context ) = new TypeMap {
650+ // is in tvarBounds? Don't create new tvars if true
651+ private var tvarBounds : Boolean = false
647652 def apply (tp : Type ): Type = tp match {
648- case ThisType (tref : TypeRef ) =>
649- if (tref.symbol.is(Module ))
650- TermRef (tref.prefix, tref.symbol.sourceModule)
651- else
652- mapOver(tref)
653- case _ => mapOver(tp)
654- }
655- }
656-
657- // We are checking the possibility of `tp1 <:< tp2`, thus we should
658- // minimize `tp1` while maximizing `tp2`. See tests/patmat/3645b.scala
659- def childTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false ) {
660- def apply (t : Type ): Type = t.dealias match {
661- // map `ThisType` of `tp1` to a type variable
662- // precondition: `tp1` should have the same shape as `path.Child`, thus `ThisType` is always covariant
663- case tp @ ThisType (tref) if ! tref.symbol.isStaticOwner =>
653+ case ThisType (tref : TypeRef ) if ! tref.symbol.isStaticOwner =>
664654 if (tref.symbol.is(Module ))
665- this (TermRef (tref.prefix, tref.symbol.sourceModule))
666- else
667- newTypeVar(TypeBounds .upper(removeThisType.apply(tref)))
668-
669- case tp =>
670- mapOver(tp)
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)
671663 }
672664 }
673665
674- // replace type parameter references with bounds
675- def parentTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true ) {
676- def apply (tp : Type ): Type = mapOver(tp.dealias)
677- }
678-
679666 // replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
680667 def instUndetMap (implicit ctx : Context ) = new TypeMap {
681668 def apply (t : Type ): Type = t match {
@@ -690,24 +677,24 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
690677 )
691678
692679 val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
693- val protoTp1 = childTypeMap .apply(tp1.appliedTo(tvars) )
680+ val protoTp1 = removeThisType .apply(tp1) .appliedTo(tvars)
694681
695682 // If parent contains a reference to an abstract type, then we should
696683 // refine subtype checking to eliminate abstract types according to
697684 // variance. As this logic is only needed in exhaustivity check,
698685 // we manually patch subtyping check instead of changing TypeComparer.
699- // See tests/patmat/3645b .scala
686+ // See tests/patmat/i3645b .scala
700687 def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
701688 implicit val ictx = ctx.fresh.setNewTyperState()
702- parent.argInfos.nonEmpty && childTypeMap .apply(parent) <:< parentTypeMap .apply(tp2)
689+ parent.argInfos.nonEmpty && minTypeMap .apply(parent) <:< maxTypeMap .apply(tp2)
703690 }
704691
705692 if (protoTp1 <:< tp2) {
706693 if (isFullyDefined(protoTp1, force)) protoTp1
707694 else instUndetMap.apply(protoTp1)
708695 }
709696 else {
710- val protoTp2 = parentTypeMap .apply(tp2)
697+ val protoTp2 = maxTypeMap .apply(tp2)
711698 if (protoTp1 <:< protoTp2 || parentQualify) {
712699 if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
713700 else instUndetMap.apply(protoTp1)
0 commit comments