defer is a compile-time construct: the cleanup is copied into every exit path of the function. That is why a loop body and a branch are refused — a loop body's would fire once at function exit rather than once per iteration, and a branch would have to express "maybe registered", which a form copied into every exit path or into none cannot say. A let is neither. It is not a frame here: its bindings are function slots like any other and nothing is released at scope exit, so a let at the top level of a function body has exactly the function's extent and a defer written in it always registers. It was refused for a reason that does not apply to it. A let nested inside such a let has the same extent and the same permission; a let inside a while or an if has the loop's or the arm's, and inherits the refusal. The permission is granted again before every form of a body, never once around the body: check withdraws it as it starts, so granting it once would let the first defer through and refuse the second — and two resources acquired in one let is the case this exists for. defer-let.flan covers that one specifically, along with nesting, interleaved registration order across the let boundary, and an early return. The two refusals that stay now name what blocks them.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%