FA-43091 / Borrow checking / Open access
A repeated lifetime binder silently shadows its earlier declaration · case 01
A repeated lifetime binder silently shadows its earlier declaration.
ROOT CAUSE
The static analyzer mishandles duplicate param: a repeated lifetime binder silently shadows its earlier declaration.
VERIFIED REPAIR
Apply the specified transfer or inference rule at this site: if len(d['params'])!=len(set(d['params'])): errors.append('duplicate-param').
Unsuccessful approach: The partial repair uses if len(d['params'])>2 and len(d['params'])!=len(set(d['params'])): errors.append('duplicate-param'), which still violates the stipulated analysis contract.
Case contract
Check borrowed function signature well-formedness: lifetime parameters unique; all occurrences declared or static; output elision needs exactly one input lifetime; receiver elision uses receiver lifetime; every output source is an input; by-reference return cannot originate in a local; returned mutable borrow requires mutable input; output extent must fit source extent; bound lifetime cannot escape binder depth; unused lifetime parameters rejected in this toy language. 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 False: errors.append('duplicate-param')
if any(x not in d['params'] and x!='static' for x in d['uses']): errors.append('undeclared-occurrence')
if d['elided'] and d['receiver'] is None and len(set(d['inputs']))!=1: errors.append('ambiguous-elision')
if d['elided'] and d['receiver'] is not None and d['output']!=d['receiver']: errors.append('receiver-elision')
if any(x not in d['inputs'] for x in d['sources']): errors.append('output-source')
if bool(set(d['sources'])&set(d['locals'])): errors.append('local-return')
if d['mutable_out'] and not set(d['sources'])<=set(d['mutable_inputs']): errors.append('mutable-source')
if not set(d['required'])<=set(d['available']): errors.append('return-extent')
if d['bound_depth']>d['output_depth']: errors.append('binder-escape')
if not set(d['params'])<=set(d['used_params']): errors.append('unused-param')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'params': ['a'], 'uses': ['a'], 'inputs': ['a'], 'output': None, 'receiver': None, 'elided': False, 'sources': [], 'locals': [], 'mutable_out': False, 'mutable_inputs': [], 'required': [], 'available': [], 'bound_depth': 0, 'output_depth': 0, 'used_params': ['a']}
check('well formed empty obligations',solve(base),[])
check('duplicate-param regression 0', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('duplicate-param regression 1', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('undeclared-occurrence regression 0', solve(dict(base, **({'uses':['a','b'+str(N)]}))), ['undeclared-occurrence'])
check('undeclared-occurrence regression 1', solve(dict(base, **({'uses':['a','z']}))), ['undeclared-occurrence'])
check('ambiguous-elision regression 0', solve(dict(base, **({'elided':True,'inputs':['a','b']}))), ['ambiguous-elision'])
check('ambiguous-elision regression 1', solve(dict(base, **({'elided':True,'inputs':list(range(N+2))}))), ['ambiguous-elision'])
check('receiver-elision regression 0', solve(dict(base, **({'elided':True,'receiver':'a','output':'b'}))), ['receiver-elision'])
check('receiver-elision regression 1', solve(dict(base, **({'elided':True,'receiver':'a','output':'static'}))), ['receiver-elision'])
check('output-source regression 0', solve(dict(base, **({'sources':['a','b']}))), ['output-source'])
check('output-source regression 1', solve(dict(base, **({'sources':['a','z'+str(N)]}))), ['output-source'])
check('local-return regression 0', solve(dict(base, **({'inputs':['a','b'],'sources':['a','b'],'locals':['b']}))), ['local-return'])
check('local-return regression 1', solve(dict(base, **({'inputs':['a','c'],'sources':['a','c'],'locals':['c']}))), ['local-return'])
check('mutable-source regression 0', solve(dict(base, **({'mutable_out':True,'inputs':['a','b'],'sources':['a','b'],'mutable_inputs':['a']}))), ['mutable-source'])
check('mutable-source regression 1', solve(dict(base, **({'mutable_out':True,'sources':['a'],'mutable_inputs':['b']}))), ['mutable-source'])
check('return-extent regression 0', solve(dict(base, **({'required':[N],'available':[N+1]}))), ['return-extent'])
check('return-extent regression 1', solve(dict(base, **({'required':[N,N+1],'available':[N+1,N+2]}))), ['return-extent'])
check('binder-escape regression 0', solve(dict(base, **({'bound_depth':N,'output_depth':N-1}))), ['binder-escape'])
check('binder-escape regression 1', solve(dict(base, **({'bound_depth':N+1,'output_depth':N}))), ['binder-escape'])
check('unused-param regression 0', solve(dict(base, **({'params':['a','b'],'used_params':['a']}))), ['unused-param'])
check('unused-param regression 1', solve(dict(base, **({'params':['a','z'+str(N)],'used_params':['a']}))), ['unused-param'])
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 |
| duplicate-param regression 0 | [] | ['duplicate-param'] | Failed |
| duplicate-param regression 1 | [] | ['duplicate-param'] | Failed |
| undeclared-occurrence regression 0 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| undeclared-occurrence regression 1 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| ambiguous-elision regression 0 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| ambiguous-elision regression 1 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| receiver-elision regression 0 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| receiver-elision regression 1 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| output-source regression 0 | ['output-source'] | ['output-source'] | Passed |
| output-source regression 1 | ['output-source'] | ['output-source'] | Passed |
| local-return regression 0 | ['local-return'] | ['local-return'] | Passed |
| local-return regression 1 | ['local-return'] | ['local-return'] | Passed |
| mutable-source regression 0 | ['mutable-source'] | ['mutable-source'] | Passed |
| mutable-source regression 1 | ['mutable-source'] | ['mutable-source'] | Passed |
| return-extent regression 0 | ['return-extent'] | ['return-extent'] | Passed |
| return-extent regression 1 | ['return-extent'] | ['return-extent'] | Passed |
| binder-escape regression 0 | ['binder-escape'] | ['binder-escape'] | Passed |
| binder-escape regression 1 | ['binder-escape'] | ['binder-escape'] | Passed |
| unused-param regression 0 | ['unused-param'] | ['unused-param'] | Passed |
| unused-param regression 1 | ['unused-param'] | ['unused-param'] | Passed |
SHA-256 / 46dbaced57c9f8e2ac65e4d78dd5c83d605b4f1c56756baf95fb0482673f9a6e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if len(d['params'])>2 and len(d['params'])!=len(set(d['params'])): errors.append('duplicate-param')
if any(x not in d['params'] and x!='static' for x in d['uses']): errors.append('undeclared-occurrence')
if d['elided'] and d['receiver'] is None and len(set(d['inputs']))!=1: errors.append('ambiguous-elision')
if d['elided'] and d['receiver'] is not None and d['output']!=d['receiver']: errors.append('receiver-elision')
if any(x not in d['inputs'] for x in d['sources']): errors.append('output-source')
if bool(set(d['sources'])&set(d['locals'])): errors.append('local-return')
if d['mutable_out'] and not set(d['sources'])<=set(d['mutable_inputs']): errors.append('mutable-source')
if not set(d['required'])<=set(d['available']): errors.append('return-extent')
if d['bound_depth']>d['output_depth']: errors.append('binder-escape')
if not set(d['params'])<=set(d['used_params']): errors.append('unused-param')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'params': ['a'], 'uses': ['a'], 'inputs': ['a'], 'output': None, 'receiver': None, 'elided': False, 'sources': [], 'locals': [], 'mutable_out': False, 'mutable_inputs': [], 'required': [], 'available': [], 'bound_depth': 0, 'output_depth': 0, 'used_params': ['a']}
check('well formed empty obligations',solve(base),[])
check('duplicate-param regression 0', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('duplicate-param regression 1', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('undeclared-occurrence regression 0', solve(dict(base, **({'uses':['a','b'+str(N)]}))), ['undeclared-occurrence'])
check('undeclared-occurrence regression 1', solve(dict(base, **({'uses':['a','z']}))), ['undeclared-occurrence'])
check('ambiguous-elision regression 0', solve(dict(base, **({'elided':True,'inputs':['a','b']}))), ['ambiguous-elision'])
check('ambiguous-elision regression 1', solve(dict(base, **({'elided':True,'inputs':list(range(N+2))}))), ['ambiguous-elision'])
check('receiver-elision regression 0', solve(dict(base, **({'elided':True,'receiver':'a','output':'b'}))), ['receiver-elision'])
check('receiver-elision regression 1', solve(dict(base, **({'elided':True,'receiver':'a','output':'static'}))), ['receiver-elision'])
check('output-source regression 0', solve(dict(base, **({'sources':['a','b']}))), ['output-source'])
check('output-source regression 1', solve(dict(base, **({'sources':['a','z'+str(N)]}))), ['output-source'])
check('local-return regression 0', solve(dict(base, **({'inputs':['a','b'],'sources':['a','b'],'locals':['b']}))), ['local-return'])
check('local-return regression 1', solve(dict(base, **({'inputs':['a','c'],'sources':['a','c'],'locals':['c']}))), ['local-return'])
check('mutable-source regression 0', solve(dict(base, **({'mutable_out':True,'inputs':['a','b'],'sources':['a','b'],'mutable_inputs':['a']}))), ['mutable-source'])
check('mutable-source regression 1', solve(dict(base, **({'mutable_out':True,'sources':['a'],'mutable_inputs':['b']}))), ['mutable-source'])
check('return-extent regression 0', solve(dict(base, **({'required':[N],'available':[N+1]}))), ['return-extent'])
check('return-extent regression 1', solve(dict(base, **({'required':[N,N+1],'available':[N+1,N+2]}))), ['return-extent'])
check('binder-escape regression 0', solve(dict(base, **({'bound_depth':N,'output_depth':N-1}))), ['binder-escape'])
check('binder-escape regression 1', solve(dict(base, **({'bound_depth':N+1,'output_depth':N}))), ['binder-escape'])
check('unused-param regression 0', solve(dict(base, **({'params':['a','b'],'used_params':['a']}))), ['unused-param'])
check('unused-param regression 1', solve(dict(base, **({'params':['a','z'+str(N)],'used_params':['a']}))), ['unused-param'])
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 |
| duplicate-param regression 0 | [] | ['duplicate-param'] | Failed |
| duplicate-param regression 1 | [] | ['duplicate-param'] | Failed |
| undeclared-occurrence regression 0 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| undeclared-occurrence regression 1 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| ambiguous-elision regression 0 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| ambiguous-elision regression 1 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| receiver-elision regression 0 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| receiver-elision regression 1 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| output-source regression 0 | ['output-source'] | ['output-source'] | Passed |
| output-source regression 1 | ['output-source'] | ['output-source'] | Passed |
| local-return regression 0 | ['local-return'] | ['local-return'] | Passed |
| local-return regression 1 | ['local-return'] | ['local-return'] | Passed |
| mutable-source regression 0 | ['mutable-source'] | ['mutable-source'] | Passed |
| mutable-source regression 1 | ['mutable-source'] | ['mutable-source'] | Passed |
| return-extent regression 0 | ['return-extent'] | ['return-extent'] | Passed |
| return-extent regression 1 | ['return-extent'] | ['return-extent'] | Passed |
| binder-escape regression 0 | ['binder-escape'] | ['binder-escape'] | Passed |
| binder-escape regression 1 | ['binder-escape'] | ['binder-escape'] | Passed |
| unused-param regression 0 | ['unused-param'] | ['unused-param'] | Passed |
| unused-param regression 1 | ['unused-param'] | ['unused-param'] | Passed |
SHA-256 / 7b1dce369cd76fd029dec91699bf75d8911c114165a6c394cfc2bcc98a3c8fde
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
errors=[]
if len(d['params'])!=len(set(d['params'])): errors.append('duplicate-param')
if any(x not in d['params'] and x!='static' for x in d['uses']): errors.append('undeclared-occurrence')
if d['elided'] and d['receiver'] is None and len(set(d['inputs']))!=1: errors.append('ambiguous-elision')
if d['elided'] and d['receiver'] is not None and d['output']!=d['receiver']: errors.append('receiver-elision')
if any(x not in d['inputs'] for x in d['sources']): errors.append('output-source')
if bool(set(d['sources'])&set(d['locals'])): errors.append('local-return')
if d['mutable_out'] and not set(d['sources'])<=set(d['mutable_inputs']): errors.append('mutable-source')
if not set(d['required'])<=set(d['available']): errors.append('return-extent')
if d['bound_depth']>d['output_depth']: errors.append('binder-escape')
if not set(d['params'])<=set(d['used_params']): errors.append('unused-param')
return errors
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'params': ['a'], 'uses': ['a'], 'inputs': ['a'], 'output': None, 'receiver': None, 'elided': False, 'sources': [], 'locals': [], 'mutable_out': False, 'mutable_inputs': [], 'required': [], 'available': [], 'bound_depth': 0, 'output_depth': 0, 'used_params': ['a']}
check('well formed empty obligations',solve(base),[])
check('duplicate-param regression 0', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('duplicate-param regression 1', solve(dict(base, **({'params':['a','a']}))), ['duplicate-param'])
check('undeclared-occurrence regression 0', solve(dict(base, **({'uses':['a','b'+str(N)]}))), ['undeclared-occurrence'])
check('undeclared-occurrence regression 1', solve(dict(base, **({'uses':['a','z']}))), ['undeclared-occurrence'])
check('ambiguous-elision regression 0', solve(dict(base, **({'elided':True,'inputs':['a','b']}))), ['ambiguous-elision'])
check('ambiguous-elision regression 1', solve(dict(base, **({'elided':True,'inputs':list(range(N+2))}))), ['ambiguous-elision'])
check('receiver-elision regression 0', solve(dict(base, **({'elided':True,'receiver':'a','output':'b'}))), ['receiver-elision'])
check('receiver-elision regression 1', solve(dict(base, **({'elided':True,'receiver':'a','output':'static'}))), ['receiver-elision'])
check('output-source regression 0', solve(dict(base, **({'sources':['a','b']}))), ['output-source'])
check('output-source regression 1', solve(dict(base, **({'sources':['a','z'+str(N)]}))), ['output-source'])
check('local-return regression 0', solve(dict(base, **({'inputs':['a','b'],'sources':['a','b'],'locals':['b']}))), ['local-return'])
check('local-return regression 1', solve(dict(base, **({'inputs':['a','c'],'sources':['a','c'],'locals':['c']}))), ['local-return'])
check('mutable-source regression 0', solve(dict(base, **({'mutable_out':True,'inputs':['a','b'],'sources':['a','b'],'mutable_inputs':['a']}))), ['mutable-source'])
check('mutable-source regression 1', solve(dict(base, **({'mutable_out':True,'sources':['a'],'mutable_inputs':['b']}))), ['mutable-source'])
check('return-extent regression 0', solve(dict(base, **({'required':[N],'available':[N+1]}))), ['return-extent'])
check('return-extent regression 1', solve(dict(base, **({'required':[N,N+1],'available':[N+1,N+2]}))), ['return-extent'])
check('binder-escape regression 0', solve(dict(base, **({'bound_depth':N,'output_depth':N-1}))), ['binder-escape'])
check('binder-escape regression 1', solve(dict(base, **({'bound_depth':N+1,'output_depth':N}))), ['binder-escape'])
check('unused-param regression 0', solve(dict(base, **({'params':['a','b'],'used_params':['a']}))), ['unused-param'])
check('unused-param regression 1', solve(dict(base, **({'params':['a','z'+str(N)],'used_params':['a']}))), ['unused-param'])
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 |
| duplicate-param regression 0 | ['duplicate-param'] | ['duplicate-param'] | Passed |
| duplicate-param regression 1 | ['duplicate-param'] | ['duplicate-param'] | Passed |
| undeclared-occurrence regression 0 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| undeclared-occurrence regression 1 | ['undeclared-occurrence'] | ['undeclared-occurrence'] | Passed |
| ambiguous-elision regression 0 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| ambiguous-elision regression 1 | ['ambiguous-elision'] | ['ambiguous-elision'] | Passed |
| receiver-elision regression 0 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| receiver-elision regression 1 | ['receiver-elision'] | ['receiver-elision'] | Passed |
| output-source regression 0 | ['output-source'] | ['output-source'] | Passed |
| output-source regression 1 | ['output-source'] | ['output-source'] | Passed |
| local-return regression 0 | ['local-return'] | ['local-return'] | Passed |
| local-return regression 1 | ['local-return'] | ['local-return'] | Passed |
| mutable-source regression 0 | ['mutable-source'] | ['mutable-source'] | Passed |
| mutable-source regression 1 | ['mutable-source'] | ['mutable-source'] | Passed |
| return-extent regression 0 | ['return-extent'] | ['return-extent'] | Passed |
| return-extent regression 1 | ['return-extent'] | ['return-extent'] | Passed |
| binder-escape regression 0 | ['binder-escape'] | ['binder-escape'] | Passed |
| binder-escape regression 1 | ['binder-escape'] | ['binder-escape'] | Passed |
| unused-param regression 0 | ['unused-param'] | ['unused-param'] | Passed |
| unused-param regression 1 | ['unused-param'] | ['unused-param'] | Passed |
SHA-256 / 3034ed1110cb2e8383151540923c39e1e3b4eb5cef0a09367e4601ae444e6b56
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:43:58.304148+00:00.
Case digest / de8481030a96843c34ee96910fd31a0a59e47fc1ad7bb9503da2bd58df871e0b