Skip to content

feat(codegen): recursive reassignment + read scan in optimizer passes - #1462

Closed
gHashTag wants to merge 2 commits into
feat/mut-inference-clean-2026-07-13from
feat/recursive-opt-scan-2026-07-13
Closed

gHashTag wants to merge 2 commits into
feat/mut-inference-clean-2026-07-13from
feat/recursive-opt-scan-2026-07-13

Conversation

@gHashTag

@gHashTag gHashTag commented Jul 13, 2026 •

Copy link
Copy Markdown
Owner

What

Three optimizer passes (const_propagate, copy_propagate, dead_store_elim) checked for reassignment/reads only at the top-level statement list, without recursing into if/while/for bodies. Locals reassigned inside conditionals had their let dropped or identifiers inlined, leaving dangling references (E0425).

Fixes #1464

How

Recursive reassignment and read scanning in all three passes:

  • const_propagate: uses assigns_to_recursive() instead of top-level scan
  • copy_propagate: same recursive check before inlining
  • dead_store_elim: collect_reads_in_stmts() recurses into control-flow bodies
  • New helper assigns_to_recursive(): mirrors collect_mutable_names pattern

Measured impact (tri-net, cross-env verified)

Before (#1461 only):  208 errors (E0384 fixed, E0425 remains)
After (#1461+#1462):  26 errors (E0425 fixed, remaining = E0107 Vec generics)

Cross-env verified: 28 errors on linux, 26 on macOS arm64 (±2 platform tolerance).

Files

bootstrap/src/compiler.rs — +50 lines (3 pass fixes + helper function)

Stacked on #1461 (mut-inference).

phi^2 + phi^-2 = 3

Three surgical fixes to the optimizer that together let mut-inference
(PR #1461) actually deliver clean gen/rust on downstream repos:

1. const_propagate: reassigned-check now uses collect_mutable_names,
   which already recurses into if/while/for/for-range bodies. Previously
   a `let X = <literal>` reassigned INSIDE a control-flow block was
   incorrectly considered non-reassigned, inlined, and its declaration
   dropped, leaving dangling `X = ...` reassignments in emit.

2. copy_propagate: same recursive reassigned-check guard added. A
   `let X = Y` where X is reassigned later (including inside
   control-flow) is no longer copy-propagated.

3. dead_store_elim: new helper collect_reads_in_stmts recurses into
   if/while/for/for-range bodies when building the `reads` set. Without
   this a `let i = 0;` that is only read inside a `while` body was
   seen as dead and eliminated. StmtAssign with a simple-identifier LHS
   still contributes only the RHS to `reads` (pre-existing dead-store
   semantics preserved).

Measured on tri-net specs (all 119 regenerated):
- baseline PR #1461 (SHA 6171697): cargo check --lib -> 208 errors
  (145x E0425 cannot-find-value, 26x E0107 Vec generics, misc)
- this PR: cargo check --lib -> 28 errors
  (26x E0107 Vec generics, 2x independent)
- delta: -180 errors, -87%. E0425 -> 0.

t27c own tests: 1491 passed / 3 failed. Same 3 pre-existing failures
(#1401 let_binding_is_lowered / test_let_binding_emitted_{c,rust}_1401)
that already fail on baseline 6171697; not a regression from this PR.

FROZEN_HASH re-sealed via bootstrap/stage0 ceremony.

Remaining 28 errors are independent bugs (Vec<> generics elision and
2 type-inference edge cases), not touched by this PR.

phi^2 + phi^-2 = 3
@gHashTag
gHashTag deleted the branch feat/mut-inference-clean-2026-07-13 July 13, 2026 07:22
@gHashTag gHashTag closed this Jul 13, 2026
gHashTag pushed a commit that referenced this pull request Jul 13, 2026
gHashTag added a commit that referenced this pull request Jul 13, 2026
…#1465)

* feat(codegen): recursive reassignment + read scan in optimizer passes

Three surgical fixes to the optimizer that together let mut-inference
(PR #1461) actually deliver clean gen/rust on downstream repos:

1. const_propagate: reassigned-check now uses collect_mutable_names,
   which already recurses into if/while/for/for-range bodies. Previously
   a `let X = <literal>` reassigned INSIDE a control-flow block was
   incorrectly considered non-reassigned, inlined, and its declaration
   dropped, leaving dangling `X = ...` reassignments in emit.

2. copy_propagate: same recursive reassigned-check guard added. A
   `let X = Y` where X is reassigned later (including inside
   control-flow) is no longer copy-propagated.

3. dead_store_elim: new helper collect_reads_in_stmts recurses into
   if/while/for/for-range bodies when building the `reads` set. Without
   this a `let i = 0;` that is only read inside a `while` body was
   seen as dead and eliminated. StmtAssign with a simple-identifier LHS
   still contributes only the RHS to `reads` (pre-existing dead-store
   semantics preserved).

Measured on tri-net specs (all 119 regenerated):
- baseline PR #1461 (SHA 6171697): cargo check --lib -> 208 errors
  (145x E0425 cannot-find-value, 26x E0107 Vec generics, misc)
- this PR: cargo check --lib -> 28 errors
  (26x E0107 Vec generics, 2x independent)
- delta: -180 errors, -87%. E0425 -> 0.

t27c own tests: 1491 passed / 3 failed. Same 3 pre-existing failures
(#1401 let_binding_is_lowered / test_let_binding_emitted_{c,rust}_1401)
that already fail on baseline 6171697; not a regression from this PR.

FROZEN_HASH re-sealed via bootstrap/stage0 ceremony.

Remaining 28 errors are independent bugs (Vec<> generics elision and
2 type-inference edge cases), not touched by this PR.

phi^2 + phi^-2 = 3

* docs(NOW): update for recursive optimizer scan PR #1462 (Fixes #1464)

phi^2 + phi^-2 = 3

---------

Co-authored-by: Perplexity Computer <agent@perplexity.ai>
Co-authored-by: SSD DDD <ssdm4@MacBook-Pro.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant