Skip to content

Commit bcb72fa

Browse files
committed
Fix #12475: Approximate ThisType in child instantiation
1 parent 5efc3b5 commit bcb72fa

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

+15-6
Original file line numberDiff line numberDiff line change
@@ -692,15 +692,24 @@ object TypeOps:
692692
*/
693693
private def instantiateToSubType(tp1: NamedType, tp2: Type)(using Context): Type = {
694694
// In order for a child type S to qualify as a valid subtype of the parent
695-
// T, we need to test whether it is possible S <: T. Therefore, we replace
696-
// type parameters in T with tvars, and see if the subtyping is true.
697-
val approximateTypeParams = new TypeMap {
695+
// T, we need to test whether it is possible S <: T.
696+
//
697+
// The check is different from subtype checking due to type parameters and
698+
// `this`. We perform the following operations to approximate the parameters:
699+
//
700+
// 1. Replace type parameters in T with tvars
701+
// 2. Replace `A.this.C` with `A#C` (see tests/patmat/i12681.scala)
702+
//
703+
val approximateParent = new TypeMap {
698704
val boundTypeParams = util.HashMap[TypeRef, TypeVar]()
699705

700706
def apply(tp: Type): Type = tp.dealias match {
701707
case _: MatchType =>
702708
tp // break cycles
703709

710+
case ThisType(tref: TypeRef) if !tref.symbol.isStaticOwner =>
711+
tref
712+
704713
case tp: TypeRef if !tp.symbol.isClass =>
705714
def lo = LazyRef.of(apply(tp.underlying.loBound))
706715
def hi = LazyRef.of(apply(tp.underlying.hiBound))
@@ -787,7 +796,7 @@ object TypeOps:
787796
// we manually patch subtyping check instead of changing TypeComparer.
788797
// See tests/patmat/i3645b.scala
789798
def parentQualify(tp1: Type, tp2: Type) = tp1.classSymbol.info.parents.exists { parent =>
790-
parent.argInfos.nonEmpty && approximateTypeParams(parent) <:< tp2
799+
parent.argInfos.nonEmpty && approximateParent(parent) <:< tp2
791800
}
792801

793802
def instantiate(): Type = {
@@ -797,8 +806,8 @@ object TypeOps:
797806

798807
if (protoTp1 <:< tp2) instantiate()
799808
else {
800-
val protoTp2 = approximateTypeParams(tp2)
801-
if (protoTp1 <:< protoTp2 || parentQualify(protoTp1, protoTp2)) instantiate()
809+
val approxTp2 = approximateParent(tp2)
810+
if (protoTp1 <:< approxTp2 || parentQualify(protoTp1, approxTp2)) instantiate()
802811
else NoType
803812
}
804813
}

tests/patmat/i12681.scala

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
object Examples {
2+
3+
case class Leaf1() extends i.Root
4+
case class Leaf2() extends i.Branch
5+
6+
val i = new Inner()
7+
8+
class Inner {
9+
10+
sealed trait Root
11+
sealed trait Branch extends Root
12+
13+
// simulate ordinal method of a Mirror.SumOf generated at this call site
14+
def myOrdinal(r: Root): Int = r match {
15+
case _: Examples.Leaf1 => 0
16+
case _: Inner.this.Branch => 1
17+
}
18+
}
19+
20+
}

0 commit comments

Comments
 (0)