You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
check-rust: linear SSA for let mut reassignment (#1465)
## Summary
Implements straight-line `let mut` reassignment encoding for `assura
check-rust` (the residual called out after epic #1456).
### Why it was skipped in #1459 / PR #1464
- #1459 AC allowed **encode *or* residual rewrite hints**; demos closed
without needing `+=`
- Linear SSA is still a real encoder change with soundness edges
(CFG-shaped mutation)
- Epic batch prioritized demos/docs/interop over deeper body encode
### What this does
- Extend `fold_simple_lets` to apply `x = e` and `x += e` (and other
assign-ops) on a **straight-line** path
- Still BNM for assigns inside `if` / `match` / loops (no full CFG SSA)
- Unit + integration tests; docs residual tables updated
### Not in scope
- Full SSA / phi nodes / loop mutation
- Verus-level borrow modeling
## Test plan
- [x] `cargo test -p assura --lib --locked let_mut_`
- [x] `cargo test -p assura --test check_rust_body_ir --locked let_mut`
- [x] Manual: `assura check-rust` on `let mut y = x; y += 1; y` with
`@ensures result == x + 1` → verified
---------
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -213,12 +213,12 @@ gaps):
213
213
|-------|--------|
214
214
| Panic paths (`/0`, `%0`, `/`/`%` with zero-including path divisors, `is_multiple_of(0)`, literal `0.ilog2()`) | Soundness: do not encode panic as free SMT div/mod |
215
215
|`rem_euclid`/`div_euclid`/`div_ceil`/`next_multiple_of` with non-positive or zero-including divisors | Same soundness rule; use a positive const or `NonZeroU*` param |
216
-
|`let mut y = x; y += 1; y` (reassignment) | Pure `let mut` fold only (#1343); mutation/SSA not modeled; rewrite to pure lets|
216
+
|Assignments inside `if`/`match`/loops (not linear) | Linear SSA fold only; straight-line `let mut y = x; y += 1; y` is modeled|
217
217
| Bare `checked_*` / `overflowing_*` without peel (Option or `(T, bool)` return as the result type) | Intentional: peel with `.unwrap_or` / `.unwrap_or_default` / `.is_some()` / `.is_none()` / `.0` / `.1`; full Option/tuple values are not IR types |
218
218
219
-
CLI prints these rewrite hints on `body_not_modeled` exit (pointing at
220
-
`docs/CHECK-RUST-SURFACE.md`). Full SSA mutation encode is tracked under
221
-
the check-rust competitiveness epic, not required for residual honesty.
219
+
CLI prints rewrite hints on `body_not_modeled` exit (pointing at
220
+
`docs/CHECK-RUST-SURFACE.md`). Straight-line `let mut` reassignment is
221
+
folded in `fold_simple_lets` (linear SSA); CFG-shaped mutation remains residual.
222
222
223
223
Signed path-param `reverse_bits`/`swap_bytes`/`count_*`/`trailing_*`/`leading_*`
224
224
use synthetic `2^64` bit-pattern map for full i64 (same as `count_ones`).
@@ -99,7 +99,7 @@ reports `body_not_modeled` and exits **1**. They are not silent Verified.
99
99
100
100
| Shape | Why / what to do |
101
101
|-------|------------------|
102
-
|`let mut y = x; y += 1; y` (reassignment) | Pure `let mut` fold only; mutation/SSA not modeled. Prefer pure expressions or immutable lets. |
102
+
|Assignments inside `if` / `match` / loops | Linear SSA only (no CFG). Rewrite to pure expressions or branch-local values. |
103
103
| Bare `checked_*` / `overflowing_*` as the **return type** (full `Option` / `(T, bool)`) | Peel: `.unwrap_or` / `.unwrap_or_default` / `.is_some()` / `.is_none()` / `.0` / `.1`. Full Option/tuple values are not IR result types. |
104
104
| Bodies outside Bucket A (I/O, arbitrary methods, complex ADTs, …) | Supply a co-located `{Name}.ir`, simplify the body, or keep contracts on `.assura` + generated code. |
0 commit comments