Skip to content

Commit 5e9b757

Browse files
committed
Emit deferred reachability warnings
1 parent e8255c9 commit 5e9b757

File tree

1 file changed

+25
-10
lines changed
  • compiler/src/dotty/tools/dotc/transform/patmat

1 file changed

+25
-10
lines changed

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

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,9 @@ class SpaceEngine(using Context) extends SpaceLogic {
900900
def checkRedundancy(_match: Match): Unit = {
901901
debug.println(s"---------------checking redundant patterns ${_match.show}")
902902

903-
val Match(sel, cases) = _match
903+
val Match(sel, _) = _match
904+
val cases = _match.cases.toIndexedSeq
905+
904906
val selTyp = sel.tpe.widen.dealias
905907

906908
if (!redundancyCheckable(sel)) return
@@ -911,7 +913,14 @@ class SpaceEngine(using Context) extends SpaceLogic {
911913
else project(selTyp)
912914
debug.println(s"targetSpace: ${show(targetSpace)}")
913915

914-
cases.iterator.zipWithIndex.foldLeft(Nil: List[Space]) { case (prevs, (CaseDef(pat, guard, _), i)) =>
916+
var i = 0
917+
val len = cases.length
918+
var prevs = List.empty[Space]
919+
var deferred = List.empty[Tree]
920+
921+
while (i < len) {
922+
val CaseDef(pat, guard, _) = cases(i)
923+
915924
debug.println(i"case pattern: $pat")
916925

917926
val curr = project(pat)
@@ -923,18 +932,24 @@ class SpaceEngine(using Context) extends SpaceLogic {
923932
val covered = simplify(intersect(curr, targetSpace))
924933
debug.println(s"covered: ${show(covered)}")
925934

926-
if pat != EmptyTree // rethrow case of catch uses EmptyTree
927-
&& prev != Empty // avoid isSubspace(Empty, Empty) - one of the previous cases much be reachable
928-
&& isSubspace(covered, prev)
929-
then {
930-
if isNullable && i == cases.length - 1 && isWildcardArg(pat) then
931-
report.warning(MatchCaseOnlyNullWarning(), pat.srcPos)
932-
else
935+
if prev == Empty && covered == Empty then // defer until a case is reachable
936+
deferred ::= pat
937+
else {
938+
for (pat <- deferred.reverseIterator)
933939
report.warning(MatchCaseUnreachable(), pat.srcPos)
940+
if pat != EmptyTree // rethrow case of catch uses EmptyTree
941+
&& isSubspace(covered, prev)
942+
then {
943+
val nullOnly = isNullable && i == len - 1 && isWildcardArg(pat)
944+
val msg = if nullOnly then MatchCaseOnlyNullWarning() else MatchCaseUnreachable()
945+
report.warning(msg, pat.srcPos)
946+
}
947+
deferred = Nil
934948
}
935949

936950
// in redundancy check, take guard as false in order to soundly approximate
937-
(if guard.isEmpty then covered else Empty) :: prevs
951+
prevs ::= (if guard.isEmpty then covered else Empty)
952+
i += 1
938953
}
939954
}
940955
}

0 commit comments

Comments
 (0)