lean4-htt/tests/elab/doControlInfoAggregate.lean
Sebastian Graf a1240f7b80
fix: correct alternative-fold base in do match (#13491)
This PR fixes the `ControlInfo` inference for a do-block `match`: the
fold over the match arms started from `ControlInfo.pure` (defaults to
`numRegularExits := 1`, `noFallthrough := false`), but `alternative`
sums `numRegularExits` and ANDs `noFallthrough`, so the fold identity is
`{ numRegularExits := 0, noFallthrough := true }`. With the wrong base,
a `match` whose arms all `break`/`continue`/`return` reported
`numRegularExits = 1` and `noFallthrough = false`, suppressing the
dead-code warning on the continuation after the match. The fix corrects
both the inference handler in `InferControlInfo.lean` and the fold in
`elabDoMatchCore`.
2026-04-22 13:25:30 +00:00

82 lines
2.3 KiB
Text

set_option backward.do.legacy false
-- When an inner doElem's `ControlInfo` has `numRegularExits := 0` (because all branches
-- `break`/`continue`/`return`, or it is a non-terminating `repeat`), the trailing `return`
-- inside the enclosing `for` body used to be dropped during inference, and the for elaborator
-- then threw "Early returning ... but the info said there is no early return" even though the
-- elaborator does visit the trailing element. `ofSeq`/`ControlInfo.sequence` now aggregate
-- `breaks`/`continues`/`returnsEarly`/`reassigns` past `numRegularExits == 0` elements, so the
-- inferred info matches what the elaborator actually sees.
/--
warning: This `do` element and its control-flow region are dead code. Consider refactoring your code to remove it.
-/
#guard_msgs in
example (cond : Bool) : IO Nat := do
for _ in [1, 2] do
if cond then break else break
return 42
return 1
/--
warning: This `do` element and its control-flow region are dead code. Consider refactoring your code to remove it.
-/
#guard_msgs in
example (cond : Bool) : IO Nat := do
for _ in [1, 2] do
if cond then continue else continue
return 42
return 1
/--
warning: This `do` element and its control-flow region are dead code. Consider refactoring your code to remove it.
-/
#guard_msgs in
example (i : Nat) : IO Nat := do
for _ in [1, 2] do
match i with
| 0 => break
| _ => break
return 42
return 1
/--
warning: This `do` element and its control-flow region are dead code. Consider refactoring your code to remove it.
-/
#guard_msgs in
example : IO Nat := do
for _ in [1, 2] do
try break catch _ => break
return 42
return 1
/--
warning: This `do` element and its control-flow region are dead code. Consider refactoring your code to remove it.
-/
#guard_msgs in
example (cond : Bool) : IO Nat := do
for _ in [1, 2] do
unless cond do break
if cond then break else break
return 42
return 1
#guard_msgs in
example : IO Nat := do
for _ in [1, 2] do
repeat
pure ()
return 42
return 1
-- The `return 2` is required to give the do block its `Id Nat` result type; no dead-code warning
-- should fire on it.
#guard_msgs in
example (x : Nat) : Id Nat := do
if x = 3 then
repeat
pure ()
else
repeat
pure ()
return 2