Skip to content

Defer

Accepted

Accepted for V1 scope-exit cleanup source semantics.

defer schedules a statement to run when the current lexical block scope exits:

var file = try File.open(path)
defer file.dispose()

The deferred statement runs on every exit edge from that scope:

  • fallthrough
  • return
  • try error propagation
  • break
  • continue

Multiple defers in the same scope run in reverse source order.

defer second()
defer first()

Here first() runs before second() when the scope exits.

defer is statement syntax, not an expression. The deferred statement is checked in a void context; meaningful produced values are discarded only under the normal value-to-void lint policy.

Scope

A defer belongs to the lexical block in which it appears. A defer inside a loop body runs when that iteration's body scope exits, not when the surrounding function exits:

for item in items {
  defer trace_item(item)
  process(item)
}

defer does not run immediately and does not mark a resource cleaned when it is registered. The cleanup action remains pending until the owning scope exits:

var file = try File.open(path)
defer file.dispose()
file.read(buf)

Resource Lints

V1 has no defer cancellation. An active cleanup defer remains scheduled until scope exit. Moving a binding before an active cleanup defer runs is lintable because the deferred cleanup would later target moved-from storage:

var file = try File.open(path)
defer file.dispose()

return move file // lint candidate: ownership/move-with-active-defer

defer file.dispose() is place-based for lint purposes: the cleanup expression is evaluated at scope exit. Reassignment is coherent when the old value is explicitly cleaned and the binding holds a fresh live value by scope exit:

var file = try File.open(path)
defer file.dispose()

file.dispose()
file = try File.open(other)

Disposing without reassignment leaves the active defer as a double-cleanup risk:

var file = try File.open(path)
defer file.dispose()

file.dispose()

The double cleanup is lintable at the scope exit edge as ownership/double-cleanup.

Deferred

V1 has no error-only defer form. A future errdefer statement for cleanup that runs only on error exits is tracked by CEP-0065: Error-Only Defer.