v35.5.0 — FJARR_LEAK Phase 2 D-FULL (full-strict default-on)
🔐 FJARR_LEAK Phase 2 D-FULL — full-strict default-on
Closes Compass §4.4 "@safe sebagai default" for affine semantics.
All non-primitive types (str, [T], struct, enum, tuple-with-move-fields,
Tensor, Quantized) are now Move by default — reuse after consume requires
explicit .clone(). The --strict-ownership CLI flag is preserved as a no-op
for compatibility (default mode is now what strict mode used to be).
Headline change
is_copy_type(ty)permanently delegates tois_copy_type_strict(ty).--strict-ownershipis no longer required for affine semantics; flag accepted but no-op.
Cascade fixes (Phase 3)
stdlib/parser_ast.fj(1 site):op_precreads fromopi[0]instead of consuming boundop.stdlib/codegen_driver.fj(~30 sites): re-fetch from ast in let-bindings, postpone fn-arg consume to last use, broadvars.clone()/ast.clone()insertions on hot paths.stdlib/analyzer.fj(6 sites):extract_identcalls now.clone()each str/[T] arg.
COW _FjArr runtime (Phase 5)
_FjArr C struct gains int rc. _fj_arr_clone is O(1) refcount-bump (not deep memcpy). _fj_arr_grow does Copy-on-Write deep copy when rc > 1. Without COW, .clone() cascades caused OOM (>26 GB) at chain bootstrap. With COW, phase17 self-compile is unchanged from v35.4.1 within noise: ~50s parallel (default cargo test) / ~101–103s serial (--test-threads=1). D-FULL adds ~0s overhead. (Corrected 2026-05-10 — initial ship-note erroneously reported a 2× slowdown by comparing parallel-baseline vs serial-post-ship; see docs/PHASE17_PERF_B0_FINDINGS.md for the apples-to-apples reproduction.)
Interpreter .clone() recognition
Universal O(1) .clone() for Value::Array/Str/Tensor/Struct/Enum/Tuple/Map/Quantized via Rc/Arc-share. Mutating ops (push etc.) already use Arc::make_mut so sharing is safe.
Test contract migration (Phase 4)
- 7 lib tests in
borrow_lite.rs+type_check/mod.rsflipped fromis_ok()to assert SE024/ME001/ME003. - 12 integration test files updated to the new contract.
- 19 Q6A example files updated with
.clone()insertions (auto viaauto_clone_fix3.py+ manual for f-string/loop cases).
E2 design decision: skip (E2.C)
Methods do not consume receivers. arr.method(x) reads arr without marking it moved — internally consistent with the existing functional-style C runtime where push/pop/etc. return fresh arrays. Documented in docs/D_FULL_OPTION_B_PHASE_PLAN.md §3.
Engineering gates
| Gate | Result |
|---|---|
cargo test --lib |
7,633 / 7,633 PASS |
cargo test --release --test selfhost_stage1_full |
86 / 86 PASS @ ~13.7s |
cargo test --release --test selfhost_phase17_self_compile |
4 / 4 PASS — ~50s parallel / ~101s serial; unchanged from v35.4.1 within noise; Stage 2 byte-equality preserved through D-FULL |
cargo clippy --lib -- -D warnings |
clean |
cargo fmt -- --check |
clean |
Source of truth
docs/FJARR_LEAK_PHASE_2_D_FULL_FINDINGS.md— closure proofdocs/D_FULL_OPTION_B_PHASE_PLAN.md— Phase 1 B0 audit + 5-phase plandocs/D_FULL_CASCADE_B0_FINDINGS.md— initial scope-doc
Predecessors in this arc
v35.1.0 (FJARR_LEAK Phase 1 arena, 88 B/array → 0) → v35.2.0 (Phase 2 D-LITE opt-in) → v35.5.0 (Phase 2 D-FULL default-on).