From 52b129f558e5b9b37c95670d881b147e2b44701b Mon Sep 17 00:00:00 2001 From: Brummel Date: Fri, 8 May 2026 01:55:15 +0200 Subject: [PATCH] =?UTF-8?q?DESIGN:=20clarify=20Iter=2018a=20schema=20?= =?UTF-8?q?=E2=80=94=20modes=20are=20Type::Fn=20metadata,=20not=20Type=20v?= =?UTF-8?q?ariants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids the ~190 Type match-arms in the typechecker that a new Type variant would require. ParamMode enum (Implicit | Own | Borrow) attaches per-param to Type::Fn, with serde defaults so existing fixture hashes stay bit-identical. --- docs/DESIGN.md | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index ce8a52c..8f049a9 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -883,21 +883,46 @@ extension (e.g. linear ownership) or be rejected at design time. ### Schema additions -**Iter 18a — mode wrappers on `Type`.** +**Iter 18a — parameter modes on `Type::Fn`.** + +The form-A surface for fn signatures gains mode wrappers: ``` -Type::Borrow(Box) ; `(borrow T)` in form-A -Type::Own(Box) ; `(own T)` in form-A +(fn-type (params (borrow (List Int))) (ret (con Int))) +(fn-type (params (own (List Int))) (ret (own (List Int)))) ``` -Both are transparent for unification (they erase to their inner -`Type` for HM purposes) but carry binding mode metadata for the -RC pipeline. Skipped during JSON serialisation when absent so -canonical hashes of every pre-18a fixture stay bit-identical. +Internally, this is *not* a new `Type` variant. Modes are +metadata on `Type::Fn`: + +```rust +Type::Fn { + params: Vec, + param_modes: Vec, // same length as params + ret: Box, + ret_mode: ParamMode, + effects: Vec, +} + +enum ParamMode { Implicit, Own, Borrow } // default: Implicit +``` + +`Implicit` is the legacy (pre-18a) state — semantically +equivalent to `Own` but printed bare (`(con T)`, no wrapper). +`Own` and `Borrow` are explicitly annotated. The implementation +keeps `Type` itself unchanged, so unification, occurs, apply, +and ~190 other `Type` match-arms in the typechecker need no new +branch. + +JSON canonical hash for every pre-18a fixture stays bit- +identical: `param_modes` is skipped when every entry is +`Implicit`, `ret_mode` is skipped when `Implicit`. Existing +modules emit the same bytes as before. + The legacy `(con T)` form is treated as `(own T)` semantically throughout the 18-series; a later iter (deferred) makes the -explicit annotation mandatory and rejects bare `(con T)` for -boxed parameter types. +explicit annotation mandatory and rejects `Implicit` for boxed +parameter types. **Iter 18c/18d — new `Term` variants.**