FAILURE MAP
← Case archive

FA-44171 / Borrow checking / Open access

Continuation argument lowering transfers one owned value twice · case 01

Continuation argument lowering transfers one owned value twice.

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

ROOT CAUSE

The static analyzer mishandles argument transfer once: continuation argument lowering transfers one owned value twice.

VERIFIED REPAIR

Apply the specified transfer or inference rule at this site: if len(d['argument_transfers'])!=len(set(d['argument_transfers'])): errors.append('argument-transfer-once').

Unsuccessful approach: The partial repair uses if len(d['argument_transfers'])>2 and len(d['argument_transfers'])!=len(set(d['argument_transfers'])): errors.append('argument-transfer-once'), which still violates the stipulated analysis contract.

Case contract

Check a one-shot continuation calculus with borrowed captures. A continuation resumes at most once; abort releases captures; escaping continuation may not borrow its capturing stack; cloning continuation cannot duplicate unique captures; resumption restores suspended loans; captured owner must survive resumed body; continuation argument ownership is transferred once; nested handler cannot release outer captures; unwound continuation invalidates frame-local reference results; resumed result origin must be among the continuation declared return origins. 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['resume_count']>1: errors.append('one-shot-resume')
    if d['aborted'] and bool(d['capture_live']): errors.append('abort-capture-release')
    if d['escapes'] and bool(d['stack_captures']): errors.append('escape-capture-stack')
    if d['cloned'] and bool(d['unique_captures']): errors.append('clone-unique-capture')
    if not set(d['suspended'])<=set(d['restored']): errors.append('resume-loan-restore')
    if d['resumed_end']>d['owner_end']: errors.append('captured-owner-duration')
    if False: errors.append('argument-transfer-once')
    if bool(set(d['outer_captures'])&set(d['released'])): errors.append('handler-capture-boundary')
    if d['unwound'] and bool(d['frame_results']): errors.append('unwind-frame-result')
    if not set(d['result_origins'])<=set(d['declared_returns']): errors.append('continuation-return-summary')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'resume_count': 0, 'aborted': False, 'capture_live': [], 'escapes': False, 'stack_captures': [], 'cloned': False, 'unique_captures': [], 'suspended': [], 'restored': [], 'owner_end': 0, 'resumed_end': 0, 'argument_transfers': [], 'outer_captures': [], 'released': [], 'unwound': False, 'frame_results': [], 'result_origins': [], 'declared_returns': []}
check('well formed empty obligations',solve(base),[])
check('one-shot-resume regression 0', solve(dict(base, **({'resume_count':2}))), ['one-shot-resume'])
check('one-shot-resume regression 1', solve(dict(base, **({'resume_count':2,'owner_end':N,'resumed_end':N}))), ['one-shot-resume'])
check('abort-capture-release regression 0', solve(dict(base, **({'aborted':True,'capture_live':['r']}))), ['abort-capture-release'])
check('abort-capture-release regression 1', solve(dict(base, **({'aborted':True,'capture_live':[N]}))), ['abort-capture-release'])
check('escape-capture-stack regression 0', solve(dict(base, **({'escapes':True,'stack_captures':['r']}))), ['escape-capture-stack'])
check('escape-capture-stack regression 1', solve(dict(base, **({'escapes':True,'stack_captures':[N]}))), ['escape-capture-stack'])
check('clone-unique-capture regression 0', solve(dict(base, **({'cloned':True,'unique_captures':['r']}))), ['clone-unique-capture'])
check('clone-unique-capture regression 1', solve(dict(base, **({'cloned':True,'unique_captures':[N]}))), ['clone-unique-capture'])
check('resume-loan-restore regression 0', solve(dict(base, **({'suspended':['a','b'],'restored':['a']}))), ['resume-loan-restore'])
check('resume-loan-restore regression 1', solve(dict(base, **({'suspended':[N,N+1],'restored':[N]}))), ['resume-loan-restore'])
check('captured-owner-duration regression 0', solve(dict(base, **({'resumed_end':N+1,'owner_end':N}))), ['captured-owner-duration'])
check('captured-owner-duration regression 1', solve(dict(base, **({'resumed_end':N+2,'owner_end':N+1}))), ['captured-owner-duration'])
check('argument-transfer-once regression 0', solve(dict(base, **({'argument_transfers':['x','x']}))), ['argument-transfer-once'])
check('argument-transfer-once regression 1', solve(dict(base, **({'argument_transfers':[N,N]}))), ['argument-transfer-once'])
check('handler-capture-boundary regression 0', solve(dict(base, **({'outer_captures':['r'],'released':['r']}))), ['handler-capture-boundary'])
check('handler-capture-boundary regression 1', solve(dict(base, **({'outer_captures':[N],'released':[N]}))), ['handler-capture-boundary'])
check('unwind-frame-result regression 0', solve(dict(base, **({'unwound':True,'frame_results':['r']}))), ['unwind-frame-result'])
check('unwind-frame-result regression 1', solve(dict(base, **({'unwound':True,'frame_results':[N]}))), ['unwind-frame-result'])
check('continuation-return-summary regression 0', solve(dict(base, **({'result_origins':['a','b'],'declared_returns':['a']}))), ['continuation-return-summary'])
check('continuation-return-summary regression 1', solve(dict(base, **({'result_origins':[N,N+1],'declared_returns':[N]}))), ['continuation-return-summary'])
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
one-shot-resume regression 0['one-shot-resume']['one-shot-resume']Passed
one-shot-resume regression 1['one-shot-resume']['one-shot-resume']Passed
abort-capture-release regression 0['abort-capture-release']['abort-capture-release']Passed
abort-capture-release regression 1['abort-capture-release']['abort-capture-release']Passed
escape-capture-stack regression 0['escape-capture-stack']['escape-capture-stack']Passed
escape-capture-stack regression 1['escape-capture-stack']['escape-capture-stack']Passed
clone-unique-capture regression 0['clone-unique-capture']['clone-unique-capture']Passed
clone-unique-capture regression 1['clone-unique-capture']['clone-unique-capture']Passed
resume-loan-restore regression 0['resume-loan-restore']['resume-loan-restore']Passed
resume-loan-restore regression 1['resume-loan-restore']['resume-loan-restore']Passed
captured-owner-duration regression 0['captured-owner-duration']['captured-owner-duration']Passed
captured-owner-duration regression 1['captured-owner-duration']['captured-owner-duration']Passed
argument-transfer-once regression 0[]['argument-transfer-once']Failed
argument-transfer-once regression 1[]['argument-transfer-once']Failed
handler-capture-boundary regression 0['handler-capture-boundary']['handler-capture-boundary']Passed
handler-capture-boundary regression 1['handler-capture-boundary']['handler-capture-boundary']Passed
unwind-frame-result regression 0['unwind-frame-result']['unwind-frame-result']Passed
unwind-frame-result regression 1['unwind-frame-result']['unwind-frame-result']Passed
continuation-return-summary regression 0['continuation-return-summary']['continuation-return-summary']Passed
continuation-return-summary regression 1['continuation-return-summary']['continuation-return-summary']Passed

SHA-256 / c126bc8c6a3166f71a8c60bb9407e14f9ce1ec51cfebc5b3bc4430cfd6694d2b

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['resume_count']>1: errors.append('one-shot-resume')
    if d['aborted'] and bool(d['capture_live']): errors.append('abort-capture-release')
    if d['escapes'] and bool(d['stack_captures']): errors.append('escape-capture-stack')
    if d['cloned'] and bool(d['unique_captures']): errors.append('clone-unique-capture')
    if not set(d['suspended'])<=set(d['restored']): errors.append('resume-loan-restore')
    if d['resumed_end']>d['owner_end']: errors.append('captured-owner-duration')
    if len(d['argument_transfers'])>2 and len(d['argument_transfers'])!=len(set(d['argument_transfers'])): errors.append('argument-transfer-once')
    if bool(set(d['outer_captures'])&set(d['released'])): errors.append('handler-capture-boundary')
    if d['unwound'] and bool(d['frame_results']): errors.append('unwind-frame-result')
    if not set(d['result_origins'])<=set(d['declared_returns']): errors.append('continuation-return-summary')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'resume_count': 0, 'aborted': False, 'capture_live': [], 'escapes': False, 'stack_captures': [], 'cloned': False, 'unique_captures': [], 'suspended': [], 'restored': [], 'owner_end': 0, 'resumed_end': 0, 'argument_transfers': [], 'outer_captures': [], 'released': [], 'unwound': False, 'frame_results': [], 'result_origins': [], 'declared_returns': []}
check('well formed empty obligations',solve(base),[])
check('one-shot-resume regression 0', solve(dict(base, **({'resume_count':2}))), ['one-shot-resume'])
check('one-shot-resume regression 1', solve(dict(base, **({'resume_count':2,'owner_end':N,'resumed_end':N}))), ['one-shot-resume'])
check('abort-capture-release regression 0', solve(dict(base, **({'aborted':True,'capture_live':['r']}))), ['abort-capture-release'])
check('abort-capture-release regression 1', solve(dict(base, **({'aborted':True,'capture_live':[N]}))), ['abort-capture-release'])
check('escape-capture-stack regression 0', solve(dict(base, **({'escapes':True,'stack_captures':['r']}))), ['escape-capture-stack'])
check('escape-capture-stack regression 1', solve(dict(base, **({'escapes':True,'stack_captures':[N]}))), ['escape-capture-stack'])
check('clone-unique-capture regression 0', solve(dict(base, **({'cloned':True,'unique_captures':['r']}))), ['clone-unique-capture'])
check('clone-unique-capture regression 1', solve(dict(base, **({'cloned':True,'unique_captures':[N]}))), ['clone-unique-capture'])
check('resume-loan-restore regression 0', solve(dict(base, **({'suspended':['a','b'],'restored':['a']}))), ['resume-loan-restore'])
check('resume-loan-restore regression 1', solve(dict(base, **({'suspended':[N,N+1],'restored':[N]}))), ['resume-loan-restore'])
check('captured-owner-duration regression 0', solve(dict(base, **({'resumed_end':N+1,'owner_end':N}))), ['captured-owner-duration'])
check('captured-owner-duration regression 1', solve(dict(base, **({'resumed_end':N+2,'owner_end':N+1}))), ['captured-owner-duration'])
check('argument-transfer-once regression 0', solve(dict(base, **({'argument_transfers':['x','x']}))), ['argument-transfer-once'])
check('argument-transfer-once regression 1', solve(dict(base, **({'argument_transfers':[N,N]}))), ['argument-transfer-once'])
check('handler-capture-boundary regression 0', solve(dict(base, **({'outer_captures':['r'],'released':['r']}))), ['handler-capture-boundary'])
check('handler-capture-boundary regression 1', solve(dict(base, **({'outer_captures':[N],'released':[N]}))), ['handler-capture-boundary'])
check('unwind-frame-result regression 0', solve(dict(base, **({'unwound':True,'frame_results':['r']}))), ['unwind-frame-result'])
check('unwind-frame-result regression 1', solve(dict(base, **({'unwound':True,'frame_results':[N]}))), ['unwind-frame-result'])
check('continuation-return-summary regression 0', solve(dict(base, **({'result_origins':['a','b'],'declared_returns':['a']}))), ['continuation-return-summary'])
check('continuation-return-summary regression 1', solve(dict(base, **({'result_origins':[N,N+1],'declared_returns':[N]}))), ['continuation-return-summary'])
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
one-shot-resume regression 0['one-shot-resume']['one-shot-resume']Passed
one-shot-resume regression 1['one-shot-resume']['one-shot-resume']Passed
abort-capture-release regression 0['abort-capture-release']['abort-capture-release']Passed
abort-capture-release regression 1['abort-capture-release']['abort-capture-release']Passed
escape-capture-stack regression 0['escape-capture-stack']['escape-capture-stack']Passed
escape-capture-stack regression 1['escape-capture-stack']['escape-capture-stack']Passed
clone-unique-capture regression 0['clone-unique-capture']['clone-unique-capture']Passed
clone-unique-capture regression 1['clone-unique-capture']['clone-unique-capture']Passed
resume-loan-restore regression 0['resume-loan-restore']['resume-loan-restore']Passed
resume-loan-restore regression 1['resume-loan-restore']['resume-loan-restore']Passed
captured-owner-duration regression 0['captured-owner-duration']['captured-owner-duration']Passed
captured-owner-duration regression 1['captured-owner-duration']['captured-owner-duration']Passed
argument-transfer-once regression 0[]['argument-transfer-once']Failed
argument-transfer-once regression 1[]['argument-transfer-once']Failed
handler-capture-boundary regression 0['handler-capture-boundary']['handler-capture-boundary']Passed
handler-capture-boundary regression 1['handler-capture-boundary']['handler-capture-boundary']Passed
unwind-frame-result regression 0['unwind-frame-result']['unwind-frame-result']Passed
unwind-frame-result regression 1['unwind-frame-result']['unwind-frame-result']Passed
continuation-return-summary regression 0['continuation-return-summary']['continuation-return-summary']Passed
continuation-return-summary regression 1['continuation-return-summary']['continuation-return-summary']Passed

SHA-256 / 243cbc167ade2d8b6a99328932ca7d56d3c4a2d48b666cec38d5793bc701a546

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['resume_count']>1: errors.append('one-shot-resume')
    if d['aborted'] and bool(d['capture_live']): errors.append('abort-capture-release')
    if d['escapes'] and bool(d['stack_captures']): errors.append('escape-capture-stack')
    if d['cloned'] and bool(d['unique_captures']): errors.append('clone-unique-capture')
    if not set(d['suspended'])<=set(d['restored']): errors.append('resume-loan-restore')
    if d['resumed_end']>d['owner_end']: errors.append('captured-owner-duration')
    if len(d['argument_transfers'])!=len(set(d['argument_transfers'])): errors.append('argument-transfer-once')
    if bool(set(d['outer_captures'])&set(d['released'])): errors.append('handler-capture-boundary')
    if d['unwound'] and bool(d['frame_results']): errors.append('unwind-frame-result')
    if not set(d['result_origins'])<=set(d['declared_returns']): errors.append('continuation-return-summary')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'resume_count': 0, 'aborted': False, 'capture_live': [], 'escapes': False, 'stack_captures': [], 'cloned': False, 'unique_captures': [], 'suspended': [], 'restored': [], 'owner_end': 0, 'resumed_end': 0, 'argument_transfers': [], 'outer_captures': [], 'released': [], 'unwound': False, 'frame_results': [], 'result_origins': [], 'declared_returns': []}
check('well formed empty obligations',solve(base),[])
check('one-shot-resume regression 0', solve(dict(base, **({'resume_count':2}))), ['one-shot-resume'])
check('one-shot-resume regression 1', solve(dict(base, **({'resume_count':2,'owner_end':N,'resumed_end':N}))), ['one-shot-resume'])
check('abort-capture-release regression 0', solve(dict(base, **({'aborted':True,'capture_live':['r']}))), ['abort-capture-release'])
check('abort-capture-release regression 1', solve(dict(base, **({'aborted':True,'capture_live':[N]}))), ['abort-capture-release'])
check('escape-capture-stack regression 0', solve(dict(base, **({'escapes':True,'stack_captures':['r']}))), ['escape-capture-stack'])
check('escape-capture-stack regression 1', solve(dict(base, **({'escapes':True,'stack_captures':[N]}))), ['escape-capture-stack'])
check('clone-unique-capture regression 0', solve(dict(base, **({'cloned':True,'unique_captures':['r']}))), ['clone-unique-capture'])
check('clone-unique-capture regression 1', solve(dict(base, **({'cloned':True,'unique_captures':[N]}))), ['clone-unique-capture'])
check('resume-loan-restore regression 0', solve(dict(base, **({'suspended':['a','b'],'restored':['a']}))), ['resume-loan-restore'])
check('resume-loan-restore regression 1', solve(dict(base, **({'suspended':[N,N+1],'restored':[N]}))), ['resume-loan-restore'])
check('captured-owner-duration regression 0', solve(dict(base, **({'resumed_end':N+1,'owner_end':N}))), ['captured-owner-duration'])
check('captured-owner-duration regression 1', solve(dict(base, **({'resumed_end':N+2,'owner_end':N+1}))), ['captured-owner-duration'])
check('argument-transfer-once regression 0', solve(dict(base, **({'argument_transfers':['x','x']}))), ['argument-transfer-once'])
check('argument-transfer-once regression 1', solve(dict(base, **({'argument_transfers':[N,N]}))), ['argument-transfer-once'])
check('handler-capture-boundary regression 0', solve(dict(base, **({'outer_captures':['r'],'released':['r']}))), ['handler-capture-boundary'])
check('handler-capture-boundary regression 1', solve(dict(base, **({'outer_captures':[N],'released':[N]}))), ['handler-capture-boundary'])
check('unwind-frame-result regression 0', solve(dict(base, **({'unwound':True,'frame_results':['r']}))), ['unwind-frame-result'])
check('unwind-frame-result regression 1', solve(dict(base, **({'unwound':True,'frame_results':[N]}))), ['unwind-frame-result'])
check('continuation-return-summary regression 0', solve(dict(base, **({'result_origins':['a','b'],'declared_returns':['a']}))), ['continuation-return-summary'])
check('continuation-return-summary regression 1', solve(dict(base, **({'result_origins':[N,N+1],'declared_returns':[N]}))), ['continuation-return-summary'])
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
one-shot-resume regression 0['one-shot-resume']['one-shot-resume']Passed
one-shot-resume regression 1['one-shot-resume']['one-shot-resume']Passed
abort-capture-release regression 0['abort-capture-release']['abort-capture-release']Passed
abort-capture-release regression 1['abort-capture-release']['abort-capture-release']Passed
escape-capture-stack regression 0['escape-capture-stack']['escape-capture-stack']Passed
escape-capture-stack regression 1['escape-capture-stack']['escape-capture-stack']Passed
clone-unique-capture regression 0['clone-unique-capture']['clone-unique-capture']Passed
clone-unique-capture regression 1['clone-unique-capture']['clone-unique-capture']Passed
resume-loan-restore regression 0['resume-loan-restore']['resume-loan-restore']Passed
resume-loan-restore regression 1['resume-loan-restore']['resume-loan-restore']Passed
captured-owner-duration regression 0['captured-owner-duration']['captured-owner-duration']Passed
captured-owner-duration regression 1['captured-owner-duration']['captured-owner-duration']Passed
argument-transfer-once regression 0['argument-transfer-once']['argument-transfer-once']Passed
argument-transfer-once regression 1['argument-transfer-once']['argument-transfer-once']Passed
handler-capture-boundary regression 0['handler-capture-boundary']['handler-capture-boundary']Passed
handler-capture-boundary regression 1['handler-capture-boundary']['handler-capture-boundary']Passed
unwind-frame-result regression 0['unwind-frame-result']['unwind-frame-result']Passed
unwind-frame-result regression 1['unwind-frame-result']['unwind-frame-result']Passed
continuation-return-summary regression 0['continuation-return-summary']['continuation-return-summary']Passed
continuation-return-summary regression 1['continuation-return-summary']['continuation-return-summary']Passed

SHA-256 / e613f1e6b3e0ea60caf3a012866b3dad1fb79f384ff7314d160c6525e37b03ad

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

Case digest / 2ab2910956dc1ddb6fc84ef2a454ae896b47f5ac0de67b37b2d61acc2c6962f7