Skip to content

Commit 25b15bf

Browse files
authored
Merge pull request #4869 from abeln/unreachable-case
Fix #4661: Missing unreachable case warnings
2 parents b4670b7 + a1be0cd commit 25b15bf

File tree

6 files changed

+85
-14
lines changed

6 files changed

+85
-14
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with TastyCoreImpl w
1111
}
1212

1313
object CaseDef extends CaseDefExtractor {
14-
def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match {
15-
case x: tpd.CaseDef =>
16-
Some(x.pat, optional(x.guard), x.body)
17-
case _ => None
18-
}
14+
def unapply(x: CaseDef): Some[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body)
1915
}
2016

2117
}

compiler/src/dotty/tools/dotc/tastyreflect/ConstantOpsImpl.scala

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,11 @@ trait ConstantOpsImpl extends scala.tasty.reflect.ConstantOps with TastyCoreImpl
1313
object Constant extends ConstantModule {
1414

1515
object Unit extends UnitExtractor {
16-
def unapply(x: Constant): Boolean = x match {
17-
case x: Constants.Constant => x.tag == Constants.UnitTag
18-
case _ => false
19-
}
16+
def unapply(x: Constant): Boolean = x.tag == Constants.UnitTag
2017
}
2118

2219
object Null extends NullExtractor {
23-
def unapply(x: Constant): Boolean = x match {
24-
case x: Constants.Constant => x.tag == Constants.NullTag
25-
case _ => false
26-
}
20+
def unapply(x: Constant): Boolean = x.tag == Constants.NullTag
2721
}
2822

2923
object Boolean extends BooleanExtractor {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,12 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
293293
private val nullSpace = Typ(nullType)
294294

295295
override def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type): Space = {
296+
// Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1)
297+
if (tp1 == nullType || tp2 == nullType) {
298+
// Since projections of types don't include null, intersection with null is empty.
299+
return Empty
300+
}
296301
val and = AndType(tp1, tp2)
297-
// Precondition: !(tp1 <:< tp2) && !(tp2 <:< tp1)
298302
// Then, no leaf of the and-type tree `and` is a subtype of `and`.
299303
val res = inhabited(and)
300304

tests/patmat/i4880a.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
14: Match case Unreachable

tests/patmat/t4661.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
9: Match case Unreachable
2+
10: Match case Unreachable
3+
11: Match case Unreachable
4+
26: Match case Unreachable
5+
27: Match case Unreachable
6+
28: Match case Unreachable
7+
33: Match case Unreachable
8+
36: Match case Unreachable
9+
37: Match case Unreachable
10+
38: Match case Unreachable
11+
39: Match case Unreachable
12+
40: Only null matched
13+
46: Match case Unreachable
14+
52: Match case Unreachable
15+
59: Only null matched

tests/patmat/t4661.scala

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
trait Foo
2+
class One extends Foo
3+
class Two extends Foo
4+
class Three extends Foo
5+
6+
object Test {
7+
def test(f: Foo) = f match {
8+
case f: Foo =>
9+
case f: One => // unreachable
10+
case f: Two => // unreachable
11+
case f: Three => // unreachable
12+
}
13+
}
14+
15+
trait Prefix {
16+
sealed trait Bar
17+
class BarOne extends Bar
18+
class BarTwo extends Bar
19+
class BarThree extends Bar
20+
}
21+
22+
class TestPrefix(val p: Prefix) {
23+
import p._
24+
def test(b: Bar) = b match {
25+
case b: Bar =>
26+
case b: BarOne => // unreachable
27+
case b: BarTwo => // unreachable
28+
case b: BarThree => // unreachable
29+
}
30+
31+
def test2(b: Bar) = b match {
32+
case b: Prefix#BarOne =>
33+
case b: BarOne => // unreachable
34+
case b: Prefix#BarTwo =>
35+
case b: Prefix#BarThree =>
36+
case b: BarTwo => // unreachable
37+
case b: BarThree => // unreachable
38+
case b: Bar => // unreachable
39+
case b: Prefix#Bar => // unreachable
40+
case _ => // only null matches
41+
}
42+
43+
def test3(b: Prefix#Bar) = b match {
44+
case b: Bar =>
45+
case b: Prefix#BarOne =>
46+
case b: BarOne => // unreachable
47+
case _ =>
48+
}
49+
50+
def test4(b: Bar) = b match {
51+
case b: Bar =>
52+
case b:Prefix#Bar => // unreachable
53+
}
54+
55+
def test5(b: Bar) = b match {
56+
case b: Prefix#BarOne =>
57+
case b: Prefix#BarTwo =>
58+
case b: Prefix#BarThree =>
59+
case _ => // only null matches
60+
}
61+
}

0 commit comments

Comments
 (0)