diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 2216e1a..6753dca 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -964,6 +964,34 @@ Term::Clone { value: Box } ; `(clone X)` — explicit Term::ReuseAs { source: Box, body: Box } ; `(reuse-as SRC NEW-CTOR)` ``` +`Term::ReuseAs` is structured as a *wrapper* around a `body` +term rather than as a `reuse_from: Option` modifier on +`Term::Ctor`. Two substantive reasons: + +1. **Compositional flexibility.** Reuse-as is conceptually a + wrapper that says "this expression's allocation comes from + ``'s slot". The wrapper form generalises naturally + if future iters introduce other allocating constructs + (record literals, opaque box wrappers, capability cells) — + they all become valid `body` positions. A modifier on + `Term::Ctor` would have to be replicated on every + constructible Term variant the language grows. +2. **Source-locality at the head.** `(reuse-as SRC NEW-CTOR)` + reads as a single sentence with the source-binder named at + the head. The modifier form would scatter the reuse intent + across a child position of the constructor's argument + syntax, separating the `source` from the rest of the + reuse-as semantics. + +The trade-off this accepts: the schema permits `Term::ReuseAs +{ body }` where `body` is not an allocating form (e.g. a +literal, a var). Such terms are caught at typecheck via a +`reuse-as-non-allocating-body` diagnostic — structural rejection +in the typechecker, not the schema. This is the same trade-off +Decision 7 made for `Term::If`'s relationship to nested +`Term::Match`: prefer composability over schema-level +rejection where the typecheck rule is unambiguous. + **Iter 18e — `TypeDef` attribute.** ```