FA-43451 / Borrow checking / Open access
Moving one actual is hidden by another correctly summarized move · case 01
Moving one actual is hidden by another correctly summarized move.
ROOT CAUSE
The static analyzer mishandles move summary: moving one actual is hidden by another correctly summarized move.
VERIFIED REPAIR
Apply the specified transfer or inference rule at this site: if not set(d['body_moves'])<=set(d['moves']): errors.append('move-summary').
Unsuccessful approach: The partial repair uses if set(d['body_moves']).isdisjoint(d['moves']) and bool(d['body_moves']): errors.append('move-summary'), which still violates the stipulated analysis contract.
Case contract
Validate a callee borrow effect summary against observed static body effects. Reads, writes, moves and escapes are separate effect sets; writes require unique actuals; a returned alias must list every possible argument origin; unknown callees conservatively retain actual references; a noescape assertion excludes body escapes; argument-to-formal mapping must be a bijection over expected formals; normal and unwind exits both release declared call-local loans. Input is a fully explicit descriptor of the stated toy IR. Return rule identifiers in declaration order; absent optional obligations use the provided neutral defaults. No rule is an assertion about a production language.
Why this case matters
A finite offline static-analysis model of ownership and borrowing; it does not execute the analyzed program.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if not set(d['body_reads'])<=set(d['reads']): errors.append('read-summary')
if not set(d['body_writes'])<=set(d['writes']): errors.append('write-summary')
if False: errors.append('move-summary')
if not set(d['body_escapes'])<=set(d['escapes']): errors.append('escape-summary')
if not set(d['writes'])<=set(d['unique_actuals']): errors.append('unique-actual')
if not set(d['body_return_origins'])<=set(d['return_origins']): errors.append('return-origin-summary')
if d['unknown'] and not set(d['actual_refs'])<=set(d['retained']): errors.append('unknown-retention')
if d['noescape'] and bool(d['body_escapes']): errors.append('noescape-proof')
if len(d['mapping'])!=len(set(d['mapping'])) or set(d['mapping'])!=set(d['formals']): errors.append('formal-map-bijection')
if not set(d['call_loans'])<=set(d['released_normal']) or not set(d['call_loans'])<=set(d['released_unwind']): errors.append('unwind-release')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'body_reads': [], 'reads': [], 'body_writes': [], 'writes': [], 'body_moves': [], 'moves': [], 'body_escapes': [], 'escapes': [], 'unique_actuals': [], 'return_origins': [], 'body_return_origins': [], 'unknown': False, 'actual_refs': [], 'retained': [], 'noescape': False, 'mapping': [], 'formals': [], 'call_loans': [], 'released_normal': [], 'released_unwind': []}
check('well formed empty obligations',solve(base),[])
check('read-summary regression 0', solve(dict(base, **({'body_reads':['a','b'],'reads':['a']}))), ['read-summary'])
check('read-summary regression 1', solve(dict(base, **({'body_reads':[N,N+1],'reads':[N]}))), ['read-summary'])
check('write-summary regression 0', solve(dict(base, **({'body_writes':['a','b'],'writes':['a'],'unique_actuals':['a']}))), ['write-summary'])
check('write-summary regression 1', solve(dict(base, **({'body_writes':[N,N+1],'writes':[N],'unique_actuals':[N]}))), ['write-summary'])
check('move-summary regression 0', solve(dict(base, **({'body_moves':['a','b'],'moves':['a']}))), ['move-summary'])
check('move-summary regression 1', solve(dict(base, **({'body_moves':[N,N+1],'moves':[N]}))), ['move-summary'])
check('escape-summary regression 0', solve(dict(base, **({'body_escapes':['a','b'],'escapes':['a']}))), ['escape-summary'])
check('escape-summary regression 1', solve(dict(base, **({'body_escapes':[N,N+1],'escapes':[N]}))), ['escape-summary'])
check('unique-actual regression 0', solve(dict(base, **({'writes':['a','b'],'unique_actuals':['a']}))), ['unique-actual'])
check('unique-actual regression 1', solve(dict(base, **({'writes':[N],'unique_actuals':[N+1]}))), ['unique-actual'])
check('return-origin-summary regression 0', solve(dict(base, **({'body_return_origins':['a','b'],'return_origins':['a']}))), ['return-origin-summary'])
check('return-origin-summary regression 1', solve(dict(base, **({'body_return_origins':[N,N+1],'return_origins':[N]}))), ['return-origin-summary'])
check('unknown-retention regression 0', solve(dict(base, **({'unknown':True,'actual_refs':['a','b'],'retained':['a']}))), ['unknown-retention'])
check('unknown-retention regression 1', solve(dict(base, **({'unknown':True,'actual_refs':[N,N+1],'retained':[N]}))), ['unknown-retention'])
check('noescape-proof regression 0', solve(dict(base, **({'noescape':True,'body_escapes':['r'],'escapes':['r']}))), ['noescape-proof'])
check('noescape-proof regression 1', solve(dict(base, **({'noescape':True,'body_escapes':[N],'escapes':[N]}))), ['noescape-proof'])
check('formal-map-bijection regression 0', solve(dict(base, **({'mapping':['a','a'],'formals':['a']}))), ['formal-map-bijection'])
check('formal-map-bijection regression 1', solve(dict(base, **({'mapping':[N,N],'formals':[N]}))), ['formal-map-bijection'])
check('unwind-release regression 0', solve(dict(base, **({'call_loans':['r'],'released_normal':['r']}))), ['unwind-release'])
check('unwind-release regression 1', solve(dict(base, **({'call_loans':[N],'released_normal':[N]}))), ['unwind-release'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| well formed empty obligations | [] | [] | Passed |
| read-summary regression 0 | ['read-summary'] | ['read-summary'] | Passed |
| read-summary regression 1 | ['read-summary'] | ['read-summary'] | Passed |
| write-summary regression 0 | ['write-summary'] | ['write-summary'] | Passed |
| write-summary regression 1 | ['write-summary'] | ['write-summary'] | Passed |
| move-summary regression 0 | [] | ['move-summary'] | Failed |
| move-summary regression 1 | [] | ['move-summary'] | Failed |
| escape-summary regression 0 | ['escape-summary'] | ['escape-summary'] | Passed |
| escape-summary regression 1 | ['escape-summary'] | ['escape-summary'] | Passed |
| unique-actual regression 0 | ['unique-actual'] | ['unique-actual'] | Passed |
| unique-actual regression 1 | ['unique-actual'] | ['unique-actual'] | Passed |
| return-origin-summary regression 0 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| return-origin-summary regression 1 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| unknown-retention regression 0 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| unknown-retention regression 1 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| noescape-proof regression 0 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| noescape-proof regression 1 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| formal-map-bijection regression 0 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| formal-map-bijection regression 1 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| unwind-release regression 0 | ['unwind-release'] | ['unwind-release'] | Passed |
| unwind-release regression 1 | ['unwind-release'] | ['unwind-release'] | Passed |
SHA-256 / 7468bd93d2c16756b3275a76256631ede902fd4f1d611a39e49c98b922fda631
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if not set(d['body_reads'])<=set(d['reads']): errors.append('read-summary')
if not set(d['body_writes'])<=set(d['writes']): errors.append('write-summary')
if set(d['body_moves']).isdisjoint(d['moves']) and bool(d['body_moves']): errors.append('move-summary')
if not set(d['body_escapes'])<=set(d['escapes']): errors.append('escape-summary')
if not set(d['writes'])<=set(d['unique_actuals']): errors.append('unique-actual')
if not set(d['body_return_origins'])<=set(d['return_origins']): errors.append('return-origin-summary')
if d['unknown'] and not set(d['actual_refs'])<=set(d['retained']): errors.append('unknown-retention')
if d['noescape'] and bool(d['body_escapes']): errors.append('noescape-proof')
if len(d['mapping'])!=len(set(d['mapping'])) or set(d['mapping'])!=set(d['formals']): errors.append('formal-map-bijection')
if not set(d['call_loans'])<=set(d['released_normal']) or not set(d['call_loans'])<=set(d['released_unwind']): errors.append('unwind-release')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'body_reads': [], 'reads': [], 'body_writes': [], 'writes': [], 'body_moves': [], 'moves': [], 'body_escapes': [], 'escapes': [], 'unique_actuals': [], 'return_origins': [], 'body_return_origins': [], 'unknown': False, 'actual_refs': [], 'retained': [], 'noescape': False, 'mapping': [], 'formals': [], 'call_loans': [], 'released_normal': [], 'released_unwind': []}
check('well formed empty obligations',solve(base),[])
check('read-summary regression 0', solve(dict(base, **({'body_reads':['a','b'],'reads':['a']}))), ['read-summary'])
check('read-summary regression 1', solve(dict(base, **({'body_reads':[N,N+1],'reads':[N]}))), ['read-summary'])
check('write-summary regression 0', solve(dict(base, **({'body_writes':['a','b'],'writes':['a'],'unique_actuals':['a']}))), ['write-summary'])
check('write-summary regression 1', solve(dict(base, **({'body_writes':[N,N+1],'writes':[N],'unique_actuals':[N]}))), ['write-summary'])
check('move-summary regression 0', solve(dict(base, **({'body_moves':['a','b'],'moves':['a']}))), ['move-summary'])
check('move-summary regression 1', solve(dict(base, **({'body_moves':[N,N+1],'moves':[N]}))), ['move-summary'])
check('escape-summary regression 0', solve(dict(base, **({'body_escapes':['a','b'],'escapes':['a']}))), ['escape-summary'])
check('escape-summary regression 1', solve(dict(base, **({'body_escapes':[N,N+1],'escapes':[N]}))), ['escape-summary'])
check('unique-actual regression 0', solve(dict(base, **({'writes':['a','b'],'unique_actuals':['a']}))), ['unique-actual'])
check('unique-actual regression 1', solve(dict(base, **({'writes':[N],'unique_actuals':[N+1]}))), ['unique-actual'])
check('return-origin-summary regression 0', solve(dict(base, **({'body_return_origins':['a','b'],'return_origins':['a']}))), ['return-origin-summary'])
check('return-origin-summary regression 1', solve(dict(base, **({'body_return_origins':[N,N+1],'return_origins':[N]}))), ['return-origin-summary'])
check('unknown-retention regression 0', solve(dict(base, **({'unknown':True,'actual_refs':['a','b'],'retained':['a']}))), ['unknown-retention'])
check('unknown-retention regression 1', solve(dict(base, **({'unknown':True,'actual_refs':[N,N+1],'retained':[N]}))), ['unknown-retention'])
check('noescape-proof regression 0', solve(dict(base, **({'noescape':True,'body_escapes':['r'],'escapes':['r']}))), ['noescape-proof'])
check('noescape-proof regression 1', solve(dict(base, **({'noescape':True,'body_escapes':[N],'escapes':[N]}))), ['noescape-proof'])
check('formal-map-bijection regression 0', solve(dict(base, **({'mapping':['a','a'],'formals':['a']}))), ['formal-map-bijection'])
check('formal-map-bijection regression 1', solve(dict(base, **({'mapping':[N,N],'formals':[N]}))), ['formal-map-bijection'])
check('unwind-release regression 0', solve(dict(base, **({'call_loans':['r'],'released_normal':['r']}))), ['unwind-release'])
check('unwind-release regression 1', solve(dict(base, **({'call_loans':[N],'released_normal':[N]}))), ['unwind-release'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| well formed empty obligations | [] | [] | Passed |
| read-summary regression 0 | ['read-summary'] | ['read-summary'] | Passed |
| read-summary regression 1 | ['read-summary'] | ['read-summary'] | Passed |
| write-summary regression 0 | ['write-summary'] | ['write-summary'] | Passed |
| write-summary regression 1 | ['write-summary'] | ['write-summary'] | Passed |
| move-summary regression 0 | [] | ['move-summary'] | Failed |
| move-summary regression 1 | [] | ['move-summary'] | Failed |
| escape-summary regression 0 | ['escape-summary'] | ['escape-summary'] | Passed |
| escape-summary regression 1 | ['escape-summary'] | ['escape-summary'] | Passed |
| unique-actual regression 0 | ['unique-actual'] | ['unique-actual'] | Passed |
| unique-actual regression 1 | ['unique-actual'] | ['unique-actual'] | Passed |
| return-origin-summary regression 0 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| return-origin-summary regression 1 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| unknown-retention regression 0 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| unknown-retention regression 1 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| noescape-proof regression 0 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| noescape-proof regression 1 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| formal-map-bijection regression 0 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| formal-map-bijection regression 1 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| unwind-release regression 0 | ['unwind-release'] | ['unwind-release'] | Passed |
| unwind-release regression 1 | ['unwind-release'] | ['unwind-release'] | Passed |
SHA-256 / eec2d95894f34c8141114319e647817f5ef6b7b99e81b7dbb446ac79bcb8bd52
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if not set(d['body_reads'])<=set(d['reads']): errors.append('read-summary')
if not set(d['body_writes'])<=set(d['writes']): errors.append('write-summary')
if not set(d['body_moves'])<=set(d['moves']): errors.append('move-summary')
if not set(d['body_escapes'])<=set(d['escapes']): errors.append('escape-summary')
if not set(d['writes'])<=set(d['unique_actuals']): errors.append('unique-actual')
if not set(d['body_return_origins'])<=set(d['return_origins']): errors.append('return-origin-summary')
if d['unknown'] and not set(d['actual_refs'])<=set(d['retained']): errors.append('unknown-retention')
if d['noescape'] and bool(d['body_escapes']): errors.append('noescape-proof')
if len(d['mapping'])!=len(set(d['mapping'])) or set(d['mapping'])!=set(d['formals']): errors.append('formal-map-bijection')
if not set(d['call_loans'])<=set(d['released_normal']) or not set(d['call_loans'])<=set(d['released_unwind']): errors.append('unwind-release')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'body_reads': [], 'reads': [], 'body_writes': [], 'writes': [], 'body_moves': [], 'moves': [], 'body_escapes': [], 'escapes': [], 'unique_actuals': [], 'return_origins': [], 'body_return_origins': [], 'unknown': False, 'actual_refs': [], 'retained': [], 'noescape': False, 'mapping': [], 'formals': [], 'call_loans': [], 'released_normal': [], 'released_unwind': []}
check('well formed empty obligations',solve(base),[])
check('read-summary regression 0', solve(dict(base, **({'body_reads':['a','b'],'reads':['a']}))), ['read-summary'])
check('read-summary regression 1', solve(dict(base, **({'body_reads':[N,N+1],'reads':[N]}))), ['read-summary'])
check('write-summary regression 0', solve(dict(base, **({'body_writes':['a','b'],'writes':['a'],'unique_actuals':['a']}))), ['write-summary'])
check('write-summary regression 1', solve(dict(base, **({'body_writes':[N,N+1],'writes':[N],'unique_actuals':[N]}))), ['write-summary'])
check('move-summary regression 0', solve(dict(base, **({'body_moves':['a','b'],'moves':['a']}))), ['move-summary'])
check('move-summary regression 1', solve(dict(base, **({'body_moves':[N,N+1],'moves':[N]}))), ['move-summary'])
check('escape-summary regression 0', solve(dict(base, **({'body_escapes':['a','b'],'escapes':['a']}))), ['escape-summary'])
check('escape-summary regression 1', solve(dict(base, **({'body_escapes':[N,N+1],'escapes':[N]}))), ['escape-summary'])
check('unique-actual regression 0', solve(dict(base, **({'writes':['a','b'],'unique_actuals':['a']}))), ['unique-actual'])
check('unique-actual regression 1', solve(dict(base, **({'writes':[N],'unique_actuals':[N+1]}))), ['unique-actual'])
check('return-origin-summary regression 0', solve(dict(base, **({'body_return_origins':['a','b'],'return_origins':['a']}))), ['return-origin-summary'])
check('return-origin-summary regression 1', solve(dict(base, **({'body_return_origins':[N,N+1],'return_origins':[N]}))), ['return-origin-summary'])
check('unknown-retention regression 0', solve(dict(base, **({'unknown':True,'actual_refs':['a','b'],'retained':['a']}))), ['unknown-retention'])
check('unknown-retention regression 1', solve(dict(base, **({'unknown':True,'actual_refs':[N,N+1],'retained':[N]}))), ['unknown-retention'])
check('noescape-proof regression 0', solve(dict(base, **({'noescape':True,'body_escapes':['r'],'escapes':['r']}))), ['noescape-proof'])
check('noescape-proof regression 1', solve(dict(base, **({'noescape':True,'body_escapes':[N],'escapes':[N]}))), ['noescape-proof'])
check('formal-map-bijection regression 0', solve(dict(base, **({'mapping':['a','a'],'formals':['a']}))), ['formal-map-bijection'])
check('formal-map-bijection regression 1', solve(dict(base, **({'mapping':[N,N],'formals':[N]}))), ['formal-map-bijection'])
check('unwind-release regression 0', solve(dict(base, **({'call_loans':['r'],'released_normal':['r']}))), ['unwind-release'])
check('unwind-release regression 1', solve(dict(base, **({'call_loans':[N],'released_normal':[N]}))), ['unwind-release'])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| well formed empty obligations | [] | [] | Passed |
| read-summary regression 0 | ['read-summary'] | ['read-summary'] | Passed |
| read-summary regression 1 | ['read-summary'] | ['read-summary'] | Passed |
| write-summary regression 0 | ['write-summary'] | ['write-summary'] | Passed |
| write-summary regression 1 | ['write-summary'] | ['write-summary'] | Passed |
| move-summary regression 0 | ['move-summary'] | ['move-summary'] | Passed |
| move-summary regression 1 | ['move-summary'] | ['move-summary'] | Passed |
| escape-summary regression 0 | ['escape-summary'] | ['escape-summary'] | Passed |
| escape-summary regression 1 | ['escape-summary'] | ['escape-summary'] | Passed |
| unique-actual regression 0 | ['unique-actual'] | ['unique-actual'] | Passed |
| unique-actual regression 1 | ['unique-actual'] | ['unique-actual'] | Passed |
| return-origin-summary regression 0 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| return-origin-summary regression 1 | ['return-origin-summary'] | ['return-origin-summary'] | Passed |
| unknown-retention regression 0 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| unknown-retention regression 1 | ['unknown-retention'] | ['unknown-retention'] | Passed |
| noescape-proof regression 0 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| noescape-proof regression 1 | ['noescape-proof'] | ['noescape-proof'] | Passed |
| formal-map-bijection regression 0 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| formal-map-bijection regression 1 | ['formal-map-bijection'] | ['formal-map-bijection'] | Passed |
| unwind-release regression 0 | ['unwind-release'] | ['unwind-release'] | Passed |
| unwind-release regression 1 | ['unwind-release'] | ['unwind-release'] | Passed |
SHA-256 / da0cc2f158e5b10bef05994fa32e96fbab0e8ac8bd5fcc5a8a1db0dda9816a87
Verification & scope
The explicitly stated toy language is the complete scope; this is not a production compiler or a claim about Rust semantics. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:44:02.035073+00:00.
Case digest / 83df4a2b06ab908f83a11b5ff23bbc5bc6605fabaeb47665ea6f0089a9b62c3d