You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR introduces the `do← body` marker (ASCII `do<- body`), which lets
ordinary continuation-taking wrappers like `withReader` or
`Meta.withLocalDecl` participate in the surrounding `do` block's control
flow. When `do← body` appears as the last argument of an application
inside a `do` block, the body's `return`, `break`, `continue`, and
`mut`-variable reassignments are forwarded out through the wrapper to
the enclosing block.
```lean
example : ReaderT Ctx IO Nat := do
let mut x := 0
withReader (·.bump) (do←
if cond then return 0 -- early-returns from the outer `do`
x := x + 1) -- mutates the outer `x`
return x
```
The syntax is reminiscent of a nested action `(← body)`, but unlike a
nested action, `body` is not run eagerly in the `do` block context
before the wrapping function is called. The wrapping function decides
when to run `body`, and code is inserted to forward `body`'s effects to
the outer `do` block.
Internally, `elabDoExpr` and the `ControlInfo` inferer recognise the
marker and route the body through the same `EffectForwarder` framework
that already powers `try`/`catch`. The framework now lets each caller
decide whether the surrounding continuation is dead: `try`/`catch`
propagates `info.noFallthrough`, while `do←` always treats the
continuation as live (an opaque wrapper might not invoke the body at
all). A new `DoElemCont.withDeadCodeFromInfo` helper captures the shared
pattern. A wrapper validator rejects shapes that don't fit `(… → m α) →
m α` with a polymorphic `α` (e.g. `withConst`, `foldlM`) up front with a
dedicated diagnostic, rather than letting a downstream type mismatch
surface. `dropParens` moves from `Lean.Elab.Term` to `Lean.Parser.Term`
since it is a generic term-syntax utility.
0 commit comments