Skip to content

Commit 6d5eba0

Browse files
committed
Fix #4880: always instantiate prefix tvar
1 parent f4de761 commit 6d5eba0

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -656,18 +656,18 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
656656
// Fix subtype checking for child instantiation,
657657
// such that `Foo(Test.this.foo) <:< Foo(Foo.this)`
658658
// See tests/patmat/i3938.scala
659-
def removeThisType(implicit ctx: Context) = new TypeMap {
660-
// is in tvarBounds? Don't create new tvars if true
661-
private var tvarBounds: Boolean = false
659+
class RemoveThisMap extends TypeMap {
660+
var prefixTVar: Type = null
662661
def apply(tp: Type): Type = tp match {
663662
case ThisType(tref: TypeRef) if !tref.symbol.isStaticOwner =>
664663
if (tref.symbol.is(Module))
665664
TermRef(this(tref.prefix), tref.symbol.sourceModule)
666-
else if (tvarBounds)
665+
else if (prefixTVar != null)
667666
this(tref)
668667
else {
669-
tvarBounds = true
670-
newTypeVar(TypeBounds.upper(this(tref)))
668+
prefixTVar = WildcardType // prevent recursive call from assigning it
669+
prefixTVar = newTypeVar(TypeBounds.upper(this(tref)))
670+
prefixTVar
671671
}
672672
case tp => mapOver(tp)
673673
}
@@ -681,14 +681,17 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
681681
}
682682
}
683683

684+
val removeThisType = new RemoveThisMap
685+
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
686+
val protoTp1 = removeThisType.apply(tp1).appliedTo(tvars)
687+
684688
val force = new ForceDegree.Value(
685-
tvar => !(ctx.typerState.constraint.entry(tvar.origin) eq tvar.origin.underlying),
689+
tvar =>
690+
!(ctx.typerState.constraint.entry(tvar.origin) eq tvar.origin.underlying) ||
691+
(tvar `eq` removeThisType.prefixTVar),
686692
minimizeAll = false
687693
)
688694

689-
val tvars = tp1.typeParams.map { tparam => newTypeVar(tparam.paramInfo.bounds) }
690-
val protoTp1 = removeThisType.apply(tp1).appliedTo(tvars)
691-
692695
// If parent contains a reference to an abstract type, then we should
693696
// refine subtype checking to eliminate abstract types according to
694697
// variance. As this logic is only needed in exhaustivity check,

tests/patmat/i4880.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10: Pattern Match Exhaustivity: _: ZipArchive, _: VirtualFile, _: PlainFile

tests/patmat/i4880.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
sealed abstract class AbstractFile
2+
class PlainFile(path: String) extends AbstractFile
3+
class VirtualFile(name: String) extends AbstractFile
4+
abstract class ZipArchive(path: String) extends AbstractFile {
5+
sealed abstract class Entry(name: String) extends VirtualFile(name)
6+
class DirEntry(path: String) extends Entry(path)
7+
}
8+
9+
object Test {
10+
def foo(file: AbstractFile) = file match {
11+
case ze: ZipArchive#Entry =>
12+
}
13+
}

0 commit comments

Comments
 (0)