Skip to content

Commit 199c09d

Browse files
committed
Fix #3145: treat sealed classes and traits as inhabited
Sealed classes and traits are effectively inhabited in practice. By treating them as inhabited by default, we avoid spurious warnings that ignore anonymous classes. When we have a mechanism to track anonymous children or disallow anonymous children for sealed classes, we could revert this change to make the check stronger.
1 parent 367a66a commit 199c09d

File tree

9 files changed

+59
-16
lines changed

9 files changed

+59
-16
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
578578
case tp: RefinedType =>
579579
recur(tp.parent)
580580
case tp: TypeRef =>
581-
recur(tp.prefix) &&
582-
!(tp.classSymbol.is(Sealed) && tp.classSymbol.is(AbstractOrTrait) && tp.classSymbol.children.isEmpty) &&
583-
!(tp.classSymbol.is(AbstractFinal))
581+
recur(tp.prefix) && !(tp.classSymbol.is(AbstractFinal))
584582
case _ =>
585583
true
586584
}
@@ -709,8 +707,10 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
709707
/** Abstract sealed types, or-types, Boolean and Java enums can be decomposed */
710708
def canDecompose(tp: Type): Boolean = {
711709
val dealiasedTp = tp.dealias
712-
val res = tp.classSymbol.is(allOf(Abstract, Sealed)) ||
713-
tp.classSymbol.is(allOf(Trait, Sealed)) ||
710+
val res =
711+
(tp.classSymbol.is(Sealed) &&
712+
tp.classSymbol.is(AbstractOrTrait) &&
713+
tp.classSymbol.children.nonEmpty ) ||
714714
dealiasedTp.isInstanceOf[OrType] ||
715715
(dealiasedTp.isInstanceOf[AndType] && {
716716
val and = dealiasedTp.asInstanceOf[AndType]

tests/patmat/3144.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7: Match case Unreachable
1+
6: Pattern Match Exhaustivity: _: Foo

tests/patmat/3144c.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7: Match case Unreachable
1+
6: Pattern Match Exhaustivity: _: Foo

tests/patmat/3145.scala

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
object Test {
2+
sealed trait Foo
3+
class Bar(val s: String) extends Foo
4+
sealed abstract class Baz(val s: String) extends Foo
5+
6+
val f: Foo => String = {
7+
case bar: Bar => bar.s
8+
case baz: Baz => baz.s
9+
}
10+
}
11+
12+
object Test2 {
13+
sealed trait Foo
14+
class Bar extends Foo
15+
sealed trait Baz extends Foo
16+
17+
def f(x: Foo) = x match {
18+
case bar: Bar => 1
19+
case baz: Baz => 2
20+
}
21+
}
22+
23+
object Test3 {
24+
sealed trait Foo
25+
class Bar extends Foo
26+
sealed trait Baz extends Foo
27+
28+
def foo = {
29+
val x: Foo = new Baz {}
30+
x match {
31+
case bar: Bar => 1
32+
case baz: Baz => 2
33+
}
34+
}
35+
36+
def bar = {
37+
val x: Baz = new Baz {}
38+
x match {
39+
case bar: Bar => 1
40+
case baz: Baz => 2
41+
}
42+
}
43+
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
23: Pattern Match Exhaustivity: _: SealedClass & OpenTrait, _: AbstractClass & OpenTrait, _: Clazz & OpenTrait, _: Trait & OpenTrait
2-
27: Pattern Match Exhaustivity: _: SealedClass & OpenTrait & OpenTrait2, _: AbstractClass & OpenTrait & OpenTrait2, _: Clazz & OpenTrait & OpenTrait2, _: Trait & OpenTrait & OpenTrait2
3-
31: Pattern Match Exhaustivity: _: Trait & OpenClass
4-
35: Pattern Match Exhaustivity: _: Trait & OpenTrait & OpenClass
1+
23: Pattern Match Exhaustivity: _: SealedAbstractClass & OpenTrait, _: SealedClass & OpenTrait, _: SealedTrait & OpenTrait, _: AbstractClass & OpenTrait, _: Clazz & OpenTrait, _: Trait & OpenTrait
2+
27: Pattern Match Exhaustivity: _: SealedAbstractClass & OpenTrait & OpenTrait2, _: SealedClass & OpenTrait & OpenTrait2, _: SealedTrait & OpenTrait & OpenTrait2, _: AbstractClass & OpenTrait & OpenTrait2, _: Clazz & OpenTrait & OpenTrait2, _: Trait & OpenTrait & OpenTrait2
3+
31: Pattern Match Exhaustivity: _: SealedTrait & OpenClass, _: Trait & OpenClass
4+
35: Pattern Match Exhaustivity: _: SealedTrait & OpenTrait & OpenClass, _: Trait & OpenTrait & OpenClass
55
40: Match case Unreachable
6-
43: Pattern Match Exhaustivity: _: Trait & OpenAbstractClass
7-
47: Pattern Match Exhaustivity: _: Trait & OpenClass & OpenTrait & OpenClassSubclass
6+
43: Pattern Match Exhaustivity: _: SealedTrait & OpenAbstractClass, _: Trait & OpenAbstractClass
7+
47: Pattern Match Exhaustivity: _: SealedTrait & OpenClass & OpenTrait & OpenClassSubclass, _: Trait & OpenClass & OpenTrait & OpenClassSubclass

tests/patmat/patmatexhaust.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
49: Pattern Match Exhaustivity: _: Gp
55
59: Pattern Match Exhaustivity: Nil
66
75: Pattern Match Exhaustivity: _: B
7+
87: Pattern Match Exhaustivity: _: C1
78
100: Pattern Match Exhaustivity: _: C1
89
114: Pattern Match Exhaustivity: D2(), D1
910
126: Pattern Match Exhaustivity: _: C1

tests/patmat/patmatexhaust.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class TestSealedExhaustive { // compile only
8484
case class C3() extends C
8585
case object C4 extends C
8686

87-
def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end.
87+
def ma10(x: C) = x match { // treat abstract sealed C1 is as inhabited.
8888
case C3() => true
8989
case C2 | C4 => true
9090
}

tests/patmat/t8511.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
18: Pattern Match Exhaustivity: Baz(), Bar(_)
1+
18: Pattern Match Exhaustivity: EatsExhaustiveWarning(_), Baz(), Bar(_)

tests/patmat/t9677.check

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)