Skip to content

Commit 6463216

Browse files
olwangclaude
andcommitted
docs: mark L1 (first-class owned Fn + mut-Ctx params) done; L2 unblocked
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a38dc85 commit 6463216

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

docs/planning/declarative-rewrite-roadmap.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,20 @@ is narrow and one-directional.
6565

6666
## Layered plan (priority order)
6767

68-
1. **L1 — language (keystone): make `owned Fn` a first-class value.** Lift the
69-
"parameter-position-only" gate so `owned Fn(args) -> ret` is allowed as a
70-
generic type argument (`List<owned Fn ...>`), a struct field, and a
71-
`let`/`local` binding; accept a closure literal as a value expression; and
72-
resolve a call on a closure-typed binding (`f(x)`). Keep `noescape`/`read Fn`
73-
parameter-only. Work is **parser + checker** (type a closure literal as
74-
`owned Fn`; allow it in storable positions; resolve closure-value calls) plus a
75-
**lowering** glue step (emit closure values + `Box<dyn FnMut>` in non-parameter
76-
positions, call closure-typed loads) — all on the existing
77-
`MakeClosure`/`CallClosure` + `Box<dyn FnMut>` substrate. Parity-gated like any
78-
feature. Everything else rides on this.
68+
1. **L1 — language (keystone): make `owned Fn` a first-class value. ✅ DONE.**
69+
`owned Fn(args) -> ret` is now a first-class value: usable as a generic type
70+
argument (`List<owned Fn ...>`), a struct field, a `let`/`local` binding, and a
71+
return type; closure literals are accepted in value position; calls on a
72+
closure-typed binding resolve (`let f = r.fxn; f(args)`). owned-only stays the
73+
rule (`noescape`/`read Fn` remain parameter-only — storing a borrow-capturing
74+
closure is unsound). Stored closures lower to `Rc<dyn Fn(..)>` (Clone-able
75+
through `List.get`, callable via shared ref). **L1b ✅ DONE:** `Fn`-type
76+
parameters now carry `read`/`mut`/`take` effects end to end, so a rule can take
77+
`owned Fn(read UOp, mut Ctx) -> Option<UOp>` and mutate `ctx` in-body (exclusive
78+
borrow for the call, sound + explicit) — the ctx-mutating rules transliterate
79+
1:1. Verified e2e at VM↔compiled parity (`tests/vm_eval_parity/owned_fn.rs`:
80+
toy probe, PatternMatcher shape, and `mut Ctx` rule). So the keystone is in;
81+
L2 is now unblocked and needs **no further language change**.
7982
2. **L2 — library/runtime: PatternMatcher + graph_rewrite.** With L1, build a
8083
`UOp`/`UPat` type and a native `graph_rewrite(sink, rules, bottom_up, name)`
8184
driver (fixpoint + memoization) plus a gated `toposort(gate: Fn(UOp)->Bool)`

0 commit comments

Comments
 (0)