@@ -926,36 +926,36 @@ object SpaceEngine {
926
926
then project(OrType (selTyp, ConstantType (Constant (null )), soft = false ))
927
927
else project(selTyp)
928
928
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 =
930
930
cases match
931
931
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))
934
938
val covered = trace(" covered" )(simplify(intersect(curr, targetSpace)))
935
939
val prev = trace(" prev" )(simplify(Or (prevs)))
936
940
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 )
938
942
else
939
943
for pat <- deferred.reverseIterator
940
944
do report.warning(MatchCaseUnreachable (), pat.srcPos)
941
945
942
946
if pat != EmptyTree // rethrow case of catch uses EmptyTree
943
947
&& ! 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 ))))) )
945
949
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)
949
953
950
954
// 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 )
959
959
end checkReachability
960
960
961
961
def checkMatch (m : Match )(using Context ): Unit =
0 commit comments