Skip to content

Commit 992f231

Browse files
committed
Change projection approach
1 parent 55f32f4 commit 992f231

File tree

1 file changed

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

1 file changed

+16
-16
lines changed

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

+16-16
Original file line numberDiff line numberDiff line change
@@ -926,36 +926,36 @@ object SpaceEngine {
926926
then project(OrType(selTyp, ConstantType(Constant(null)), soft = false))
927927
else project(selTyp)
928928

929-
@tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree]): Unit =
929+
@tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree], nullCovered: Boolean): Unit =
930930
cases match
931931
case Nil =>
932-
case CaseDef(pat, guard, _) :: rest =>
933-
val curr = trace(i"project($pat)")(project(pat))
932+
case (c @ CaseDef(pat, guard, _)) :: rest =>
933+
val patNullable = Nullables.matchesNull(c)
934+
val curr = trace(i"project($pat)")(
935+
if patNullable
936+
then Or(List(project(pat), Typ(ConstantType(Constant(null)))))
937+
else project(pat))
934938
val covered = trace("covered")(simplify(intersect(curr, targetSpace)))
935939
val prev = trace("prev")(simplify(Or(prevs)))
936940
if prev == Empty && covered == Empty then // defer until a case is reachable
937-
recur(rest, prevs, pat :: deferred)
941+
recur(rest, prevs, pat :: deferred, nullCovered)
938942
else
939943
for pat <- deferred.reverseIterator
940944
do report.warning(MatchCaseUnreachable(), pat.srcPos)
941945

942946
if pat != EmptyTree // rethrow case of catch uses EmptyTree
943947
&& !pat.symbol.isAllOf(SyntheticCase, butNot=Method) // ExpandSAMs default cases use SyntheticCase
944-
&& isSubspace(covered, prev)
948+
&& isSubspace(covered, Or(List(prev, Typ(ConstantType(Constant(null))))))
945949
then
946-
val nullOnly = isNullable && isWildcardArg(pat) && !mayCoverNull(prev)
947-
val msg = if nullOnly then MatchCaseOnlyNullWarning() else MatchCaseUnreachable()
948-
report.warning(msg, pat.srcPos)
950+
val nullOnly = isNullable && isWildcardArg(pat) && !nullCovered && !isSubspace(covered, prev) && (!ctx.explicitNulls || selTyp.isInstanceOf[FlexibleType])
951+
if nullOnly then report.warning(MatchCaseOnlyNullWarning() , pat.srcPos)
952+
else if (isSubspace(covered, prev)) then report.warning(MatchCaseUnreachable(), pat.srcPos)
949953

950954
// in redundancy check, take guard as false in order to soundly approximate
951-
val newPrev = if (guard.isEmpty)
952-
then if (isWildcardArg(pat))
953-
then Typ(ConstantType(Constant(null))) :: covered :: prevs
954-
else covered :: prevs
955-
else prevs
956-
recur(rest, newPrev, Nil)
957-
958-
recur(m.cases, Nil, Nil)
955+
val newPrev = if (guard.isEmpty) then covered :: prevs else prevs
956+
recur(rest, newPrev, Nil, nullCovered || (guard.isEmpty && patNullable))
957+
958+
recur(m.cases, Nil, Nil, false)
959959
end checkReachability
960960

961961
def checkMatch(m: Match)(using Context): Unit =

0 commit comments

Comments
 (0)