@@ -597,9 +597,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
597
597
* Otherwise, return NoType.
598
598
*
599
599
*/
600
- def instantiate (tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type = {
600
+ def instantiate (tp1 : NamedType , tp2 : Type )(implicit ctx : Context ): Type = {
601
601
// 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 {
603
603
def expose (tp : TypeRef ): Type = {
604
604
val lo = this (tp.info.loBound)
605
605
val hi = this (tp.info.hiBound)
@@ -615,7 +615,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
615
615
exposed
616
616
}
617
617
618
- override def mapOver (tp : Type ): Type = tp match {
618
+ def apply (tp : Type ): Type = tp match {
619
619
case tp : TypeRef if tp.underlying.isInstanceOf [TypeBounds ] =>
620
620
// See tests/patmat/gadt.scala tests/patmat/exhausting.scala tests/patmat/t9657.scala
621
621
expose(tp)
@@ -636,46 +636,33 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
636
636
exposed
637
637
638
638
case _ =>
639
- super . mapOver(tp)
639
+ mapOver(tp)
640
640
}
641
641
}
642
642
643
+ def minTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = false )
644
+ def maxTypeMap (implicit ctx : Context ) = new AbstractTypeMap (maximize = true )
645
+
643
646
// Fix subtype checking for child instantiation,
644
647
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
645
648
// See tests/patmat/i3938.scala
646
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
647
652
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 =>
664
654
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)
671
663
}
672
664
}
673
665
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
-
679
666
// replace uninstantiated type vars with WildcardType, check tests/patmat/3333.scala
680
667
def instUndetMap (implicit ctx : Context ) = new TypeMap {
681
668
def apply (t : Type ): Type = t match {
@@ -690,24 +677,24 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
690
677
)
691
678
692
679
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)
694
681
695
682
// If parent contains a reference to an abstract type, then we should
696
683
// refine subtype checking to eliminate abstract types according to
697
684
// variance. As this logic is only needed in exhaustivity check,
698
685
// we manually patch subtyping check instead of changing TypeComparer.
699
- // See tests/patmat/3645b .scala
686
+ // See tests/patmat/i3645b .scala
700
687
def parentQualify = tp1.widen.classSymbol.info.parents.exists { parent =>
701
688
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)
703
690
}
704
691
705
692
if (protoTp1 <:< tp2) {
706
693
if (isFullyDefined(protoTp1, force)) protoTp1
707
694
else instUndetMap.apply(protoTp1)
708
695
}
709
696
else {
710
- val protoTp2 = parentTypeMap .apply(tp2)
697
+ val protoTp2 = maxTypeMap .apply(tp2)
711
698
if (protoTp1 <:< protoTp2 || parentQualify) {
712
699
if (isFullyDefined(AndType (protoTp1, protoTp2), force)) protoTp1
713
700
else instUndetMap.apply(protoTp1)
0 commit comments