Skip to content

Commit 2b37f03

Browse files
committed
In instantiateToSubType, also infer the prefix of the approximated parent
1 parent e9d88c7 commit 2b37f03

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ object TypeOps:
701701
// `this`. We perform the following operations to approximate the parameters:
702702
//
703703
// 1. Replace type parameters in T with tvars
704-
// 2. Replace `A.this.C` with `A#C` (see tests/patmat/i12681.scala)
704+
// 2. Replace non-class applied types with a tvar, bounded by its type constructor's underlying type
705705
// 3. Replace non-reducing MatchType with its bound
706706
//
707707
val approximateParent = new TypeMap {
@@ -715,9 +715,6 @@ object TypeOps:
715715
// then to avoid it failing the <:<
716716
// we'll approximate by widening to its bounds
717717

718-
case ThisType(tref: TypeRef) if !tref.symbol.isStaticOwner =>
719-
tref
720-
721718
case tp: TypeRef if !tp.symbol.isClass =>
722719
def lo = LazyRef.of(apply(tp.underlying.loBound))
723720
def hi = LazyRef.of(apply(tp.underlying.hiBound))
@@ -794,9 +791,12 @@ object TypeOps:
794791
}
795792
}
796793

797-
val inferThisMap = new InferPrefixMap
798-
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
799-
val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars)
794+
def inferPrefix(tp: Type) =
795+
val inferThisMap = new InferPrefixMap
796+
val tvars = tp.typeParams.map(tparam => newTypeVar(tparam.paramInfo.bounds))
797+
inferThisMap(tp).appliedTo(tvars)
798+
799+
val protoTp1 = inferPrefix(tp1)
800800

801801
// If parent contains a reference to an abstract type, then we should
802802
// refine subtype checking to eliminate abstract types according to
@@ -814,7 +814,7 @@ object TypeOps:
814814

815815
if (protoTp1 <:< tp2) instantiate()
816816
else {
817-
val approxTp2 = approximateParent(tp2)
817+
val approxTp2 = inferPrefix(approximateParent(tp2))
818818
if (protoTp1 <:< approxTp2 || parentQualify(protoTp1, approxTp2)) instantiate()
819819
else NoType
820820
}

tests/patmat/t6146.comb1.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Like the "tricksier" variantion in t6146, but less tricksy (less nesting)
2+
// but also with a non-Any type argument, and some invariant usage of the type.
3+
// Used to study why `case _: C.type =>` is considered unreachable
4+
// in the ordinal method object A synthesises.
5+
trait T[X] {
6+
sealed trait A
7+
object A {
8+
case object B extends A
9+
}
10+
11+
def give: X
12+
def take(x: X): X
13+
}
14+
15+
object O extends T[String] {
16+
def give = "O"
17+
def take(x: String) = s"$x. Love, O."
18+
}
19+
20+
case object C extends O.A

0 commit comments

Comments
 (0)