plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
8805ee9
— Peter John
2026-11-02T18:41:53+05:30
docs(plans): closure field-assignment fix review plan
docs/plans/2026-11-02-closure-field-assign.review.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Fix: a closure assigning two fields of a captured record
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
A closure that assigns more than one field of a record it captures fails to compile:
|
|
5
|
+
|
|
6
|
+
```plum
|
|
7
|
+
record Pair2(x: Int, y: Int)
|
|
8
|
+
|
|
9
|
+
test "t"
|
|
10
|
+
m := Pair2(x: 0, y: 0)
|
|
11
|
+
f := ||
|
|
12
|
+
m.x = 5
|
|
13
|
+
m.y = 6
|
|
14
|
+
f()
|
|
15
|
+
assert m.y == 6
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
It fails with `codegen error: codegen: cannot assign field 'x' on non-class type Int`. A single field assignment works, and so do two assignments on a closure *parameter*. The bug was found while building `std/game/Scene`, which had to work around it. Repros are in the session scratchpad (`zi-bugs/a.plum`, `b.plum`, `d.plum`).
|
|
19
|
+
|
|
20
|
+
## What changes for Plum code
|
|
21
|
+
Nothing new to learn: the snippet above compiles and the test passes. Any number of field assignments to a captured record, through any mix of statements, works the same as it does outside a closure.
|
|
22
|
+
|
|
23
|
+
## Work, in order
|
|
24
|
+
1. Add a failing regression test in plum-wasm-codegen/tests for the repro and its variants:
|
|
25
|
+
- two and three field assignments;
|
|
26
|
+
- the assigned value from a captured local (`m.x = k`, `m.y = k + 1`);
|
|
27
|
+
- a nested record field (`m.inner.x = 1`);
|
|
28
|
+
- a struct (value type) captured, which must keep its current semantics, whatever those are; document them;
|
|
29
|
+
- a read after the closure call.
|
|
30
|
+
2. Find the root cause in codegen (closure capture of a record, probably the captured variable's type after the first statement), and fix it there rather than special-casing two assignments.
|
|
31
|
+
3. Remove the workaround in `plum-std/game/Scene.plum` if it's still there, keeping its tests green.
|
|
32
|
+
|
|
33
|
+
## How we will know it works
|
|
34
|
+
- The new tests pass, along with `cargo test --workspace` and `plum test plum-std plum-examples plum-game/web-test/fixtures`.
|
|
35
|
+
- `plum-examples/scene.plum` and `game.plum` still pass the browser check.
|
|
36
|
+
|
|
37
|
+
## Not in scope
|
|
38
|
+
- Other closure features: capture by reference semantics for structs beyond documenting current behaviour, and `fn(..)?` optional function types.
|