Skip to content

Commit 92a2e54

Browse files
committed
make prefix handling logic more explicit
1 parent 934d1ef commit 92a2e54

File tree

1 file changed

+22
-35
lines changed
  • compiler/src/dotty/tools/dotc/transform/patmat

1 file changed

+22
-35
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)