@@ -938,7 +938,7 @@ object SpaceEngine {
938938 */
939939 private def selectorIsBoundVar (selector : Tree , pat : Tree )(using Context ): Boolean =
940940 pat match
941- case Bind (_, _) => selector.symbol == pat .symbol
941+ case b : Bind => selector.symbol == b .symbol
942942 case _ => false
943943
944944 /** Find the index of the parameter in an outer UnApply pattern that directly binds the selector symbol.
@@ -948,8 +948,7 @@ object SpaceEngine {
948948 *
949949 */
950950 private def selectorParamIndex (selector : Tree , pat : Tree )(using Context ): Option [Int ] =
951- pat match
952- case Bind (_, inner) => selectorParamIndex(selector, inner)
951+ unbind(pat) match
953952 case UnApply (_, _, pats) =>
954953 val idx = pats.indexWhere {
955954 case b : Bind => b.symbol == selector.symbol
@@ -958,30 +957,30 @@ object SpaceEngine {
958957 if idx >= 0 then Some (idx) else None
959958 case _ => None
960959
961- private def projectSubMatch (pat : Tree , sm : SubMatch )(using Context ): Space =
960+ private def projectSubMatch (pat : Tree , sm : SubMatch )(using Context ): Option [ Space ] =
962961 val Match (selector, cases) = sm
963962
964963 val subSpace = Or (cases.map(projectCaseDef))
965964 val selTyp = toUnderlying(selector.tpe)
966965
967966 if selectorIsBoundVar(selector, pat) then
968- simplify(intersect(project(pat), subSpace))
967+ Some ( simplify(intersect(project(pat), subSpace) ))
969968 else selectorParamIndex(selector, pat) match
970969 case Some (idx) =>
971970 project(pat) match
972971 case Prod (tp, unappTp, params) =>
973972 val narrowedParam = simplify(intersect(params(idx), subSpace))
974- simplify(Prod (tp, unappTp, params.updated(idx, narrowedParam)))
975- case other => other
973+ Some ( simplify(Prod (tp, unappTp, params.updated(idx, narrowedParam) )))
974+ case other => Some ( other)
976975 case None =>
977- if simplify(minus(project(selTyp), subSpace)) == Empty then project(pat)
978- else Empty
976+ if simplify(minus(project(selTyp), subSpace)) == Empty then Some ( project(pat) )
977+ else None
979978
980979 /** Project a single CaseDef to the space it definitely covers */
981980 private def projectCaseDef (c : CaseDef )(using Context ): Space =
982981 if ! c.guard.isEmpty then Empty
983982 else c.body match
984- case sm : SubMatch => projectSubMatch(c.pat, sm)
983+ case sm : SubMatch => projectSubMatch(c.pat, sm).getOrElse( Empty )
985984 case _ => project(c.pat)
986985
987986 def checkExhaustivity (m : Match )(using Context ): Unit = trace(i " checkExhaustivity( $m) " ) {
@@ -1032,7 +1031,12 @@ object SpaceEngine {
10321031 cases match
10331032 case Nil =>
10341033 case (c @ CaseDef (pat, _, _)) :: rest =>
1035- val curr = trace(i " project( $pat) " )(projectPat(pat))
1034+ val (curr, hasContrib) = c.body match
1035+ case sm : SubMatch =>
1036+ projectSubMatch(pat, sm) match
1037+ case Some (smSpace) => (smSpace, true )
1038+ case None => (projectPat(pat), false )
1039+ case _ => (projectPat(pat), true )
10361040 val covered = trace(" covered" )(simplify(intersect(curr, targetSpace)))
10371041 val prev = trace(" prev" )(simplify(Or (prevs)))
10381042 if prev == Empty && covered == Empty then // defer until a case is reachable
@@ -1057,8 +1061,8 @@ object SpaceEngine {
10571061 hadNullOnly = true
10581062 report.warning(MatchCaseOnlyNullWarning (), pat.srcPos)
10591063
1060- // in redundancy check, take guard as false (or potential sub cases as partial) for a sound approximation
1061- val newPrev = if ! c.guard.isEmpty || c.body. isInstanceOf [ SubMatch ] then prevs else covered :: prevs
1064+ // in redundancy check, take guard as false for a sound approximation
1065+ val newPrev = if hasContrib && c.guard.isEmpty then covered :: prevs else prevs
10621066 recur(rest, newPrev, Nil )
10631067
10641068 recur(m.cases, Nil , Nil )
0 commit comments