Skip to content
Closed
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
8a72058
chore: add test for std refcell
Stevengre Oct 29, 2025
9f82eec
chore: add simple test for one struct casting
Stevengre Oct 30, 2025
c2d6862
chore: update state without thunk and any modification
Stevengre Oct 30, 2025
28cf9d5
feat: support UnsafeCell cast to Int
Stevengre Oct 30, 2025
93cad6f
chore: new passed prove-rs/local-raw-fail.rs test
Stevengre Oct 30, 2025
fa24d9b
fix: closure_access_struct failure
Stevengre Oct 30, 2025
ede664c
chore: make format
Stevengre Oct 30, 2025
55237eb
chore: remove passed test expected
Stevengre Oct 30, 2025
21f5034
chore: update expected state
Stevengre Oct 30, 2025
537b584
chore: update test pass status
Stevengre Oct 30, 2025
c525218
chore: update test pass status
Stevengre Oct 30, 2025
f270fe8
chore: add more test for the semantics
Stevengre Oct 31, 2025
c25f259
chore: update test_integration.py
Stevengre Oct 31, 2025
2093f58
feat: support reverse transparent struct cast
Stevengre Nov 1, 2025
a313ead
feat: refine transparent alignment handling
Stevengre Nov 3, 2025
1057a44
update expected output
Stevengre Nov 3, 2025
d3d93ca
feat: solve interior-mut3-fail.rs
Stevengre Nov 4, 2025
8d95126
feat: provide more information for functions without body
Stevengre Nov 4, 2025
46e791a
feat(not-ready)
Stevengre Nov 4, 2025
4b3ba64
chore: interior-mut shouldn't fail with this pr
Stevengre Nov 4, 2025
e319042
chore: add comments
Stevengre Nov 4, 2025
96dc111
feat: support ZSTs
Stevengre Nov 4, 2025
e4b482c
chore: interior-mut3 should pass
Stevengre Nov 5, 2025
430dd93
fix: adjust stack projection writes
Stevengre Nov 5, 2025
6cb7e3f
feat: support cast from bytes to int
Stevengre Nov 5, 2025
e5f30b7
feat: support ref borrow (need to optimize)
Stevengre Nov 5, 2025
0a78bae
feat: support cast from int to bytes
Stevengre Nov 5, 2025
d0c1793
restore stable-mir-json
Stevengre Nov 5, 2025
08389d0
chore: format
Stevengre Nov 5, 2025
2e1aeb1
feat: add #withPointerOffset to support projections' pointer offset
Stevengre Nov 5, 2025
1b24944
feat: enhance interior mutability handling in projections
Stevengre Nov 5, 2025
5ca54b5
refactor: remove unused NormalSym population logic in _functions
Stevengre Nov 5, 2025
4683341
feat: simplify borrow cell increment and decrement logic for interior…
Stevengre Nov 5, 2025
a8b3258
feat: add handling for pointer realignment across transparent wrapper…
Stevengre Nov 5, 2025
f1c3005
feat: initialize zero-sized locals for borrowing to ensure projection…
Stevengre Nov 5, 2025
d94197b
feat: streamline alignment rule for struct types in #alignOf function
Stevengre Nov 5, 2025
d45a24a
feat: update expected output for pointer cast length test and symboli…
Stevengre Nov 5, 2025
69a4efd
feat: add comment for pointer transmutation test and correctness check
Stevengre Nov 5, 2025
eb83742
feat: add static array checks for transmute operations in MIR execution
Stevengre Nov 5, 2025
b13b312
feat: refactor type identification for Ref and RefMut in type metadata
Stevengre Nov 5, 2025
d3b81e1
feat: update expected step count in crate2::test_crate1_with test
Stevengre Nov 5, 2025
716dc16
feat: refine drop semantics and enhance comments for clarity
Stevengre Nov 5, 2025
3450bc8
feat: enhance Drop terminator documentation and clarify borrow-aware …
Stevengre Nov 5, 2025
1efd5f7
feat: update expected step count in crate2::main.expected test
Stevengre Nov 5, 2025
cd57064
feat: enhance drop semantics to support general drops and improve bor…
Stevengre Nov 6, 2025
0a16989
feat: enhance borrow reference handling and clarify aggregate process…
Stevengre Nov 6, 2025
0b07a30
Update kmir/src/kmir/kdist/mir-semantics/kmir.md
Stevengre Nov 6, 2025
d57f4f3
Update kmir/src/kmir/kdist/mir-semantics/kmir.md
Stevengre Nov 6, 2025
541edd4
feat: update expected step count in crate2::test_crate1_with.expected
Stevengre Nov 6, 2025
193bef5
chore: update expected output
Stevengre Nov 6, 2025
8358db0
test: ensure interior mut refcell updates mint and account data
Stevengre Nov 6, 2025
3b3ef6a
docs(rt): Clarify zero sized type limitations
Stevengre Nov 6, 2025
9cc3eaf
moved to "jh/int-bytes-cast"
Stevengre Nov 6, 2025
8a77758
move to `jh/correct-offset`
Stevengre Nov 6, 2025
8e75511
moved to `jh/zero-sized`
Stevengre Nov 6, 2025
4f9fcd9
moved to `jh/interior-mut`
Stevengre Nov 6, 2025
83c924c
moved to `jh/zero-sized`
Stevengre Nov 6, 2025
54ceab5
chore: make ci fail faster
Stevengre Nov 7, 2025
00e2df2
chore: moved to jh/align-transparent-place
Stevengre Nov 7, 2025
55f9281
chore: moved to jh/pointer2int
Stevengre Nov 7, 2025
5c6128e
chore: moved to jh/delete-doc
Stevengre Nov 7, 2025
61c8c69
chore: remove empty lines
Stevengre Nov 7, 2025
8cc88c4
chore: move to jh/align-transparent-place
Stevengre Nov 7, 2025
82392e7
chore: move to jh/align-transparent-place
Stevengre Nov 7, 2025
cca1452
chore: move to jh/align-transparent-place
Stevengre Nov 7, 2025
76a081e
chore: move to jh/zero-sized-decode
Stevengre Nov 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 151 additions & 2 deletions kmir/src/kmir/kdist/mir-semantics/kmir.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,162 @@ This does not sacrifice unsoundness as we would not eliminate any assertion fail
Other terminators that matter at the MIR level "Runtime" are `Drop` and `Unreachable`.
Drops are elaborated to Noops but still define the continuing control flow. Unreachable terminators lead to a program error.

#### Drop Terminator

The `Drop` terminator traverses the target place, materialises its value and type information, and then resumes execution at the successor block once the type-directed drop handler has run.

#### Borrow-Aware Drops

Our runtime model tracks RefCell borrow counts for smart-pointer types. Dropping `RefMut<T>` releases the unique borrow by incrementing the cell, while dropping `Ref<T>` decrements the shared borrow count. The helper rules below normalise pointer shapes and apply those updates across the stack.

- Detect `RefMut<T>` / `Ref<T>` via `#isRefMutTy` and `#isRefTy`, which presently match the canonical names that contain `"RefMut<"` or `"Ref<"`.
- Extract projection data so that borrow cells can be reached regardless of pointer shape or stack depth.
- Update the borrow cell using `#incCellBorrow` for mutable borrows and `#decCellBorrow` for shared borrows; the cell is represented as a signed 64-bit integer (`rt/data.md`).
- The model does not assert that the borrow cell currently equals `-1`; repeated drops therefore leave the configuration unchanged.

```k
rule [termDrop]: <k> #execTerminator(terminator(terminatorKindDrop(_PLACE, TARGET, _UNWIND), _SPAN))
// TODO: support general drops (not specifically Ref/RefMut)
rule [termDrop]:
<k> #execTerminator(terminator(terminatorKindDrop(place(local(I), PROJS), TARGET, _UNWIND), _SPAN))
=>
#execBlockIdx(TARGET)
#applyDrop(
operandMove(place(local(I), PROJS)),
getTyOf(tyOfLocal(getLocal(LOCALS, I)), PROJS)
) ~> #execBlockIdx(TARGET)
...
</k>
<locals> LOCALS </locals>
requires 0 <=Int I
andBool I <Int size(LOCALS)
andBool isTypedLocal(LOCALS[I])
[preserves-definedness] // valid local index checked

syntax KItem ::= #applyDrop ( Evaluation , MaybeTy ) [strict(1)]
// std::cell::Ref/RefMut aggregates carry the BorrowRef helper (independent of `T`) in slot 1;
rule <k> #applyDrop(Aggregate(_, ARGS), MTY)
=> #releaseBorrowRef(getValue(ARGS, 1), #isRefMutTy(#lookupMaybeTy(MTY)))
...
</k>
requires 1 <Int size(ARGS)
andBool (#isRefMutTy(#lookupMaybeTy(MTY)) orBool #isRefTy(#lookupMaybeTy(MTY)))
rule <k> #applyDrop(_:Value, MTY) => .K ... </k>
requires notBool #isRefMutTy(#lookupMaybeTy(MTY))
andBool notBool #isRefTy(#lookupMaybeTy(MTY))

syntax Bool ::= #isRefMutTy ( TypeInfo ) [function, total]
rule #isRefMutTy(typeInfoStructType(NAME:String, _, _, _))
=> findString(NAME, "RefMut<", 0) =/=Int -1
rule #isRefMutTy(_) => false [owise]

syntax Bool ::= #isRefTy ( TypeInfo ) [function, total]
rule #isRefTy(typeInfoStructType(NAME:String, _, _, _))
=> findString(NAME, "Ref<", 0) =/=Int -1
andBool findString(NAME, "RefMut<", 0) ==Int -1
rule #isRefTy(_) => false [owise]

// Helper to release borrow reference; Bool indicates mutability
syntax KItem ::= #releaseBorrowRef(Value, Bool)

// Strip tuple/struct wrappers so the borrow cell pointer can be normalised.
rule #releaseBorrowRef(Aggregate(_, ListItem(PTR) _), IS_MUT)
=> #releaseBorrowRef(PTR, IS_MUT)

// Turn References into PtrLocal so projection traversal can reach the borrow cell.
rule #releaseBorrowRef(Reference(OFFSET, PLACE, MUT, META), IS_MUT)
=> #releaseBorrowRef(PtrLocal(OFFSET, PLACE, MUT, META), IS_MUT)

// Stack height 0: borrow cell lives in the current frame, adjust projections (respecting pointer metadata).
rule <k> #releaseBorrowRef(PtrLocal(0, place(local(J), PROJS), _, metadata(_SIZE, PTR_OFFSET, ORIGIN_SIZE)), IS_MUT)
=>
#traverseProjection(
toLocal(J),
getValue(LOCALS, J),
#withPointerOffset(PROJS, PTR_OFFSET, ORIGIN_SIZE),
.Contexts
)
~> #readProjection(false)
~> #applyBorrowCellLocal(J, #withPointerOffset(PROJS, PTR_OFFSET, ORIGIN_SIZE), IS_MUT)
...
</k>
<locals> LOCALS </locals>
requires 0 <=Int J
andBool J <Int size(LOCALS)
andBool isTypedValue(LOCALS[J])
[preserves-definedness]

// Non-zero stack height: borrow cell resides in an ancestor frame, so traverse via `toStack`.
rule <k> #releaseBorrowRef(PtrLocal(OFFSET, place(local(J), PROJS), _, metadata(_SIZE, PTR_OFFSET, ORIGIN_SIZE)), IS_MUT)
=>
#traverseProjection(
toStack(OFFSET, local(J)),
#localFromFrame({STACK[OFFSET -Int 1]}:>StackFrame, local(J), OFFSET),
#withPointerOffset(PROJS, PTR_OFFSET, ORIGIN_SIZE),
.Contexts
)
~> #readProjection(false)
~> #applyBorrowCellStack(OFFSET, J, #withPointerOffset(PROJS, PTR_OFFSET, ORIGIN_SIZE), IS_MUT)
...
</k>
<stack> STACK </stack>
requires 0 <Int OFFSET
andBool OFFSET <=Int size(STACK)
andBool isStackFrame(STACK[OFFSET -Int 1])
[preserves-definedness]

// If the value shape does not match the std Ref/RefMut layout (e.g. custom wrappers), bail out without touching memory.
rule #releaseBorrowRef(_, _) => .K [owise]

syntax ProjectionElems ::= #withPointerOffset(ProjectionElems, Int, MetadataSize) [function, total]
rule #withPointerOffset(PROJS, PTR_OFFSET, ORIGIN_SIZE)
=> appendP(PROJS, PointerOffset(PTR_OFFSET, originSize(ORIGIN_SIZE)))
requires PTR_OFFSET =/=Int 0
rule #withPointerOffset(PROJS, _PTR_OFFSET, _ORIGIN_SIZE) => PROJS [owise]

syntax KItem ::= #applyBorrowCellLocal(Int, ProjectionElems, Bool)
| #applyBorrowCellStack(Int, Int, ProjectionElems, Bool)

// Write the adjusted borrow count back into the current frame's cell.
rule <k> CELL:Value ~> #applyBorrowCellLocal(J, PROJS, IS_MUT)
=>
#setLocalValue(
place(local(J), PROJS),
#if IS_MUT
#then #incCellBorrow(CELL)
#else #decCellBorrow(CELL)
#fi
)
...
</k>
rule #applyBorrowCellLocal(_, _, _) => .K [owise]

// Same as above, but for borrow cells located in ancestor stack frames.
rule <k> CELL:Value ~> #applyBorrowCellStack(OFFSET, J, PROJS, IS_MUT)
=>
#traverseProjection(
toStack(OFFSET, local(J)),
#localFromFrame({STACK[OFFSET -Int 1]}:>StackFrame, local(J), OFFSET),
PROJS,
.Contexts
)
~> #writeProjection(
#if IS_MUT
#then #incCellBorrow(CELL)
#else #decCellBorrow(CELL)
#fi
)
...
</k>
<stack> STACK </stack>
requires 0 <Int OFFSET
andBool OFFSET <=Int size(STACK)
andBool isStackFrame(STACK[OFFSET -Int 1])
[preserves-definedness]
rule #applyBorrowCellStack(_, _, _, _) => .K [owise]
```

#### Unreachable Terminator

```k
syntax MIRError ::= "ReachedUnreachable"

rule [termUnreachable]: <k> #execTerminator(terminator(terminatorKindUnreachable, _SPAN))
Expand Down
Loading
Loading