Skip to content

Commit 158c1df

Browse files
committed
Change projection approach
1 parent 59173cd commit 158c1df

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -937,36 +937,36 @@ object SpaceEngine {
937937
then project(OrType(selTyp, ConstantType(Constant(null)), soft = false))
938938
else project(selTyp)
939939

940-
@tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree]): Unit =
940+
@tailrec def recur(cases: List[CaseDef], prevs: List[Space], deferred: List[Tree], nullCovered: Boolean): Unit =
941941
cases match
942942
case Nil =>
943-
case CaseDef(pat, guard, _) :: rest =>
944-
val curr = trace(i"project($pat)")(project(pat))
943+
case (c @ CaseDef(pat, guard, _)) :: rest =>
944+
val patNullable = Nullables.matchesNull(c)
945+
val curr = trace(i"project($pat)")(
946+
if patNullable
947+
then Or(List(project(pat), Typ(ConstantType(Constant(null)))))
948+
else project(pat))
945949
val covered = trace("covered")(simplify(intersect(curr, targetSpace)))
946950
val prev = trace("prev")(simplify(Or(prevs)))
947951
if prev == Empty && covered == Empty then // defer until a case is reachable
948-
recur(rest, prevs, pat :: deferred)
952+
recur(rest, prevs, pat :: deferred, nullCovered)
949953
else
950954
for pat <- deferred.reverseIterator
951955
do report.warning(MatchCaseUnreachable(), pat.srcPos)
952956

953957
if pat != EmptyTree // rethrow case of catch uses EmptyTree
954958
&& !pat.symbol.isAllOf(SyntheticCase, butNot=Method) // ExpandSAMs default cases use SyntheticCase
955-
&& isSubspace(covered, prev)
959+
&& isSubspace(covered, Or(List(prev, Typ(ConstantType(Constant(null))))))
956960
then
957-
val nullOnly = isNullable && isWildcardArg(pat) && !mayCoverNull(prev)
958-
val msg = if nullOnly then MatchCaseOnlyNullWarning() else MatchCaseUnreachable()
959-
report.warning(msg, pat.srcPos)
961+
val nullOnly = isNullable && isWildcardArg(pat) && !nullCovered && !isSubspace(covered, prev) && (!ctx.explicitNulls || selTyp.isInstanceOf[FlexibleType])
962+
if nullOnly then report.warning(MatchCaseOnlyNullWarning() , pat.srcPos)
963+
else if (isSubspace(covered, prev)) then report.warning(MatchCaseUnreachable(), pat.srcPos)
960964

961965
// in redundancy check, take guard as false in order to soundly approximate
962-
val newPrev = if (guard.isEmpty)
963-
then if (isWildcardArg(pat))
964-
then Typ(ConstantType(Constant(null))) :: covered :: prevs
965-
else covered :: prevs
966-
else prevs
967-
recur(rest, newPrev, Nil)
968-
969-
recur(m.cases, Nil, Nil)
966+
val newPrev = if (guard.isEmpty) then covered :: prevs else prevs
967+
recur(rest, newPrev, Nil, nullCovered || (guard.isEmpty && patNullable))
968+
969+
recur(m.cases, Nil, Nil, false)
970970
end checkReachability
971971

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

0 commit comments

Comments
 (0)