@@ -925,9 +925,39 @@ object SpaceEngine {
925
925
@ tailrec def recur (cases : List [CaseDef ], prevs : List [Space ], deferred : List [Tree ]): Unit =
926
926
cases match
927
927
case Nil =>
928
- case CaseDef (pat, guard, _) :: rest =>
928
+ case (c @ CaseDef (pat, guard, _)) :: rest =>
929
+ def checkForUnnecessaryNullable (p : Tree ): Unit = p match {
930
+ case Bind (_, body) => checkForUnnecessaryNullable(body)
931
+ case Typed (expr, tpt) =>
932
+ if tpt.tpe.isNullableUnion(stripFlexibleTypes = false , forceStrip = true ) then
933
+ report.warning(MatchCaseUnnecessaryNullable (tpt.tpe), p.srcPos)
934
+ else
935
+ checkForUnnecessaryNullable(expr)
936
+ case UnApply (_, _, patterns) =>
937
+ patterns.map(checkForUnnecessaryNullable)
938
+ case Alternative (patterns) => patterns.map(checkForUnnecessaryNullable)
939
+ case _ =>
940
+ }
941
+
942
+ def handlesNull (p : Tree ): Boolean = p match {
943
+ case Literal (Constant (null )) => true
944
+ case Typed (expr, tpt) => tpt.tpe.isSingleton || handlesNull(expr) // assume all SingletonType's handle null (see redundant-null.scala)
945
+ case Bind (_, body) => handlesNull(body)
946
+ case Alternative (patterns) => patterns.exists(handlesNull)
947
+ case _ => false
948
+ }
929
949
val curr = trace(i " project( $pat) " )(projectPat(pat))
930
- val covered = trace(" covered" )(simplify(intersect(curr, targetSpace)))
950
+ var covered = trace(" covered" )(simplify(intersect(curr, targetSpace)))
951
+
952
+ checkForUnnecessaryNullable(pat)
953
+
954
+ if ! handlesNull(pat) && ! isWildcardArg(pat) then
955
+ // Remove nullSpace from covered only if:
956
+ // 1. No pattern is the null constant (e.g., `case null =>` or `case ... | null | ... =>`) or
957
+ // has a SingletonType (e.g., `case _: n.type =>` where `val n = null`, see redundant-null.scala) in one of its pattern(s)
958
+ // 2. The pattern is a wildcard pattern.
959
+ covered = minus(covered, nullSpace)
960
+
931
961
val prev = trace(" prev" )(simplify(Or (prevs)))
932
962
if prev == Empty && covered == Empty then // defer until a case is reachable
933
963
recur(rest, prevs, pat :: deferred)
0 commit comments