Skip to content

Commit 934d1ef

Browse files
committed
Fix #3938: adapt prefix to ease prefix inference
1 parent f029755 commit 934d1ef

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
557557

558558
debug.println(s"bases of ${tp1.show}: " + bases1)
559559
debug.println(s"bases of ${tp2.show}: " + bases2)
560+
debug.println(s"${tp1.show} <:< ${tp2.show} : " + (tp1 <:< tp2))
561+
debug.println(s"${tp2.show} <:< ${tp1.show} : " + (tp2 <:< tp1))
560562

561563
val noClassConflict =
562564
bases1.forall(sym1 => sym1.is(Trait) || bases2.forall(sym2 => sym2.is(Trait) || sym1.isSubClass(sym2))) ||
@@ -638,15 +640,31 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
638640
}
639641
}
640642

643+
// Fix subtype checking for child instantiation,
644+
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
645+
// See tests/patmat/i3938.scala
646+
def removeThisType(implicit ctx: Context) = new TypeMap {
647+
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+
641657
// We are checking the possibility of `tp1 <:< tp2`, thus we should
642658
// minimize `tp1` while maximizing `tp2`. See tests/patmat/3645b.scala
643659
def childTypeMap(implicit ctx: Context) = new AbstractTypeMap(maximize = false) {
644660
def apply(t: Type): Type = t.dealias match {
645661
// map `ThisType` of `tp1` to a type variable
646662
// precondition: `tp1` should have the same shape as `path.Child`, thus `ThisType` is always covariant
647663
case tp @ ThisType(tref) if !tref.symbol.isStaticOwner =>
648-
if (tref.symbol.is(Module)) this(tref)
649-
else newTypeVar(TypeBounds.upper(tp.underlying))
664+
if (tref.symbol.is(Module))
665+
this(TermRef(tref.prefix, tref.symbol.sourceModule))
666+
else
667+
newTypeVar(TypeBounds.upper(removeThisType.apply(tref)))
650668

651669
case tp =>
652670
mapOver(tp)

tests/patmat/i3938.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* subtyping logs
2+
==> isSubType Test.this.foo.Bar(Test.this.foo.bar) <:< Foo.this.Bar?
3+
==> isSubType Test.this.foo.Bar <:< Foo.this.Bar?
4+
==> isSubType Foo(Test.this.foo) <:< Foo(Foo.this)?
5+
==> isSubType Foo <:< Foo(Foo.this)?
6+
<== isSubType Foo <:< Foo(Foo.this) = false
7+
<== isSubType Foo(Test.this.foo) <:< Foo(Foo.this) = false
8+
<== isSubType Test.this.foo.Bar <:< Foo.this.Bar = false
9+
<== isSubType Test.this.foo.Bar(Test.this.foo.bar) <:< Foo.this.Bar = false
10+
*/
11+
12+
13+
class Foo {
14+
val bar = new Bar
15+
class Bar {
16+
sealed abstract class A
17+
case class B() extends A
18+
case class C() extends A
19+
}
20+
}
21+
22+
class Test {
23+
val foo = new Foo
24+
import foo.bar._
25+
26+
def test(a: A) = {
27+
a match {
28+
case B() => 1
29+
case _ => 2 // unreachable code
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)