Summary
crates/perry-runtime/src/thread.rs:99-100 contains the comment:
No shared mutable state: Closures passed to parallelMap and spawn cannot capture mutable variables. The Perry compiler rejects this at compile time.
There is no compiler pass enforcing that. The HIR Closure struct has a mutable_captures field, but the codegen path for parallelMap / parallelFilter / spawn in crates/perry-codegen/src/expr.rs uses let _ = mutable_captures; — i.e. reads the field to silence the warning and throws it away.
The runtime-side SerializedValue deep-copies the captures, so the effect is that workers get their own snapshot (no aliasing), but that's runtime isolation via deep-copy — not the compile-time safety the comment promises. It's also identical to Node worker_threads semantics, not a Rust-style Send/Sync guarantee.
Evidence
- Comment claiming compile-time rejection:
crates/perry-runtime/src/thread.rs:99-100
- HIR field that's ignored:
mutable_captures in crates/perry-hir/src/ir.rs (closure struct)
- Codegen discarding it:
crates/perry-codegen/src/expr.rs (search for mutable_captures)
unsafe impl Send for SerializedValue without justification: crates/perry-runtime/src/thread.rs:255-256
Options
-
Remove the claim. Update the comment and any docs that promise compile-time thread safety. Describe the actual guarantee: deep-copy message passing, no shared mutable state at runtime because values are cloned across the boundary.
-
Implement the check. Add a HIR pass that walks parallelMap/parallelFilter/spawn call sites, inspects the closure's mutable_captures, and emits a compile error if it captures a mutable ref. This is the harder path but would make the claim true.
Option 1 is the minimum to stop overclaiming; option 2 is the real fix.
Docs impact
Any threading page that talks about "compile-time safety" should be updated (docs/src/threading/*).
Summary
crates/perry-runtime/src/thread.rs:99-100contains the comment:There is no compiler pass enforcing that. The HIR
Closurestruct has amutable_capturesfield, but the codegen path forparallelMap/parallelFilter/spawnincrates/perry-codegen/src/expr.rsuseslet _ = mutable_captures;— i.e. reads the field to silence the warning and throws it away.The runtime-side
SerializedValuedeep-copies the captures, so the effect is that workers get their own snapshot (no aliasing), but that's runtime isolation via deep-copy — not the compile-time safety the comment promises. It's also identical to Node worker_threads semantics, not a Rust-styleSend/Syncguarantee.Evidence
crates/perry-runtime/src/thread.rs:99-100mutable_capturesincrates/perry-hir/src/ir.rs(closure struct)crates/perry-codegen/src/expr.rs(search formutable_captures)unsafe impl Send for SerializedValuewithout justification:crates/perry-runtime/src/thread.rs:255-256Options
Remove the claim. Update the comment and any docs that promise compile-time thread safety. Describe the actual guarantee: deep-copy message passing, no shared mutable state at runtime because values are cloned across the boundary.
Implement the check. Add a HIR pass that walks
parallelMap/parallelFilter/spawncall sites, inspects the closure'smutable_captures, and emits a compile error if it captures a mutable ref. This is the harder path but would make the claim true.Option 1 is the minimum to stop overclaiming; option 2 is the real fix.
Docs impact
Any threading page that talks about "compile-time safety" should be updated (
docs/src/threading/*).