Ship

Old Docs · Resource Cleanup
On this page · 5 sections

Resource Cleanup

Decision

  • defer scopes to the nearest lexical block, not the surrounding function.

  • with name = manager { ... } is the typed region surface for paired resources, and try name = manager { body } { arms } recovers where the region ends. Resource scopes owns both.

  • provide service lifecycle uses the same scope model: drop sees the ScopeExit of its body.

  • A failure that ended a scope's own resource reaches its cleanup as ScopeExit.Ended. Terminal failures owns it.

  • GC finalizers/destructors are not Ship’s primary cleanup contract.

Rejects

RejectedWhy
Go function-scoped deferLoops would accumulate cleanup until function return
GC destructors / finalizersNot timely for files, locks, txns, spans, fixtures
Rust ownership/destructor defaultGC-first; scopes own cleanup
Python exception-suppressing exitA manager decides cleanup, never the outcome; recover with try
errdeferOutcome-aware with + ScopeExit cover the space
Exits through a with bodyA region ends only with its value or its failure

defer

Block statement, not expression. Registration when execution reaches the statement; LIFO drain on all exits (return, break, error, interruption):

for path in paths {
  let file = File.open(path);
  defer File.close(file);
  process(file);
} // close each iteration — not at function return

{
  defer Log.info("first");
  defer Log.info("second");
} // second, then first

Captures behave like ordinary closures at the defer site; test loop captures explicitly.

Open Work

  • Fallible cleanup. With.execute is total, so a commit that fails with an expected error cannot report it as one; it can only fail as a defect. A database manager needs its own errors, such as :db(...) from COMMIT, to join the region's error row and its flat Cause.

  • The body receives the manager itself; an associated yielded resource type is later. Async enter/exit and effect-yielding builders remain follow-up.

  • Scope settlement masks interruption until cleanup closes the scope, but an interrupt the scheduler injects into a fiber is not masked, as with defer.

Linear Resources

Linearity/uniqueness/multiplicity are precision tools where duplication or escape is unsafe — not the default SaaS cleanup model. Lexical scopes first.