Commit e1db666
Two deltas on top of #395's ref-to-ref binding work, surfaced by the
audit at the time #395 landed:
1. **Self-assign `r = r` guard in StmtAssign.** Without it,
`is_reborrow_source` reports true for the ref-binder LHS=RHS case,
`pre_release` ends `r`'s borrow and removes the binding, then
post-rebind calls `ref_source_borrow` which finds `r` unbound and
returns None — net effect is `r` silently stripped from the
borrow-graph. Pathological in practice (`r = r` is dead code) but a
silent unsoundness rather than a no-op. The guard short-circuits
pre_release when the RHS's source binder is the LHS binder itself.
2. **Return-escape via indirection test fixture + test.** The
strongest proof that `record_ref_binding`'s delegation to
`ref_source_borrow` works is `return r2` where `r2 = r1 = &local`
— pre-fix this slipped past `returned_borrow`'s `ref_bindings`
lookup. The three fixtures landed in #395 (`let_aliases`,
`protects_owner`, `assign_aliases`) don't exercise the
return-escape code path, which is historically the most-leaked
surface for this class of bug. New fixture
`test/e2e/fixtures/ref_to_ref_return_escape.affine` pins it
(expects `BorrowOutlivesOwner`).
331 prior tests + 1 new = 332/332 green. No changes to lib/borrow.ml
behaviour for any code path other than the self-assign edge case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e73067d commit e1db666
3 files changed
Lines changed: 59 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1392 | 1392 | | |
1393 | 1393 | | |
1394 | 1394 | | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
| 1412 | + | |
1395 | 1413 | | |
1396 | 1414 | | |
1397 | 1415 | | |
1398 | | - | |
| 1416 | + | |
| 1417 | + | |
1399 | 1418 | | |
1400 | 1419 | | |
1401 | 1420 | | |
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4454 | 4454 | | |
4455 | 4455 | | |
4456 | 4456 | | |
| 4457 | + | |
| 4458 | + | |
| 4459 | + | |
| 4460 | + | |
| 4461 | + | |
| 4462 | + | |
| 4463 | + | |
| 4464 | + | |
| 4465 | + | |
| 4466 | + | |
| 4467 | + | |
| 4468 | + | |
| 4469 | + | |
| 4470 | + | |
| 4471 | + | |
| 4472 | + | |
| 4473 | + | |
4457 | 4474 | | |
4458 | 4475 | | |
4459 | 4476 | | |
| |||
4510 | 4527 | | |
4511 | 4528 | | |
4512 | 4529 | | |
| 4530 | + | |
| 4531 | + | |
4513 | 4532 | | |
4514 | 4533 | | |
4515 | 4534 | | |
| |||
0 commit comments