Commit 2b8aa0b
## Summary
Two deltas on top of #395's ref-to-ref binding work, surfaced by the
audit posted on #395 at the time it merged. **This PR was the original
parallel implementation; it has been rewritten as a thin follow-up now
that #395 covered the broader scope.**
### 1. Self-assign `r = r` guard
Without this guard, `is_reborrow_source` reports true for the ref-binder
LHS=RHS case → `pre_release` ends `r`'s borrow and removes the binding →
post-rebind calls `ref_source_borrow` which now 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 (new 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`.
## Tests
- 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.
## Coordination
- Rebased onto current main (post-#395 + post-#399). Force-pushed.
- GPG-signed.
- This was originally the parallel implementation of #395. After #395
merged via admin-merge during the deferred-items roundup, this PR was
rewritten to contain only the two deltas the audit flagged.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e73067d commit 2b8aa0b
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