Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -948,11 +948,11 @@ class UncheckedTypePattern(argType: Type, whyNot: String)(using Context)
|"""
}

class MatchCaseUnreachable()(using Context)
class MatchCaseUnreachable(why: String = "")(using Context)
extends Message(MatchCaseUnreachableID) {
def kind = MessageKind.MatchCaseUnreachable
def msg(using Context) = "Unreachable case"
def explain(using Context) = ""
override protected def msg(using Context) = "Unreachable case"
override protected def explain(using Context) = why
}

class MatchCaseOnlyNullWarning()(using Context)
Expand Down
7 changes: 3 additions & 4 deletions compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,11 @@ object TypeTestsCasts {
def testCls = effectiveClass(testType.widen)
def unboxedTestCls = effectiveClass(unboxedTestType.widen)

def unreachable(why: => String)(using Context): Boolean = {
if (flagUnrelated)
if (inMatch) report.error(em"this case is unreachable since $why", expr.srcPos)
def unreachable(why: => String)(using Context): false =
if flagUnrelated then
if inMatch then report.error(MatchCaseUnreachable(why), expr.srcPos)
else report.warning(em"this will always yield false since $why", expr.srcPos)
false
}

/** Are `foundCls` and `testCls` classes that allow checks
* whether a test would be always false?
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,8 @@ object SpaceEngine {
if prev == Empty && covered == Empty then // defer until a case is reachable
recur(rest, prevs, pat :: deferred)
else
for pat <- deferred.reverseIterator
do report.warning(MatchCaseUnreachable(), pat.srcPos)
for deferral <- deferred.reverseIterator
do report.warning(MatchCaseUnreachable(), deferral.srcPos)

if pat != EmptyTree // rethrow case of catch uses EmptyTree
&& !pat.symbol.isAllOf(SyntheticCase, butNot=Method) // ExpandSAMs default cases use SyntheticCase
Expand Down
6 changes: 4 additions & 2 deletions tests/neg/i11118.check
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
| If the narrowing is intentional, this can be communicated by adding `.runtimeChecked` after the expression,
| which may result in a MatchError at runtime.
| This patch can be rewritten automatically under -rewrite -source 3.8-migration.
-- Error: tests/neg/i11118.scala:2:4 -----------------------------------------------------------------------------------
-- [E030] Match case Unreachable Error: tests/neg/i11118.scala:2:4 -----------------------------------------------------
2 |val (a,b) = (1,2,3) // error // warning
| ^
| this case is unreachable since type (Int, Int, Int) is not a subclass of class Tuple2
| Unreachable case
|
| longer explanation available when compiling with `-explain`
10 changes: 10 additions & 0 deletions tests/neg/i24789.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//> using options -Werror -explain

case class A(a: Int)
case class B(b: Int)
case class C(c: Int)

val a = (A(1): A | B) match
case A(_) => "OK"
case B(_) => "OK"
case C(_) => "Not OK" // error // nopos-error for the warning
18 changes: 14 additions & 4 deletions tests/neg/i8711.check
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@
19 | case x: (B | C) => x // warn
| ^^^^^^^^^^
| Unreachable case
-- Error: tests/neg/i8711.scala:9:9 ------------------------------------------------------------------------------------
-- [E030] Match case Unreachable Error: tests/neg/i8711.scala:9:9 ------------------------------------------------------
9 | case x: B => x // error: this case is unreachable since class A is not a subclass of class B
| ^
| this case is unreachable since type A and class B are unrelated
-- Error: tests/neg/i8711.scala:14:9 -----------------------------------------------------------------------------------
| Unreachable case
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| type A and class B are unrelated
---------------------------------------------------------------------------------------------------------------------
-- [E030] Match case Unreachable Error: tests/neg/i8711.scala:14:9 -----------------------------------------------------
14 | case x: C => x // error
| ^
| this case is unreachable since type A | B and class C are unrelated
| Unreachable case
|--------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| type A | B and class C are unrelated
--------------------------------------------------------------------------------------------------------------------
No warnings can be incurred under -Werror
2 changes: 1 addition & 1 deletion tests/neg/i8711.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options -Werror
//> using options -Werror -explain

class A
class B
Expand Down
12 changes: 8 additions & 4 deletions tests/neg/named-tuples-2.check
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
-- Error: tests/neg/named-tuples-2.scala:4:9 ---------------------------------------------------------------------------
-- [E030] Match case Unreachable Error: tests/neg/named-tuples-2.scala:4:9 ---------------------------------------------
4 | case (name, age) => () // error
| ^
| this case is unreachable since type (String, Int, Boolean) is not a subclass of class Tuple2
-- Error: tests/neg/named-tuples-2.scala:5:9 ---------------------------------------------------------------------------
| Unreachable case
|
| longer explanation available when compiling with `-explain`
-- [E030] Match case Unreachable Error: tests/neg/named-tuples-2.scala:5:9 ---------------------------------------------
5 | case (n, a, m, x) => () // error
| ^
| this case is unreachable since type (String, Int, Boolean) is not a subclass of class Tuple4
| Unreachable case
|
| longer explanation available when compiling with `-explain`
Loading