Commit 24b8f04
authored
Per-invariant source ranges for loop-invariant diagnostics (#1361)
## Summary
Loop-invariant verification diagnostics (a failing `invariant(...)` in a
`while`/`for` loop) previously pointed at the **whole loop** instead of
the specific invariant that failed. This change threads each invariant's
source range through the loop's metadata so loop elimination can
attribute each invariant's verification condition to that invariant's
own source location.
This support is required for
[JVerify#437](strata-org/jverify#437)
## Problem
In Strata, loop-invariant proof obligations are synthesized by
`LoopElim` and were tagged with the loop-wide metadata `md`. The
per-invariant source range was lost earlier in the pipeline: Core loop
invariants are bare `(label, expr)` pairs and Core expressions are
`Unit`-annotated, so they carry no source range.
A front-end-only change does not help: the diagnostic location is driven
by the synthesized assert's metadata, not by anything attached to the
invariant expression. The fix therefore has to live in Strata.
## Solution
Thread each invariant's source range through the loop's existing
`MetaData` array and use it per-invariant in `LoopElim`. When a
per-invariant provenance is present, each invariant's generated
assert/assume is attributed to that invariant's own source location;
otherwise we fall back to the loop metadata `md`, so loops not
originating from Laurel (Core `.st`, C_Simp) are unchanged.
## Testing
`StrataTest/.../Fundamentals/T13_WhileLoopsError.lean` adds two
caret-annotated regression tests using the existing diagnostic harness
(`TestDiagnostics`, `matchesDiagnostic`), which checks the exact
start/end line and column of each diagnostic:
1. **`badInitialInvariant`** — a single `invariant i >= 0` that fails on
entry. The caret asserts the diagnostic lands on the invariant
expression, not the `while` loop.
2. **`secondInvariantFails`** — two invariants where the first holds on
entry but the second (`invariant j >= 0`) does not. The caret asserts
the diagnostic points specifically at the failing second invariant. This
is the case that distinguishes per-invariant attribution from loop-wide
attribution: before the fix the range would resolve to the loop, so the
carets would not match.
Verification:
- `lake build Strata` — compiles, no proof breakage.
- `lake build StrataTest` — all `#guard_msgs` tests pass, including the
new ones.
- The fallback to the loop `md` keeps existing Core `.st` and C_Simp
loop diagnostics unchanged.1 parent 8abb463 commit 24b8f04
5 files changed
Lines changed: 128 additions & 9 deletions
File tree
- StrataTest/Languages/Laurel/Examples/Fundamentals
- Strata
- DL/Imperative
- Languages/Laurel
- Transform
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
296 | 317 | | |
297 | 318 | | |
298 | 319 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
418 | 418 | | |
419 | 419 | | |
420 | 420 | | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
421 | 427 | | |
422 | 428 | | |
423 | | - | |
424 | | - | |
425 | | - | |
| 429 | + | |
426 | 430 | | |
427 | 431 | | |
428 | 432 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
502 | 502 | | |
503 | 503 | | |
504 | 504 | | |
505 | | - | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
506 | 514 | | |
507 | 515 | | |
508 | 516 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
145 | 163 | | |
146 | | - | |
| 164 | + | |
147 | 165 | | |
148 | | - | |
| 166 | + | |
149 | 167 | | |
150 | 168 | | |
151 | 169 | | |
152 | | - | |
| 170 | + | |
153 | 171 | | |
154 | | - | |
| 172 | + | |
155 | 173 | | |
156 | 174 | | |
157 | 175 | | |
| |||
183 | 201 | | |
184 | 202 | | |
185 | 203 | | |
186 | | - | |
| 204 | + | |
187 | 205 | | |
188 | 206 | | |
189 | 207 | | |
| |||
Lines changed: 68 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
0 commit comments