FA-43876 / Borrow checking / Open access
A nonexhaustive guarded match omits the no-arm-taken ownership state · case 01
A nonexhaustive guarded match omits the no-arm-taken ownership state.
ROOT CAUSE
The static analyzer mishandles fallback state: a nonexhaustive guarded match omits the no-arm-taken ownership state.
VERIFIED REPAIR
Apply the specified transfer or inference rule at this site: if not d['exhaustive'] and not d['fallback_included']: errors.append('fallback-state').
Unsuccessful approach: The partial repair uses if not d['exhaustive'] and not d['fallback_included'] and not d['arms']: errors.append('fallback-state'), which still violates the stipulated analysis contract.
Case contract
Check borrow state across guarded matches. Guard failure restores prearm ownership; guard evaluation cannot move a noncopy scrutinee; arm-local loans end before another arm; guard mutation cannot change a discriminant supporting a projected borrow; arm move commits only after guard success; pattern tests are shared observations; exhaustive join includes every reachable arm; nonexhaustive matches retain fallback state; guard temporaries die on failed guard; a borrowed binding used by guard remains valid through guard expression. 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 d['guard_failed'] and set(d['pre_owned'])!=set(d['after_owned']): errors.append('failed-guard-restore')
if not set(d['guard_moves'])<=set(d['copyable']): errors.append('guard-move')
if bool(set(d['arm_local'])&set(d['next_arm_live'])): errors.append('arm-local-end')
if d['discriminant_mutated'] and d['projected_loan']: errors.append('discriminant-stability')
if not d['guard_succeeded'] and bool(d['committed_moves']): errors.append('move-commit-point')
if d['test_unique']: errors.append('pattern-test-capability')
if not set(d['arms'])<=set(d['joined']): errors.append('reachable-arm-join')
if False: errors.append('fallback-state')
if bool(set(d['guard_temps'])&set(d['failed_guard_live'])): errors.append('failed-guard-temporaries')
if d['binding_end']<d['guard_end']: errors.append('binding-guard-duration')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'guard_failed': False, 'pre_owned': [], 'after_owned': [], 'guard_moves': [], 'copyable': [], 'arm_local': [], 'next_arm_live': [], 'discriminant_mutated': False, 'projected_loan': False, 'guard_succeeded': True, 'committed_moves': [], 'test_unique': False, 'arms': [], 'joined': [], 'exhaustive': True, 'fallback_included': True, 'guard_temps': [], 'failed_guard_live': [], 'guard_end': 0, 'binding_end': 0}
check('well formed empty obligations',solve(base),[])
check('failed-guard-restore regression 0', solve(dict(base, **({'guard_failed':True,'pre_owned':['x']}))), ['failed-guard-restore'])
check('failed-guard-restore regression 1', solve(dict(base, **({'guard_failed':True,'pre_owned':[N],'after_owned':[]}))), ['failed-guard-restore'])
check('guard-move regression 0', solve(dict(base, **({'guard_moves':['a','b'],'copyable':['a']}))), ['guard-move'])
check('guard-move regression 1', solve(dict(base, **({'guard_moves':[N,N+1],'copyable':[N]}))), ['guard-move'])
check('arm-local-end regression 0', solve(dict(base, **({'arm_local':['r'],'next_arm_live':['r']}))), ['arm-local-end'])
check('arm-local-end regression 1', solve(dict(base, **({'arm_local':[N],'next_arm_live':[N]}))), ['arm-local-end'])
check('discriminant-stability regression 0', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True}))), ['discriminant-stability'])
check('discriminant-stability regression 1', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True,'guard_end':N,'binding_end':N}))), ['discriminant-stability'])
check('move-commit-point regression 0', solve(dict(base, **({'guard_succeeded':False,'committed_moves':['x']}))), ['move-commit-point'])
check('move-commit-point regression 1', solve(dict(base, **({'guard_succeeded':False,'committed_moves':[N]}))), ['move-commit-point'])
check('pattern-test-capability regression 0', solve(dict(base, **({'test_unique':True}))), ['pattern-test-capability'])
check('pattern-test-capability regression 1', solve(dict(base, **({'test_unique':True,'guard_end':N,'binding_end':N}))), ['pattern-test-capability'])
check('reachable-arm-join regression 0', solve(dict(base, **({'arms':['a','b'],'joined':['a']}))), ['reachable-arm-join'])
check('reachable-arm-join regression 1', solve(dict(base, **({'arms':list(range(N+1)),'joined':[0]}))), ['reachable-arm-join'])
check('fallback-state regression 0', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':['a'],'joined':['a']}))), ['fallback-state'])
check('fallback-state regression 1', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':[N],'joined':[N]}))), ['fallback-state'])
check('failed-guard-temporaries regression 0', solve(dict(base, **({'guard_temps':['a','b'],'failed_guard_live':['b']}))), ['failed-guard-temporaries'])
check('failed-guard-temporaries regression 1', solve(dict(base, **({'guard_temps':[N,N+1],'failed_guard_live':[N]}))), ['failed-guard-temporaries'])
check('binding-guard-duration regression 0', solve(dict(base, **({'guard_end':N+1,'binding_end':N}))), ['binding-guard-duration'])
check('binding-guard-duration regression 1', solve(dict(base, **({'guard_end':N+2,'binding_end':N+1}))), ['binding-guard-duration'])
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 |
| failed-guard-restore regression 0 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| failed-guard-restore regression 1 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| guard-move regression 0 | ['guard-move'] | ['guard-move'] | Passed |
| guard-move regression 1 | ['guard-move'] | ['guard-move'] | Passed |
| arm-local-end regression 0 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| arm-local-end regression 1 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| discriminant-stability regression 0 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| discriminant-stability regression 1 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| move-commit-point regression 0 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| move-commit-point regression 1 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| pattern-test-capability regression 0 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| pattern-test-capability regression 1 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| reachable-arm-join regression 0 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| reachable-arm-join regression 1 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| fallback-state regression 0 | [] | ['fallback-state'] | Failed |
| fallback-state regression 1 | [] | ['fallback-state'] | Failed |
| failed-guard-temporaries regression 0 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| failed-guard-temporaries regression 1 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| binding-guard-duration regression 0 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
| binding-guard-duration regression 1 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
SHA-256 / d8686923bf72a13a549e9b1955ad65923d92e89ec75658aff55ecd496fd057b0
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if d['guard_failed'] and set(d['pre_owned'])!=set(d['after_owned']): errors.append('failed-guard-restore')
if not set(d['guard_moves'])<=set(d['copyable']): errors.append('guard-move')
if bool(set(d['arm_local'])&set(d['next_arm_live'])): errors.append('arm-local-end')
if d['discriminant_mutated'] and d['projected_loan']: errors.append('discriminant-stability')
if not d['guard_succeeded'] and bool(d['committed_moves']): errors.append('move-commit-point')
if d['test_unique']: errors.append('pattern-test-capability')
if not set(d['arms'])<=set(d['joined']): errors.append('reachable-arm-join')
if not d['exhaustive'] and not d['fallback_included'] and not d['arms']: errors.append('fallback-state')
if bool(set(d['guard_temps'])&set(d['failed_guard_live'])): errors.append('failed-guard-temporaries')
if d['binding_end']<d['guard_end']: errors.append('binding-guard-duration')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'guard_failed': False, 'pre_owned': [], 'after_owned': [], 'guard_moves': [], 'copyable': [], 'arm_local': [], 'next_arm_live': [], 'discriminant_mutated': False, 'projected_loan': False, 'guard_succeeded': True, 'committed_moves': [], 'test_unique': False, 'arms': [], 'joined': [], 'exhaustive': True, 'fallback_included': True, 'guard_temps': [], 'failed_guard_live': [], 'guard_end': 0, 'binding_end': 0}
check('well formed empty obligations',solve(base),[])
check('failed-guard-restore regression 0', solve(dict(base, **({'guard_failed':True,'pre_owned':['x']}))), ['failed-guard-restore'])
check('failed-guard-restore regression 1', solve(dict(base, **({'guard_failed':True,'pre_owned':[N],'after_owned':[]}))), ['failed-guard-restore'])
check('guard-move regression 0', solve(dict(base, **({'guard_moves':['a','b'],'copyable':['a']}))), ['guard-move'])
check('guard-move regression 1', solve(dict(base, **({'guard_moves':[N,N+1],'copyable':[N]}))), ['guard-move'])
check('arm-local-end regression 0', solve(dict(base, **({'arm_local':['r'],'next_arm_live':['r']}))), ['arm-local-end'])
check('arm-local-end regression 1', solve(dict(base, **({'arm_local':[N],'next_arm_live':[N]}))), ['arm-local-end'])
check('discriminant-stability regression 0', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True}))), ['discriminant-stability'])
check('discriminant-stability regression 1', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True,'guard_end':N,'binding_end':N}))), ['discriminant-stability'])
check('move-commit-point regression 0', solve(dict(base, **({'guard_succeeded':False,'committed_moves':['x']}))), ['move-commit-point'])
check('move-commit-point regression 1', solve(dict(base, **({'guard_succeeded':False,'committed_moves':[N]}))), ['move-commit-point'])
check('pattern-test-capability regression 0', solve(dict(base, **({'test_unique':True}))), ['pattern-test-capability'])
check('pattern-test-capability regression 1', solve(dict(base, **({'test_unique':True,'guard_end':N,'binding_end':N}))), ['pattern-test-capability'])
check('reachable-arm-join regression 0', solve(dict(base, **({'arms':['a','b'],'joined':['a']}))), ['reachable-arm-join'])
check('reachable-arm-join regression 1', solve(dict(base, **({'arms':list(range(N+1)),'joined':[0]}))), ['reachable-arm-join'])
check('fallback-state regression 0', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':['a'],'joined':['a']}))), ['fallback-state'])
check('fallback-state regression 1', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':[N],'joined':[N]}))), ['fallback-state'])
check('failed-guard-temporaries regression 0', solve(dict(base, **({'guard_temps':['a','b'],'failed_guard_live':['b']}))), ['failed-guard-temporaries'])
check('failed-guard-temporaries regression 1', solve(dict(base, **({'guard_temps':[N,N+1],'failed_guard_live':[N]}))), ['failed-guard-temporaries'])
check('binding-guard-duration regression 0', solve(dict(base, **({'guard_end':N+1,'binding_end':N}))), ['binding-guard-duration'])
check('binding-guard-duration regression 1', solve(dict(base, **({'guard_end':N+2,'binding_end':N+1}))), ['binding-guard-duration'])
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 |
| failed-guard-restore regression 0 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| failed-guard-restore regression 1 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| guard-move regression 0 | ['guard-move'] | ['guard-move'] | Passed |
| guard-move regression 1 | ['guard-move'] | ['guard-move'] | Passed |
| arm-local-end regression 0 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| arm-local-end regression 1 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| discriminant-stability regression 0 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| discriminant-stability regression 1 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| move-commit-point regression 0 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| move-commit-point regression 1 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| pattern-test-capability regression 0 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| pattern-test-capability regression 1 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| reachable-arm-join regression 0 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| reachable-arm-join regression 1 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| fallback-state regression 0 | [] | ['fallback-state'] | Failed |
| fallback-state regression 1 | [] | ['fallback-state'] | Failed |
| failed-guard-temporaries regression 0 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| failed-guard-temporaries regression 1 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| binding-guard-duration regression 0 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
| binding-guard-duration regression 1 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
SHA-256 / a14a341920709d9a815f8474147e285c693b01702b95cc7701175223ea71b708
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if d['guard_failed'] and set(d['pre_owned'])!=set(d['after_owned']): errors.append('failed-guard-restore')
if not set(d['guard_moves'])<=set(d['copyable']): errors.append('guard-move')
if bool(set(d['arm_local'])&set(d['next_arm_live'])): errors.append('arm-local-end')
if d['discriminant_mutated'] and d['projected_loan']: errors.append('discriminant-stability')
if not d['guard_succeeded'] and bool(d['committed_moves']): errors.append('move-commit-point')
if d['test_unique']: errors.append('pattern-test-capability')
if not set(d['arms'])<=set(d['joined']): errors.append('reachable-arm-join')
if not d['exhaustive'] and not d['fallback_included']: errors.append('fallback-state')
if bool(set(d['guard_temps'])&set(d['failed_guard_live'])): errors.append('failed-guard-temporaries')
if d['binding_end']<d['guard_end']: errors.append('binding-guard-duration')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'guard_failed': False, 'pre_owned': [], 'after_owned': [], 'guard_moves': [], 'copyable': [], 'arm_local': [], 'next_arm_live': [], 'discriminant_mutated': False, 'projected_loan': False, 'guard_succeeded': True, 'committed_moves': [], 'test_unique': False, 'arms': [], 'joined': [], 'exhaustive': True, 'fallback_included': True, 'guard_temps': [], 'failed_guard_live': [], 'guard_end': 0, 'binding_end': 0}
check('well formed empty obligations',solve(base),[])
check('failed-guard-restore regression 0', solve(dict(base, **({'guard_failed':True,'pre_owned':['x']}))), ['failed-guard-restore'])
check('failed-guard-restore regression 1', solve(dict(base, **({'guard_failed':True,'pre_owned':[N],'after_owned':[]}))), ['failed-guard-restore'])
check('guard-move regression 0', solve(dict(base, **({'guard_moves':['a','b'],'copyable':['a']}))), ['guard-move'])
check('guard-move regression 1', solve(dict(base, **({'guard_moves':[N,N+1],'copyable':[N]}))), ['guard-move'])
check('arm-local-end regression 0', solve(dict(base, **({'arm_local':['r'],'next_arm_live':['r']}))), ['arm-local-end'])
check('arm-local-end regression 1', solve(dict(base, **({'arm_local':[N],'next_arm_live':[N]}))), ['arm-local-end'])
check('discriminant-stability regression 0', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True}))), ['discriminant-stability'])
check('discriminant-stability regression 1', solve(dict(base, **({'discriminant_mutated':True,'projected_loan':True,'guard_end':N,'binding_end':N}))), ['discriminant-stability'])
check('move-commit-point regression 0', solve(dict(base, **({'guard_succeeded':False,'committed_moves':['x']}))), ['move-commit-point'])
check('move-commit-point regression 1', solve(dict(base, **({'guard_succeeded':False,'committed_moves':[N]}))), ['move-commit-point'])
check('pattern-test-capability regression 0', solve(dict(base, **({'test_unique':True}))), ['pattern-test-capability'])
check('pattern-test-capability regression 1', solve(dict(base, **({'test_unique':True,'guard_end':N,'binding_end':N}))), ['pattern-test-capability'])
check('reachable-arm-join regression 0', solve(dict(base, **({'arms':['a','b'],'joined':['a']}))), ['reachable-arm-join'])
check('reachable-arm-join regression 1', solve(dict(base, **({'arms':list(range(N+1)),'joined':[0]}))), ['reachable-arm-join'])
check('fallback-state regression 0', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':['a'],'joined':['a']}))), ['fallback-state'])
check('fallback-state regression 1', solve(dict(base, **({'exhaustive':False,'fallback_included':False,'arms':[N],'joined':[N]}))), ['fallback-state'])
check('failed-guard-temporaries regression 0', solve(dict(base, **({'guard_temps':['a','b'],'failed_guard_live':['b']}))), ['failed-guard-temporaries'])
check('failed-guard-temporaries regression 1', solve(dict(base, **({'guard_temps':[N,N+1],'failed_guard_live':[N]}))), ['failed-guard-temporaries'])
check('binding-guard-duration regression 0', solve(dict(base, **({'guard_end':N+1,'binding_end':N}))), ['binding-guard-duration'])
check('binding-guard-duration regression 1', solve(dict(base, **({'guard_end':N+2,'binding_end':N+1}))), ['binding-guard-duration'])
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 |
| failed-guard-restore regression 0 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| failed-guard-restore regression 1 | ['failed-guard-restore'] | ['failed-guard-restore'] | Passed |
| guard-move regression 0 | ['guard-move'] | ['guard-move'] | Passed |
| guard-move regression 1 | ['guard-move'] | ['guard-move'] | Passed |
| arm-local-end regression 0 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| arm-local-end regression 1 | ['arm-local-end'] | ['arm-local-end'] | Passed |
| discriminant-stability regression 0 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| discriminant-stability regression 1 | ['discriminant-stability'] | ['discriminant-stability'] | Passed |
| move-commit-point regression 0 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| move-commit-point regression 1 | ['move-commit-point'] | ['move-commit-point'] | Passed |
| pattern-test-capability regression 0 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| pattern-test-capability regression 1 | ['pattern-test-capability'] | ['pattern-test-capability'] | Passed |
| reachable-arm-join regression 0 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| reachable-arm-join regression 1 | ['reachable-arm-join'] | ['reachable-arm-join'] | Passed |
| fallback-state regression 0 | ['fallback-state'] | ['fallback-state'] | Passed |
| fallback-state regression 1 | ['fallback-state'] | ['fallback-state'] | Passed |
| failed-guard-temporaries regression 0 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| failed-guard-temporaries regression 1 | ['failed-guard-temporaries'] | ['failed-guard-temporaries'] | Passed |
| binding-guard-duration regression 0 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
| binding-guard-duration regression 1 | ['binding-guard-duration'] | ['binding-guard-duration'] | Passed |
SHA-256 / c944e527f1b55447c63d66e45f0a56b71cf4fcf18c04433c7bd7b7848be6e516
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:06.521501+00:00.
Case digest / 4ed5ee43b5dac592e3c0d12946ef46ed4a3a52e09bfd3d0ff61ecde191397a02