FAILURE MAP
← Case archive

FA-43706 / Borrow checking / Open access

Replacing a pinned referent bypasses the move prohibition · case 01

Replacing a pinned referent bypasses the move prohibition.

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

ROOT CAUSE

The static analyzer mishandles pin replace: replacing a pinned referent bypasses the move prohibition.

VERIFIED REPAIR

Apply the specified transfer or inference rule at this site: if d['pinned'] and not d['unpin'] and d['replace']: errors.append('pin-replace').

Unsuccessful approach: The partial repair uses if d['pinned'] and not d['unpin'] and d['replace'] and bool(d['moves']): errors.append('pin-replace'), which still violates the stipulated analysis contract.

Case contract

Check a toy pin-aware ownership IR. Pinned non-Unpin values may not move; field projection requires structural pin declaration; unpinned fields remain movable; replace through pinned reference requires Unpin; pinned destructor cannot move receiver; packing disallows safe pinned field references; projecting through shared pointer cannot produce unique pinned reference; converting pin to raw keeps provenance; unchecked pin construction requires an explicit immovability proof; frame relocation invalidates an earlier pin proof. 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['pinned'] and not d['unpin'] and bool(d['moves']): errors.append('pinned-move')
    if not set(d['projected'])<=set(d['structural']): errors.append('structural-projection')
    if bool(set(d['unpin_fields'])&set(d['blocked_fields'])): errors.append('unpinned-field-move')
    if False: errors.append('pin-replace')
    if d['pinned'] and d['destructor_move']: errors.append('pinned-destructor')
    if bool(set(d['projected'])&set(d['packed_fields'])): errors.append('packed-pin')
    if d['source_shared'] and d['unique_projection']: errors.append('shared-pin-uniqueness')
    if d['raw_origin']!=d['pin_origin']: errors.append('raw-pin-provenance')
    if d['unchecked_construct'] and not d['proof']: errors.append('unchecked-pin-proof')
    if d['pin_generation']!=d['frame_generation']: errors.append('pin-relocation')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'pinned': False, 'unpin': True, 'moves': [], 'projected': [], 'structural': [], 'unpin_fields': [], 'blocked_fields': [], 'replace': False, 'destructor_move': False, 'packed_fields': [], 'source_shared': False, 'unique_projection': False, 'raw_origin': None, 'pin_origin': None, 'unchecked_construct': False, 'proof': False, 'pin_generation': 0, 'frame_generation': 0}
check('well formed empty obligations',solve(base),[])
check('pinned-move regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'moves':['x']}))), ['pinned-move'])
check('pinned-move regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'moves':[N]}))), ['pinned-move'])
check('structural-projection regression 0', solve(dict(base, **({'projected':['a','b'],'structural':['a']}))), ['structural-projection'])
check('structural-projection regression 1', solve(dict(base, **({'projected':[N,N+1],'structural':[N]}))), ['structural-projection'])
check('unpinned-field-move regression 0', solve(dict(base, **({'unpin_fields':['a'],'blocked_fields':['a']}))), ['unpinned-field-move'])
check('unpinned-field-move regression 1', solve(dict(base, **({'unpin_fields':[N],'blocked_fields':[N]}))), ['unpinned-field-move'])
check('pin-replace regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True}))), ['pin-replace'])
check('pin-replace regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True,'frame_generation':N,'pin_generation':N}))), ['pin-replace'])
check('pinned-destructor regression 0', solve(dict(base, **({'pinned':True,'destructor_move':True}))), ['pinned-destructor'])
check('pinned-destructor regression 1', solve(dict(base, **({'pinned':True,'destructor_move':True,'frame_generation':N,'pin_generation':N}))), ['pinned-destructor'])
check('packed-pin regression 0', solve(dict(base, **({'projected':['a'],'structural':['a'],'packed_fields':['a']}))), ['packed-pin'])
check('packed-pin regression 1', solve(dict(base, **({'projected':[N],'structural':[N],'packed_fields':[N]}))), ['packed-pin'])
check('shared-pin-uniqueness regression 0', solve(dict(base, **({'source_shared':True,'unique_projection':True}))), ['shared-pin-uniqueness'])
check('shared-pin-uniqueness regression 1', solve(dict(base, **({'source_shared':True,'unique_projection':True,'frame_generation':N,'pin_generation':N}))), ['shared-pin-uniqueness'])
check('raw-pin-provenance regression 0', solve(dict(base, **({'raw_origin':'b','pin_origin':'a'}))), ['raw-pin-provenance'])
check('raw-pin-provenance regression 1', solve(dict(base, **({'raw_origin':N+1,'pin_origin':N}))), ['raw-pin-provenance'])
check('unchecked-pin-proof regression 0', solve(dict(base, **({'unchecked_construct':True}))), ['unchecked-pin-proof'])
check('unchecked-pin-proof regression 1', solve(dict(base, **({'unchecked_construct':True,'frame_generation':N,'pin_generation':N}))), ['unchecked-pin-proof'])
check('pin-relocation regression 0', solve(dict(base, **({'pin_generation':N,'frame_generation':N+1}))), ['pin-relocation'])
check('pin-relocation regression 1', solve(dict(base, **({'pin_generation':N+1,'frame_generation':N+2}))), ['pin-relocation'])
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
pinned-move regression 0['pinned-move']['pinned-move']Passed
pinned-move regression 1['pinned-move']['pinned-move']Passed
structural-projection regression 0['structural-projection']['structural-projection']Passed
structural-projection regression 1['structural-projection']['structural-projection']Passed
unpinned-field-move regression 0['unpinned-field-move']['unpinned-field-move']Passed
unpinned-field-move regression 1['unpinned-field-move']['unpinned-field-move']Passed
pin-replace regression 0[]['pin-replace']Failed
pin-replace regression 1[]['pin-replace']Failed
pinned-destructor regression 0['pinned-destructor']['pinned-destructor']Passed
pinned-destructor regression 1['pinned-destructor']['pinned-destructor']Passed
packed-pin regression 0['packed-pin']['packed-pin']Passed
packed-pin regression 1['packed-pin']['packed-pin']Passed
shared-pin-uniqueness regression 0['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
shared-pin-uniqueness regression 1['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
raw-pin-provenance regression 0['raw-pin-provenance']['raw-pin-provenance']Passed
raw-pin-provenance regression 1['raw-pin-provenance']['raw-pin-provenance']Passed
unchecked-pin-proof regression 0['unchecked-pin-proof']['unchecked-pin-proof']Passed
unchecked-pin-proof regression 1['unchecked-pin-proof']['unchecked-pin-proof']Passed
pin-relocation regression 0['pin-relocation']['pin-relocation']Passed
pin-relocation regression 1['pin-relocation']['pin-relocation']Passed

SHA-256 / 80cc4feeb001c9f38d2764944d28e86add9084db4822df2157851d742ccbc8f1

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['pinned'] and not d['unpin'] and bool(d['moves']): errors.append('pinned-move')
    if not set(d['projected'])<=set(d['structural']): errors.append('structural-projection')
    if bool(set(d['unpin_fields'])&set(d['blocked_fields'])): errors.append('unpinned-field-move')
    if d['pinned'] and not d['unpin'] and d['replace'] and bool(d['moves']): errors.append('pin-replace')
    if d['pinned'] and d['destructor_move']: errors.append('pinned-destructor')
    if bool(set(d['projected'])&set(d['packed_fields'])): errors.append('packed-pin')
    if d['source_shared'] and d['unique_projection']: errors.append('shared-pin-uniqueness')
    if d['raw_origin']!=d['pin_origin']: errors.append('raw-pin-provenance')
    if d['unchecked_construct'] and not d['proof']: errors.append('unchecked-pin-proof')
    if d['pin_generation']!=d['frame_generation']: errors.append('pin-relocation')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'pinned': False, 'unpin': True, 'moves': [], 'projected': [], 'structural': [], 'unpin_fields': [], 'blocked_fields': [], 'replace': False, 'destructor_move': False, 'packed_fields': [], 'source_shared': False, 'unique_projection': False, 'raw_origin': None, 'pin_origin': None, 'unchecked_construct': False, 'proof': False, 'pin_generation': 0, 'frame_generation': 0}
check('well formed empty obligations',solve(base),[])
check('pinned-move regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'moves':['x']}))), ['pinned-move'])
check('pinned-move regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'moves':[N]}))), ['pinned-move'])
check('structural-projection regression 0', solve(dict(base, **({'projected':['a','b'],'structural':['a']}))), ['structural-projection'])
check('structural-projection regression 1', solve(dict(base, **({'projected':[N,N+1],'structural':[N]}))), ['structural-projection'])
check('unpinned-field-move regression 0', solve(dict(base, **({'unpin_fields':['a'],'blocked_fields':['a']}))), ['unpinned-field-move'])
check('unpinned-field-move regression 1', solve(dict(base, **({'unpin_fields':[N],'blocked_fields':[N]}))), ['unpinned-field-move'])
check('pin-replace regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True}))), ['pin-replace'])
check('pin-replace regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True,'frame_generation':N,'pin_generation':N}))), ['pin-replace'])
check('pinned-destructor regression 0', solve(dict(base, **({'pinned':True,'destructor_move':True}))), ['pinned-destructor'])
check('pinned-destructor regression 1', solve(dict(base, **({'pinned':True,'destructor_move':True,'frame_generation':N,'pin_generation':N}))), ['pinned-destructor'])
check('packed-pin regression 0', solve(dict(base, **({'projected':['a'],'structural':['a'],'packed_fields':['a']}))), ['packed-pin'])
check('packed-pin regression 1', solve(dict(base, **({'projected':[N],'structural':[N],'packed_fields':[N]}))), ['packed-pin'])
check('shared-pin-uniqueness regression 0', solve(dict(base, **({'source_shared':True,'unique_projection':True}))), ['shared-pin-uniqueness'])
check('shared-pin-uniqueness regression 1', solve(dict(base, **({'source_shared':True,'unique_projection':True,'frame_generation':N,'pin_generation':N}))), ['shared-pin-uniqueness'])
check('raw-pin-provenance regression 0', solve(dict(base, **({'raw_origin':'b','pin_origin':'a'}))), ['raw-pin-provenance'])
check('raw-pin-provenance regression 1', solve(dict(base, **({'raw_origin':N+1,'pin_origin':N}))), ['raw-pin-provenance'])
check('unchecked-pin-proof regression 0', solve(dict(base, **({'unchecked_construct':True}))), ['unchecked-pin-proof'])
check('unchecked-pin-proof regression 1', solve(dict(base, **({'unchecked_construct':True,'frame_generation':N,'pin_generation':N}))), ['unchecked-pin-proof'])
check('pin-relocation regression 0', solve(dict(base, **({'pin_generation':N,'frame_generation':N+1}))), ['pin-relocation'])
check('pin-relocation regression 1', solve(dict(base, **({'pin_generation':N+1,'frame_generation':N+2}))), ['pin-relocation'])
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
pinned-move regression 0['pinned-move']['pinned-move']Passed
pinned-move regression 1['pinned-move']['pinned-move']Passed
structural-projection regression 0['structural-projection']['structural-projection']Passed
structural-projection regression 1['structural-projection']['structural-projection']Passed
unpinned-field-move regression 0['unpinned-field-move']['unpinned-field-move']Passed
unpinned-field-move regression 1['unpinned-field-move']['unpinned-field-move']Passed
pin-replace regression 0[]['pin-replace']Failed
pin-replace regression 1[]['pin-replace']Failed
pinned-destructor regression 0['pinned-destructor']['pinned-destructor']Passed
pinned-destructor regression 1['pinned-destructor']['pinned-destructor']Passed
packed-pin regression 0['packed-pin']['packed-pin']Passed
packed-pin regression 1['packed-pin']['packed-pin']Passed
shared-pin-uniqueness regression 0['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
shared-pin-uniqueness regression 1['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
raw-pin-provenance regression 0['raw-pin-provenance']['raw-pin-provenance']Passed
raw-pin-provenance regression 1['raw-pin-provenance']['raw-pin-provenance']Passed
unchecked-pin-proof regression 0['unchecked-pin-proof']['unchecked-pin-proof']Passed
unchecked-pin-proof regression 1['unchecked-pin-proof']['unchecked-pin-proof']Passed
pin-relocation regression 0['pin-relocation']['pin-relocation']Passed
pin-relocation regression 1['pin-relocation']['pin-relocation']Passed

SHA-256 / df2cbb98350afce42eba172205b3e7fd290448486a83dc1f21eefd8a1f407d35

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['pinned'] and not d['unpin'] and bool(d['moves']): errors.append('pinned-move')
    if not set(d['projected'])<=set(d['structural']): errors.append('structural-projection')
    if bool(set(d['unpin_fields'])&set(d['blocked_fields'])): errors.append('unpinned-field-move')
    if d['pinned'] and not d['unpin'] and d['replace']: errors.append('pin-replace')
    if d['pinned'] and d['destructor_move']: errors.append('pinned-destructor')
    if bool(set(d['projected'])&set(d['packed_fields'])): errors.append('packed-pin')
    if d['source_shared'] and d['unique_projection']: errors.append('shared-pin-uniqueness')
    if d['raw_origin']!=d['pin_origin']: errors.append('raw-pin-provenance')
    if d['unchecked_construct'] and not d['proof']: errors.append('unchecked-pin-proof')
    if d['pin_generation']!=d['frame_generation']: errors.append('pin-relocation')
    return errors
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
base={'pinned': False, 'unpin': True, 'moves': [], 'projected': [], 'structural': [], 'unpin_fields': [], 'blocked_fields': [], 'replace': False, 'destructor_move': False, 'packed_fields': [], 'source_shared': False, 'unique_projection': False, 'raw_origin': None, 'pin_origin': None, 'unchecked_construct': False, 'proof': False, 'pin_generation': 0, 'frame_generation': 0}
check('well formed empty obligations',solve(base),[])
check('pinned-move regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'moves':['x']}))), ['pinned-move'])
check('pinned-move regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'moves':[N]}))), ['pinned-move'])
check('structural-projection regression 0', solve(dict(base, **({'projected':['a','b'],'structural':['a']}))), ['structural-projection'])
check('structural-projection regression 1', solve(dict(base, **({'projected':[N,N+1],'structural':[N]}))), ['structural-projection'])
check('unpinned-field-move regression 0', solve(dict(base, **({'unpin_fields':['a'],'blocked_fields':['a']}))), ['unpinned-field-move'])
check('unpinned-field-move regression 1', solve(dict(base, **({'unpin_fields':[N],'blocked_fields':[N]}))), ['unpinned-field-move'])
check('pin-replace regression 0', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True}))), ['pin-replace'])
check('pin-replace regression 1', solve(dict(base, **({'pinned':True,'unpin':False,'replace':True,'frame_generation':N,'pin_generation':N}))), ['pin-replace'])
check('pinned-destructor regression 0', solve(dict(base, **({'pinned':True,'destructor_move':True}))), ['pinned-destructor'])
check('pinned-destructor regression 1', solve(dict(base, **({'pinned':True,'destructor_move':True,'frame_generation':N,'pin_generation':N}))), ['pinned-destructor'])
check('packed-pin regression 0', solve(dict(base, **({'projected':['a'],'structural':['a'],'packed_fields':['a']}))), ['packed-pin'])
check('packed-pin regression 1', solve(dict(base, **({'projected':[N],'structural':[N],'packed_fields':[N]}))), ['packed-pin'])
check('shared-pin-uniqueness regression 0', solve(dict(base, **({'source_shared':True,'unique_projection':True}))), ['shared-pin-uniqueness'])
check('shared-pin-uniqueness regression 1', solve(dict(base, **({'source_shared':True,'unique_projection':True,'frame_generation':N,'pin_generation':N}))), ['shared-pin-uniqueness'])
check('raw-pin-provenance regression 0', solve(dict(base, **({'raw_origin':'b','pin_origin':'a'}))), ['raw-pin-provenance'])
check('raw-pin-provenance regression 1', solve(dict(base, **({'raw_origin':N+1,'pin_origin':N}))), ['raw-pin-provenance'])
check('unchecked-pin-proof regression 0', solve(dict(base, **({'unchecked_construct':True}))), ['unchecked-pin-proof'])
check('unchecked-pin-proof regression 1', solve(dict(base, **({'unchecked_construct':True,'frame_generation':N,'pin_generation':N}))), ['unchecked-pin-proof'])
check('pin-relocation regression 0', solve(dict(base, **({'pin_generation':N,'frame_generation':N+1}))), ['pin-relocation'])
check('pin-relocation regression 1', solve(dict(base, **({'pin_generation':N+1,'frame_generation':N+2}))), ['pin-relocation'])
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
pinned-move regression 0['pinned-move']['pinned-move']Passed
pinned-move regression 1['pinned-move']['pinned-move']Passed
structural-projection regression 0['structural-projection']['structural-projection']Passed
structural-projection regression 1['structural-projection']['structural-projection']Passed
unpinned-field-move regression 0['unpinned-field-move']['unpinned-field-move']Passed
unpinned-field-move regression 1['unpinned-field-move']['unpinned-field-move']Passed
pin-replace regression 0['pin-replace']['pin-replace']Passed
pin-replace regression 1['pin-replace']['pin-replace']Passed
pinned-destructor regression 0['pinned-destructor']['pinned-destructor']Passed
pinned-destructor regression 1['pinned-destructor']['pinned-destructor']Passed
packed-pin regression 0['packed-pin']['packed-pin']Passed
packed-pin regression 1['packed-pin']['packed-pin']Passed
shared-pin-uniqueness regression 0['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
shared-pin-uniqueness regression 1['shared-pin-uniqueness']['shared-pin-uniqueness']Passed
raw-pin-provenance regression 0['raw-pin-provenance']['raw-pin-provenance']Passed
raw-pin-provenance regression 1['raw-pin-provenance']['raw-pin-provenance']Passed
unchecked-pin-proof regression 0['unchecked-pin-proof']['unchecked-pin-proof']Passed
unchecked-pin-proof regression 1['unchecked-pin-proof']['unchecked-pin-proof']Passed
pin-relocation regression 0['pin-relocation']['pin-relocation']Passed
pin-relocation regression 1['pin-relocation']['pin-relocation']Passed

SHA-256 / feb6dc98fc5078330de7d643e94e4e47ac55b1f69b06a7b68bb0e0df55c1a41a

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

Case digest / 7c6c9bcf792928d30b6c6e805b1dde80789cb9453462001b158e7a9f12b39a33