FAILURE MAP
← Case archive

FA-43166 / Borrow checking / Open access

A later captured stack reference escapes with the closure environment · case 01

A later captured stack reference escapes with the closure environment.

Verified by executionVariant 1 · 21 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The static analyzer mishandles escape stack: a later captured stack reference escapes with the closure environment.

VERIFIED REPAIR

Apply the specified transfer or inference rule at this site: if d['escapes'] and bool(set(d['captures'])&set(d['stack'])): errors.append('escape-stack').

Unsuccessful approach: The partial repair uses if d['escapes'] and bool(d['captures']) and d['captures'][0] in d['stack']: errors.append('escape-stack'), which still violates the stipulated analysis contract.

Case contract

Validate an inferred closure environment. Captures contain declared places; overlapping prefix captures must be minimized; unique captures may not be duplicated; consumed captures require Once call mode; mutated captures require Mut or Once; an escaping environment cannot hold stack-only origins; environment region contains all call sites; captured references remain valid for the environment region; captures of packed fields cannot form references; captures of destructor-bearing aggregates cannot be narrowed to moved fields. 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['captures'])<=set(d['declared']): errors.append('capture-declaration')
    if any(a!=b and b.startswith(a+'.') for a in d['captures'] for b in d['captures']): errors.append('capture-prefix')
    if len(d['unique'])!=len(set(d['unique'])): errors.append('unique-duplicate')
    if bool(d['consumed']) and d['mode']!='Once': errors.append('once-mode')
    if bool(d['mutated']) and d['mode']=='Shared': errors.append('mut-mode')
    if False: errors.append('escape-stack')
    if not set(d['calls'])<=set(d['env']): errors.append('call-region')
    if not set(d['env'])<=set(d['valid']): errors.append('capture-validity')
    if bool(set(d['captures'])&set(d['packed'])): errors.append('packed-reference')
    if any(p.split('.')[0] in d['drop_aggregates'] for p in d['narrow_moves']): errors.append('destructor-narrowing')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'captures': [], 'declared': [], 'unique': [], 'consumed': [], 'mutated': [], 'mode': 'Shared', 'escapes': False, 'stack': [], 'env': [], 'calls': [], 'valid': [], 'packed': [], 'narrow_moves': [], 'drop_aggregates': []}
check('well formed empty obligations',solve(base),[])
check('capture-declaration regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a']}))), ['capture-declaration'])
check('capture-declaration regression 1', solve(dict(base, **({'captures':['a','x'+str(N)],'declared':['a']}))), ['capture-declaration'])
check('capture-prefix regression 0', solve(dict(base, **({'captures':['r','r.y'],'declared':['r','r.y']}))), ['capture-prefix'])
check('capture-prefix regression 1', solve(dict(base, **({'captures':['r','r.y.z'],'declared':['r','r.y.z']}))), ['capture-prefix'])
check('unique-duplicate regression 0', solve(dict(base, **({'unique':['r','r']}))), ['unique-duplicate'])
check('unique-duplicate regression 1', solve(dict(base, **({'unique':[N,N]}))), ['unique-duplicate'])
check('once-mode regression 0', solve(dict(base, **({'consumed':['x'],'mode':'Mut'}))), ['once-mode'])
check('once-mode regression 1', solve(dict(base, **({'consumed':list(range(N)),'mode':'Mut'}))), ['once-mode'])
check('mut-mode regression 0', solve(dict(base, **({'mutated':['x']}))), ['mut-mode'])
check('mut-mode regression 1', solve(dict(base, **({'mutated':[N]}))), ['mut-mode'])
check('escape-stack regression 0', solve(dict(base, **({'escapes':True,'captures':['a','b'],'declared':['a','b'],'stack':['b']}))), ['escape-stack'])
check('escape-stack regression 1', solve(dict(base, **({'escapes':True,'captures':['a','c'],'declared':['a','c'],'stack':['c']}))), ['escape-stack'])
check('call-region regression 0', solve(dict(base, **({'calls':[N],'env':[N+1],'valid':[N+1]}))), ['call-region'])
check('call-region regression 1', solve(dict(base, **({'calls':[N,N+1],'env':[N+1,N+2],'valid':[N+1,N+2]}))), ['call-region'])
check('capture-validity regression 0', solve(dict(base, **({'env':[N,N+1],'valid':[N]}))), ['capture-validity'])
check('capture-validity regression 1', solve(dict(base, **({'env':[N],'valid':[N+1]}))), ['capture-validity'])
check('packed-reference regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a','b'],'packed':['b']}))), ['packed-reference'])
check('packed-reference regression 1', solve(dict(base, **({'captures':['a','c'],'declared':['a','c'],'packed':['c']}))), ['packed-reference'])
check('destructor-narrowing regression 0', solve(dict(base, **({'narrow_moves':['r.f'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
check('destructor-narrowing regression 1', solve(dict(base, **({'narrow_moves':['r.f.g'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
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 fixtureActualExpectedOutcome
well formed empty obligations[][]Passed
capture-declaration regression 0['capture-declaration']['capture-declaration']Passed
capture-declaration regression 1['capture-declaration']['capture-declaration']Passed
capture-prefix regression 0['capture-prefix']['capture-prefix']Passed
capture-prefix regression 1['capture-prefix']['capture-prefix']Passed
unique-duplicate regression 0['unique-duplicate']['unique-duplicate']Passed
unique-duplicate regression 1['unique-duplicate']['unique-duplicate']Passed
once-mode regression 0['once-mode']['once-mode']Passed
once-mode regression 1['once-mode']['once-mode']Passed
mut-mode regression 0['mut-mode']['mut-mode']Passed
mut-mode regression 1['mut-mode']['mut-mode']Passed
escape-stack regression 0[]['escape-stack']Failed
escape-stack regression 1[]['escape-stack']Failed
call-region regression 0['call-region']['call-region']Passed
call-region regression 1['call-region']['call-region']Passed
capture-validity regression 0['capture-validity']['capture-validity']Passed
capture-validity regression 1['capture-validity']['capture-validity']Passed
packed-reference regression 0['packed-reference']['packed-reference']Passed
packed-reference regression 1['packed-reference']['packed-reference']Passed
destructor-narrowing regression 0['destructor-narrowing']['destructor-narrowing']Passed
destructor-narrowing regression 1['destructor-narrowing']['destructor-narrowing']Passed

SHA-256 / 0e178b5c8d2fb8e7111bdde97151a76b0e66656456b61dd11c7050203423af9f

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['captures'])<=set(d['declared']): errors.append('capture-declaration')
    if any(a!=b and b.startswith(a+'.') for a in d['captures'] for b in d['captures']): errors.append('capture-prefix')
    if len(d['unique'])!=len(set(d['unique'])): errors.append('unique-duplicate')
    if bool(d['consumed']) and d['mode']!='Once': errors.append('once-mode')
    if bool(d['mutated']) and d['mode']=='Shared': errors.append('mut-mode')
    if d['escapes'] and bool(d['captures']) and d['captures'][0] in d['stack']: errors.append('escape-stack')
    if not set(d['calls'])<=set(d['env']): errors.append('call-region')
    if not set(d['env'])<=set(d['valid']): errors.append('capture-validity')
    if bool(set(d['captures'])&set(d['packed'])): errors.append('packed-reference')
    if any(p.split('.')[0] in d['drop_aggregates'] for p in d['narrow_moves']): errors.append('destructor-narrowing')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'captures': [], 'declared': [], 'unique': [], 'consumed': [], 'mutated': [], 'mode': 'Shared', 'escapes': False, 'stack': [], 'env': [], 'calls': [], 'valid': [], 'packed': [], 'narrow_moves': [], 'drop_aggregates': []}
check('well formed empty obligations',solve(base),[])
check('capture-declaration regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a']}))), ['capture-declaration'])
check('capture-declaration regression 1', solve(dict(base, **({'captures':['a','x'+str(N)],'declared':['a']}))), ['capture-declaration'])
check('capture-prefix regression 0', solve(dict(base, **({'captures':['r','r.y'],'declared':['r','r.y']}))), ['capture-prefix'])
check('capture-prefix regression 1', solve(dict(base, **({'captures':['r','r.y.z'],'declared':['r','r.y.z']}))), ['capture-prefix'])
check('unique-duplicate regression 0', solve(dict(base, **({'unique':['r','r']}))), ['unique-duplicate'])
check('unique-duplicate regression 1', solve(dict(base, **({'unique':[N,N]}))), ['unique-duplicate'])
check('once-mode regression 0', solve(dict(base, **({'consumed':['x'],'mode':'Mut'}))), ['once-mode'])
check('once-mode regression 1', solve(dict(base, **({'consumed':list(range(N)),'mode':'Mut'}))), ['once-mode'])
check('mut-mode regression 0', solve(dict(base, **({'mutated':['x']}))), ['mut-mode'])
check('mut-mode regression 1', solve(dict(base, **({'mutated':[N]}))), ['mut-mode'])
check('escape-stack regression 0', solve(dict(base, **({'escapes':True,'captures':['a','b'],'declared':['a','b'],'stack':['b']}))), ['escape-stack'])
check('escape-stack regression 1', solve(dict(base, **({'escapes':True,'captures':['a','c'],'declared':['a','c'],'stack':['c']}))), ['escape-stack'])
check('call-region regression 0', solve(dict(base, **({'calls':[N],'env':[N+1],'valid':[N+1]}))), ['call-region'])
check('call-region regression 1', solve(dict(base, **({'calls':[N,N+1],'env':[N+1,N+2],'valid':[N+1,N+2]}))), ['call-region'])
check('capture-validity regression 0', solve(dict(base, **({'env':[N,N+1],'valid':[N]}))), ['capture-validity'])
check('capture-validity regression 1', solve(dict(base, **({'env':[N],'valid':[N+1]}))), ['capture-validity'])
check('packed-reference regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a','b'],'packed':['b']}))), ['packed-reference'])
check('packed-reference regression 1', solve(dict(base, **({'captures':['a','c'],'declared':['a','c'],'packed':['c']}))), ['packed-reference'])
check('destructor-narrowing regression 0', solve(dict(base, **({'narrow_moves':['r.f'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
check('destructor-narrowing regression 1', solve(dict(base, **({'narrow_moves':['r.f.g'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
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 fixtureActualExpectedOutcome
well formed empty obligations[][]Passed
capture-declaration regression 0['capture-declaration']['capture-declaration']Passed
capture-declaration regression 1['capture-declaration']['capture-declaration']Passed
capture-prefix regression 0['capture-prefix']['capture-prefix']Passed
capture-prefix regression 1['capture-prefix']['capture-prefix']Passed
unique-duplicate regression 0['unique-duplicate']['unique-duplicate']Passed
unique-duplicate regression 1['unique-duplicate']['unique-duplicate']Passed
once-mode regression 0['once-mode']['once-mode']Passed
once-mode regression 1['once-mode']['once-mode']Passed
mut-mode regression 0['mut-mode']['mut-mode']Passed
mut-mode regression 1['mut-mode']['mut-mode']Passed
escape-stack regression 0[]['escape-stack']Failed
escape-stack regression 1[]['escape-stack']Failed
call-region regression 0['call-region']['call-region']Passed
call-region regression 1['call-region']['call-region']Passed
capture-validity regression 0['capture-validity']['capture-validity']Passed
capture-validity regression 1['capture-validity']['capture-validity']Passed
packed-reference regression 0['packed-reference']['packed-reference']Passed
packed-reference regression 1['packed-reference']['packed-reference']Passed
destructor-narrowing regression 0['destructor-narrowing']['destructor-narrowing']Passed
destructor-narrowing regression 1['destructor-narrowing']['destructor-narrowing']Passed

SHA-256 / 5a59b49036c51244f07bf818857902991afca6099be29e20f13816234cc04046

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['captures'])<=set(d['declared']): errors.append('capture-declaration')
    if any(a!=b and b.startswith(a+'.') for a in d['captures'] for b in d['captures']): errors.append('capture-prefix')
    if len(d['unique'])!=len(set(d['unique'])): errors.append('unique-duplicate')
    if bool(d['consumed']) and d['mode']!='Once': errors.append('once-mode')
    if bool(d['mutated']) and d['mode']=='Shared': errors.append('mut-mode')
    if d['escapes'] and bool(set(d['captures'])&set(d['stack'])): errors.append('escape-stack')
    if not set(d['calls'])<=set(d['env']): errors.append('call-region')
    if not set(d['env'])<=set(d['valid']): errors.append('capture-validity')
    if bool(set(d['captures'])&set(d['packed'])): errors.append('packed-reference')
    if any(p.split('.')[0] in d['drop_aggregates'] for p in d['narrow_moves']): errors.append('destructor-narrowing')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'captures': [], 'declared': [], 'unique': [], 'consumed': [], 'mutated': [], 'mode': 'Shared', 'escapes': False, 'stack': [], 'env': [], 'calls': [], 'valid': [], 'packed': [], 'narrow_moves': [], 'drop_aggregates': []}
check('well formed empty obligations',solve(base),[])
check('capture-declaration regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a']}))), ['capture-declaration'])
check('capture-declaration regression 1', solve(dict(base, **({'captures':['a','x'+str(N)],'declared':['a']}))), ['capture-declaration'])
check('capture-prefix regression 0', solve(dict(base, **({'captures':['r','r.y'],'declared':['r','r.y']}))), ['capture-prefix'])
check('capture-prefix regression 1', solve(dict(base, **({'captures':['r','r.y.z'],'declared':['r','r.y.z']}))), ['capture-prefix'])
check('unique-duplicate regression 0', solve(dict(base, **({'unique':['r','r']}))), ['unique-duplicate'])
check('unique-duplicate regression 1', solve(dict(base, **({'unique':[N,N]}))), ['unique-duplicate'])
check('once-mode regression 0', solve(dict(base, **({'consumed':['x'],'mode':'Mut'}))), ['once-mode'])
check('once-mode regression 1', solve(dict(base, **({'consumed':list(range(N)),'mode':'Mut'}))), ['once-mode'])
check('mut-mode regression 0', solve(dict(base, **({'mutated':['x']}))), ['mut-mode'])
check('mut-mode regression 1', solve(dict(base, **({'mutated':[N]}))), ['mut-mode'])
check('escape-stack regression 0', solve(dict(base, **({'escapes':True,'captures':['a','b'],'declared':['a','b'],'stack':['b']}))), ['escape-stack'])
check('escape-stack regression 1', solve(dict(base, **({'escapes':True,'captures':['a','c'],'declared':['a','c'],'stack':['c']}))), ['escape-stack'])
check('call-region regression 0', solve(dict(base, **({'calls':[N],'env':[N+1],'valid':[N+1]}))), ['call-region'])
check('call-region regression 1', solve(dict(base, **({'calls':[N,N+1],'env':[N+1,N+2],'valid':[N+1,N+2]}))), ['call-region'])
check('capture-validity regression 0', solve(dict(base, **({'env':[N,N+1],'valid':[N]}))), ['capture-validity'])
check('capture-validity regression 1', solve(dict(base, **({'env':[N],'valid':[N+1]}))), ['capture-validity'])
check('packed-reference regression 0', solve(dict(base, **({'captures':['a','b'],'declared':['a','b'],'packed':['b']}))), ['packed-reference'])
check('packed-reference regression 1', solve(dict(base, **({'captures':['a','c'],'declared':['a','c'],'packed':['c']}))), ['packed-reference'])
check('destructor-narrowing regression 0', solve(dict(base, **({'narrow_moves':['r.f'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
check('destructor-narrowing regression 1', solve(dict(base, **({'narrow_moves':['r.f.g'],'drop_aggregates':['r']}))), ['destructor-narrowing'])
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 fixtureActualExpectedOutcome
well formed empty obligations[][]Passed
capture-declaration regression 0['capture-declaration']['capture-declaration']Passed
capture-declaration regression 1['capture-declaration']['capture-declaration']Passed
capture-prefix regression 0['capture-prefix']['capture-prefix']Passed
capture-prefix regression 1['capture-prefix']['capture-prefix']Passed
unique-duplicate regression 0['unique-duplicate']['unique-duplicate']Passed
unique-duplicate regression 1['unique-duplicate']['unique-duplicate']Passed
once-mode regression 0['once-mode']['once-mode']Passed
once-mode regression 1['once-mode']['once-mode']Passed
mut-mode regression 0['mut-mode']['mut-mode']Passed
mut-mode regression 1['mut-mode']['mut-mode']Passed
escape-stack regression 0['escape-stack']['escape-stack']Passed
escape-stack regression 1['escape-stack']['escape-stack']Passed
call-region regression 0['call-region']['call-region']Passed
call-region regression 1['call-region']['call-region']Passed
capture-validity regression 0['capture-validity']['capture-validity']Passed
capture-validity regression 1['capture-validity']['capture-validity']Passed
packed-reference regression 0['packed-reference']['packed-reference']Passed
packed-reference regression 1['packed-reference']['packed-reference']Passed
destructor-narrowing regression 0['destructor-narrowing']['destructor-narrowing']Passed
destructor-narrowing regression 1['destructor-narrowing']['destructor-narrowing']Passed

SHA-256 / 31bc3e8d8a845d75771ca458bcda68ca0e73bfa4fe96d77bacc152071b1d4c33

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:59.030629+00:00.

Case digest / 3248978331a0b0fd718978c0f0ac8f47e144f657637fe41e5a06d70ea555739b