From 0d8fa91f8b9f168f23ccb245becdcdef11ecd576 Mon Sep 17 00:00:00 2001 From: Stevengre Date: Tue, 19 Aug 2025 11:18:40 +0800 Subject: [PATCH 1/6] Update .gitignore to include .DS_Store and proof/ directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c92371491..c20473e33 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ __pycache__/ /deps/.stable-mir-json /.vscode/ kmir/src/tests/integration/data/**/target -.DS_Store \ No newline at end of file +.DS_Store +proof/ \ No newline at end of file From 183e69ead010ff7338f516a3a3c62fa2ef69618a Mon Sep 17 00:00:00 2001 From: Stevengre Date: Tue, 19 Aug 2025 11:19:07 +0800 Subject: [PATCH 2/6] Add test documentation for `thunk_decode_constant` and example usage - Created `README.md` to document how to reproduce issues with `entrypoint::test_process_initialize_multisig`. - Added `thunk_decode_constant.md` detailing the steps and MIR statements involved in the decoding process. - Introduced `thunk_decode_constant.rs` as a test case demonstrating the expected behavior of dereferencing a struct field. --- tests/README.md | 11 ++ tests/thuck_decode_constant.md | 243 +++++++++++++++++++++++++++++++++ tests/thuck_decode_constant.rs | 17 +++ 3 files changed, 271 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/thuck_decode_constant.md create mode 100644 tests/thuck_decode_constant.rs diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..32a072303 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,11 @@ +### Reproduce stuck in `entrypoint::test_process_initialize_multisig` + +``` +#traverseProjection ( toLocal ( 2 ) , thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 98 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 500125 ) , typeInfoRefType ( ty ( 500016 ) ) ) ) , projectionElemDeref .ProjectionElems , .Contexts ) +``` + +Can be reproduced through `thunk_decode_constant.rs`, see details in `thunk_decode_constant.md` + +``` +#traverseProjection ( toLocal ( 8 ) , thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) , projectionElemDeref .ProjectionElems , .Contexts ) +``` \ No newline at end of file diff --git a/tests/thuck_decode_constant.md b/tests/thuck_decode_constant.md new file mode 100644 index 000000000..99326f0e6 --- /dev/null +++ b/tests/thuck_decode_constant.md @@ -0,0 +1,243 @@ + +┌─ 1 (root, init) +│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC +│ span: src/rust/library/std/src/rt.rs:194 +│ +│ (10 steps) +├─ 3 +│ operandConstant ( constOperand ( ... span: span ( 91 ) , userTy: noUserTypeAnnot +│ function: main +│ span: perties/mir-semantics/deref.rs:3 +│ +│ (10 steps) +├─ 4 +│ rvalueRef ( region ( ... kind: regionKindReErased ) , borrowKindShared , place ( +│ function: main +│ span: perties/mir-semantics/deref.rs:10 +│ +│ (10 steps) +├─ 5 +│ #traverseProjection ( toLocal ( 2 ) , Reference ( 0 , place ( ... local: local ( +│ function: main +│ span: library/core/src/macros/mod.rs:44 +│ +│ (10 steps) +├─ 6 +│ #traverseProjection ( toLocal ( 3 ) , Integer ( 42 , 32 , true ) , .ProjectionEl +│ function: main +│ span: library/core/src/macros/mod.rs:44 +│ +│ (10 steps) +├─ 7 +│ thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00 +│ function: main +│ span: library/core/src/macros/mod.rs:44 +│ +│ (10 steps) +├─ 8 +│ #traverseProjection ( toLocal ( 5 ) , Reference ( 0 , place ( ... local: local ( +│ function: main +│ span: library/core/src/macros/mod.rs:45 +│ +│ (10 steps) +├─ 9 +│ ListItem (Reference ( 0 , place ( ... local: local ( 3 ) , projection: .Projecti +│ function: main +│ span: library/core/src/macros/mod.rs:45 +│ +│ (10 steps) +├─ 10 +│ Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) +│ function: main +│ span: library/core/src/macros/mod.rs:45 +│ +│ (10 steps) +├─ 11 +│ #setLocalValue ( place ( ... local: local ( 8 ) , projection: .ProjectionElems ) +│ function: main +│ span: library/core/src/macros/mod.rs:46 +│ +│ (10 steps) +├─ 12 +│ #setLocalValue ( place ( ... local: local ( 10 ) , projection: .ProjectionElems +│ function: main +│ span: library/core/src/macros/mod.rs:46 +│ +│ (6 steps) +└─ 13 (stuck, leaf) + #traverseProjection ( toLocal ( 8 ) , thunk ( #decodeConstant ( constantKindAllo + function: main + span: library/core/src/macros/mod.rs:46 + + +┌─ 2 (root, leaf, target, terminal) +│ #EndProgram ~> .K + + +Node 11: + + + + + #setLocalValue ( place ( ... local: local ( 8 ) , projection: .ProjectionElems ) , thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) ) + ~> #execStmts ( statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 10 ) , projection: .ProjectionElems ) , rvalue: rvalueUse ( operandCopy ( place ( ... local: local ( 7 ) , projection: projectionElemDeref .ProjectionElems ) ) ) ) , span: span ( 100 ) ) statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 11 ) , projection: .ProjectionElems ) , rvalue: rvalueUse ( operandCopy ( place ( ... local: local ( 8 ) , projection: projectionElemDeref .ProjectionElems ) ) ) ) , span: span ( 101 ) ) statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 9 ) , projection: .ProjectionElems ) , rvalue: rvalueBinaryOp ( binOpEq , operandMove ( place ( ... local: local ( 10 ) , projection: .ProjectionElems ) ) , operandMove ( place ( ... local: local ( 11 ) , projection: .ProjectionElems ) ) ) ) , span: span ( 90 ) ) .Statements ) + ~> #execTerminator ( terminator ( ... kind: terminatorKindSwitchInt ( ... discr: operandMove ( place ( ... local: local ( 9 ) , projection: .ProjectionElems ) ) , targets: switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 2 ) ) .Branches , otherwise: basicBlockIdx ( 1 ) ) ) , span: span ( 90 ) ) ) + + + ty ( -1 ) + + + + place ( ... local: local ( 0 ) , projection: .ProjectionElems ) + + + noBasicBlockIdx + + + unwindActionContinue + + + ListItem (newLocal ( ty ( 1 ) , mutabilityMut )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Integer ( 42 , 32 , true )) + ) , ty ( 42 ) , mutabilityNot )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 43 ) , mutabilityNot )) + ListItem (typedValue ( Integer ( 42 , 32 , true ) , ty ( 16 ) , mutabilityNot )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata )) + ListItem (thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) )) + ) , ty ( 44 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 25 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 25 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 38 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 37 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 39 ) , mutabilityMut )) + + ... + + + ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) + )) + + ... + + ... + + + + +Node 12: + + + + + #setLocalValue ( place ( ... local: local ( 10 ) , projection: .ProjectionElems ) , Integer ( 42 , 32 , true ) ) + ~> #execStmts ( statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 11 ) , projection: .ProjectionElems ) , rvalue: rvalueUse ( operandCopy ( place ( ... local: local ( 8 ) , projection: projectionElemDeref .ProjectionElems ) ) ) ) , span: span ( 101 ) ) statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 9 ) , projection: .ProjectionElems ) , rvalue: rvalueBinaryOp ( binOpEq , operandMove ( place ( ... local: local ( 10 ) , projection: .ProjectionElems ) ) , operandMove ( place ( ... local: local ( 11 ) , projection: .ProjectionElems ) ) ) ) , span: span ( 90 ) ) .Statements ) + ~> #execTerminator ( terminator ( ... kind: terminatorKindSwitchInt ( ... discr: operandMove ( place ( ... local: local ( 9 ) , projection: .ProjectionElems ) ) , targets: switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 2 ) ) .Branches , otherwise: basicBlockIdx ( 1 ) ) ) , span: span ( 90 ) ) ) + + + ty ( -1 ) + + + + place ( ... local: local ( 0 ) , projection: .ProjectionElems ) + + + noBasicBlockIdx + + + unwindActionContinue + + + ListItem (newLocal ( ty ( 1 ) , mutabilityMut )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Integer ( 42 , 32 , true )) + ) , ty ( 42 ) , mutabilityNot )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 43 ) , mutabilityNot )) + ListItem (typedValue ( Integer ( 42 , 32 , true ) , ty ( 16 ) , mutabilityNot )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata )) + ListItem (thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) )) + ) , ty ( 44 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 25 ) , mutabilityNot )) + ListItem (typedValue ( thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) , ty ( 25 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 38 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 37 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 39 ) , mutabilityMut )) + + ... + + + ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) + )) + + ... + + ... + + + + +Node 13: + + + + + #traverseProjection ( toLocal ( 8 ) , thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) , projectionElemDeref .ProjectionElems , .Contexts ) + ~> #readProjection ( false ) + ~> #freezer#setLocalValue(_,_)_RT-DATA_KItem_Place_Evaluation1_ ( place ( ... local: local ( 11 ) , projection: .ProjectionElems ) ~> .K ) + ~> #execStmts ( statement ( ... kind: statementKindAssign ( ... place: place ( ... local: local ( 9 ) , projection: .ProjectionElems ) , rvalue: rvalueBinaryOp ( binOpEq , operandMove ( place ( ... local: local ( 10 ) , projection: .ProjectionElems ) ) , operandMove ( place ( ... local: local ( 11 ) , projection: .ProjectionElems ) ) ) ) , span: span ( 90 ) ) .Statements ) + ~> #execTerminator ( terminator ( ... kind: terminatorKindSwitchInt ( ... discr: operandMove ( place ( ... local: local ( 9 ) , projection: .ProjectionElems ) ) , targets: switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 2 ) ) .Branches , otherwise: basicBlockIdx ( 1 ) ) ) , span: span ( 90 ) ) ) + + + ty ( -1 ) + + + + place ( ... local: local ( 0 ) , projection: .ProjectionElems ) + + + noBasicBlockIdx + + + unwindActionContinue + + + ListItem (newLocal ( ty ( 1 ) , mutabilityMut )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Integer ( 42 , 32 , true )) + ) , ty ( 42 ) , mutabilityNot )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 43 ) , mutabilityNot )) + ListItem (typedValue ( Integer ( 42 , 32 , true ) , ty ( 16 ) , mutabilityNot )) + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , ListItem (Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata )) + ListItem (thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) )) + ) , ty ( 44 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 25 ) , mutabilityMut )) + ListItem (typedValue ( Reference ( 0 , place ( ... local: local ( 3 ) , projection: .ProjectionElems ) , mutabilityNot , noMetadata ) , ty ( 25 ) , mutabilityNot )) + ListItem (typedValue ( thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) , ty ( 25 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) + ListItem (typedValue ( Integer ( 42 , 32 , true ) , ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 16 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 38 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 37 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 39 ) , mutabilityMut )) + + ... + + + ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) + )) + + ... + + ... + + + + diff --git a/tests/thuck_decode_constant.rs b/tests/thuck_decode_constant.rs new file mode 100644 index 000000000..e29dd1197 --- /dev/null +++ b/tests/thuck_decode_constant.rs @@ -0,0 +1,17 @@ +fn main() { + // Create a struct + let my_struct = MyStruct { value: 42 }; + + // Create a reference + let ref_to_struct = &my_struct; + + // This operation will generate the MIR statement you described: + // Dereference ref_to_struct, then access the .value field + let result = (*ref_to_struct).value; + + assert_eq!(result, 42); +} + +struct MyStruct { + value: i32, +} From 65a29f71f892d45b65d87bdd41d023eaebfdd356 Mon Sep 17 00:00:00 2001 From: Stevengre Date: Tue, 19 Aug 2025 13:16:01 +0800 Subject: [PATCH 3/6] Add mock borrow data unchecked test case - Introduced `mock_borrow_data_unchecked.rs` to simulate account borrowing behavior. - Implemented `MockAccountInfo` struct with methods for unsafe data access. - Added example usage in the main function to demonstrate functionality. - Updated `README.md` to reference the new test case and provide context. --- tests/README.md | 28 +++++++++++- tests/mock_borrow_data_unchecked.rs | 70 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 tests/mock_borrow_data_unchecked.rs diff --git a/tests/README.md b/tests/README.md index 32a072303..e67595b62 100644 --- a/tests/README.md +++ b/tests/README.md @@ -8,4 +8,30 @@ Can be reproduced through `thunk_decode_constant.rs`, see details in `thunk_deco ``` #traverseProjection ( toLocal ( 8 ) , thunk ( #decodeConstant ( constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... provSize: 0 , allocId: allocId ( 0 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty ( 25 ) , typeInfoRefType ( ty ( 16 ) ) ) ) , projectionElemDeref .ProjectionElems , .Contexts ) -``` \ No newline at end of file +``` + +## TypeError: 'NoneType' object is not subscriptable + +mock_borrow_data_unchecked.rs + +``` +INFO 2025-08-19 13:08:34,055 kmir.cargo - Deleted: /Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/tests/mock_borrow_data_unchecked.smir.json +Traceback (most recent call last): + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/.venv/bin/kmir", line 10, in + sys.exit(main()) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/__main__.py", line 451, in main + kmir(sys.argv[1:]) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/__main__.py", line 218, in kmir + _kmir_prove_rs(opts) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/__main__.py", line 66, in _kmir_prove_rs + proof = kmir.prove_rs(opts) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/kmir.py", line 186, in prove_rs + smir_info = smir_info.reduce_to(opts.start_symbol) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/smir.py", line 156, in reduce_to + _LOGGER.debug(f'Reducing items, starting at {start_ty}. Call Edges {self.call_edges}') + File "/opt/homebrew/Cellar/python@3.10/3.10.17/Frameworks/Python.framework/Versions/3.10/lib/python3.10/functools.py", line 981, in __get__ + val = self.func(instance) + File "/Users/steven/Desktop/projs/solana-token/p-token/test-properties/mir-semantics/kmir/src/kmir/smir.py", line 183, in call_edges + for b in item['mono_item_kind']['MonoItemFn']['body']['blocks'] +TypeError: 'NoneType' object is not subscriptable +``` diff --git a/tests/mock_borrow_data_unchecked.rs b/tests/mock_borrow_data_unchecked.rs new file mode 100644 index 000000000..aa58398b1 --- /dev/null +++ b/tests/mock_borrow_data_unchecked.rs @@ -0,0 +1,70 @@ +use std::ptr; + +/// Simplified Account struct, simulating the original Account structure +#[repr(C)] +pub struct Account { + pub data_len: u64, + // Other fields omitted, only data_len is kept +} + +/// Simplified MockAccountInfo, maintaining original complexity +pub struct MockAccountInfo { + raw: *mut Account, + data: Vec, // Where actual data is stored +} + +impl MockAccountInfo { + /// Create a new MockAccountInfo + pub fn new(data: Vec) -> Self { + let mut account = Account { + data_len: data.len() as u64, + }; + + Self { + raw: &mut account as *mut Account, + data, + } + } + + /// Get data pointer, simulating the original data_ptr method + pub unsafe fn data_ptr(&self) -> *mut u8 { + unsafe { + (self.raw as *const _ as *mut u8).add(std::mem::size_of::()) + } + } + + /// Get data length, simulating the original data_len method + pub unsafe fn data_len(&self) -> usize { + unsafe { (*self.raw).data_len as usize } + } + + /// Maintain original complexity for borrow_data_unchecked + /// + /// # Safety + /// + /// This method is unsafe because it does not return a `Ref`, thus leaving the borrow + /// flag untouched. Useful when an instruction has verified non-duplicate accounts. + #[inline(always)] + pub unsafe fn borrow_data_unchecked(&self) -> &[u8] { + core::slice::from_raw_parts(self.data_ptr(), self.data_len()) + } +} + +fn main() { + // Create test data + let test_data = vec![1, 2, 3, 4, 5]; + + // Create mock AccountInfo + let mock_account = MockAccountInfo::new(test_data.clone()); + + // Call borrow_data_unchecked (requires unsafe block) + let borrowed_data = unsafe { mock_account.borrow_data_unchecked() }; + + // Print results + // println!("Borrowed data: {:?}", borrowed_data); + // println!("Data length: {}", borrowed_data.len()); + + // Verify data is correct + // assert_eq!(borrowed_data, &[1, 2, 3, 4, 5]); + // println!("Verification passed!"); +} \ No newline at end of file From ea766a74fb29c313b5f30d501f4ceb699be83fd0 Mon Sep 17 00:00:00 2001 From: Stevengre Date: Tue, 19 Aug 2025 13:46:31 +0800 Subject: [PATCH 4/6] Add mock borrow data unchecked test case for account handling - Introduced `mock_borrow_data_unchecked_failed.rs` to simulate scenarios where borrowing data from accounts fails. - Implemented `Account` and `AccountInfo` structs with methods for unsafe data access. - Added a test function to validate dereferencing behavior. - Updated `README.md` to reference the new test case and provide context on the encountered issues. --- tests/README.md | 4 + tests/mock_borrow_data_unchecked_failed.md | 1061 ++++++++++++++++++++ tests/mock_borrow_data_unchecked_failed.rs | 74 ++ 3 files changed, 1139 insertions(+) create mode 100644 tests/mock_borrow_data_unchecked_failed.md create mode 100644 tests/mock_borrow_data_unchecked_failed.rs diff --git a/tests/README.md b/tests/README.md index e67595b62..d128cac10 100644 --- a/tests/README.md +++ b/tests/README.md @@ -35,3 +35,7 @@ Traceback (most recent call last): for b in item['mono_item_kind']['MonoItemFn']['body']['blocks'] TypeError: 'NoneType' object is not subscriptable ``` + +## Mock borrow_data_unchecked but encountered different stuck + +`mock_borrow_data_unchecked_failed.rs` \ No newline at end of file diff --git a/tests/mock_borrow_data_unchecked_failed.md b/tests/mock_borrow_data_unchecked_failed.md new file mode 100644 index 000000000..e2d53eac6 --- /dev/null +++ b/tests/mock_borrow_data_unchecked_failed.md @@ -0,0 +1,1061 @@ + +┌─ 1 (root, init) +│ +│ +│ +│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( -1 ) , id: mirConstId ( 0 ) ) ) ) , args: .Operands , destination: place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) +│ +│ +│ +│ ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ +│ ... +│ +│ +│ .List +│ +│ ... +│ +│ ... +│ +│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC +│ span: library/core/src/slice/iter.rs:130 +│ +│ (10 steps) +├─ 3 +│ +│ +│ +│ operandConstant ( constOperand ( ... span: span ( 869 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x00" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 1 ) , mutability: mutabilityMut ) ) , ty: ty ( 16 ) , id: mirConstId ( 93 ) ) ) ) +│ ~> #freezer#setLocalValue(_,_)_RT-DATA_KItem_Place_Evaluation1_ ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) ~> .K ) +│ ~> #setArgsFromStack ( 2 , operandConstant ( constOperand ( ... span: span ( 870 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"d\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty: ty ( 52 ) , id: mirConstId ( 46 ) ) ) ) .Operands ) +│ ~> #execBlock ( basicBlock ( ... statements: .Statements , terminator: terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 594 ) , userTy: someUserTypeAnnotationIndex ( userTypeAnnotationIndex ( 0 ) ) , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 125 ) , id: mirConstId ( 69 ) ) ) ) , args: operandMove ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) ) operandMove ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 115 ) , id: mirConstId ( 64 ) ) ) ) .Operands , destination: place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwind: unwindActionContinue ) , span: span ( 595 ) ) ) ) +│ +│ +│ ty ( 155 ) +│ +│ +│ +│ ty ( -1 ) +│ +│ +│ place ( ... local: local ( 1 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ operandConstant ( constOperand ( ... span: span ( 869 ) , userTy: noUserTypeAnno +│ function: std::vec::from_elem:: +│ span: s/mir-semantics/tests/deref.rs:44 +│ +│ (10 steps) +├─ 4 +│ +│ +│ +│ #setLocalValue ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) , Integer ( 100 , 64 , false ) ) +│ ~> #setArgsFromStack ( 3 , .Operands ) +│ ~> #execBlock ( basicBlock ( ... statements: .Statements , terminator: terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 594 ) , userTy: someUserTypeAnnotationIndex ( userTypeAnnotationIndex ( 0 ) ) , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 125 ) , id: mirConstId ( 69 ) ) ) ) , args: operandMove ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) ) operandMove ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 115 ) , id: mirConstId ( 64 ) ) ) ) .Operands , destination: place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwind: unwindActionContinue ) , span: span ( 595 ) ) ) ) +│ +│ +│ ty ( 155 ) +│ +│ +│ +│ ty ( -1 ) +│ +│ +│ place ( ... local: local ( 1 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ #setLocalValue ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) +│ function: std::vec::from_elem:: +│ span: t/library/alloc/src/vec/mod.rs:3175 +│ +│ (10 steps) +├─ 5 +│ +│ +│ +│ #setArgFromStack ( 2 , operandMove ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) ) +│ ~> #setArgsFromStack ( 3 , operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 115 ) , id: mirConstId ( 64 ) ) ) ) .Operands ) +│ ~> #execBlock ( basicBlock ( ... statements: .Statements , terminator: terminator ( ... kind: terminatorKindSwitchInt ( ... discr: operandCopy ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) ) , targets: switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) ) .Branches , otherwise: basicBlockIdx ( 2 ) ) ) , span: span ( 659 ) ) ) ) +│ +│ +│ ty ( 125 ) +│ +│ +│ +│ ty ( 155 ) +│ +│ +│ place ( ... local: local ( 0 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 115 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 132 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 13 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 129 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 65 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 64 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( ty ( -1 ) , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 16 ) , mutabilityMut )) +│ ListItem (typedValue ( Integer ( 100 , 64 , false ) , ty ( 52 ) , mutabilityNot )) +│ )) +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ #setArgFromStack ( 2 , operandMove ( place ( ... local: local ( 2 ) , projection +│ function: ::from_elem:: +│ span: no-location:0 +│ +│ (10 steps) +├─ 6 +│ +│ +│ +│ #execBlock ( basicBlock ( ... statements: .Statements , terminator: terminator ( ... kind: terminatorKindSwitchInt ( ... discr: operandCopy ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) ) , targets: switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) ) .Branches , otherwise: basicBlockIdx ( 2 ) ) ) , span: span ( 659 ) ) ) ) ~> .K +│ +│ +│ ty ( 125 ) +│ +│ +│ +│ ty ( 155 ) +│ +│ +│ place ( ... local: local ( 0 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Integer ( 100 , 64 , false ) , ty ( 52 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , .List ) , ty ( 115 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 132 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 13 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 129 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 65 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 64 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( ty ( -1 ) , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 16 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 52 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ #execBlock ( basicBlock ( ... statements: .Statements , terminator: terminator ( +│ function: ::from_elem:: +│ span: lloc/src/vec/spec_from_elem.rs:54 +│ +│ (10 steps) +├─ 7 +│ +│ +│ +│ #execStmts ( statement ( ... kind: statementKindStorageLive ( local ( 4 ) ) , span: span ( 662 ) ) statement ( ... kind: statementKindStorageLive ( local ( 10 ) ) , span: span ( 663 ) ) statement ( ... kind: statementKindStorageLive ( local ( 12 ) ) , span: span ( 663 ) ) statement ( ... kind: statementKindStorageLive ( local ( 13 ) ) , span: span ( 663 ) ) statement ( ... kind: statementKindStorageLive ( local ( 11 ) ) , span: span ( 661 ) ) .Statements ) +│ ~> #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 660 ) , userTy: someUserTypeAnnotationIndex ( userTypeAnnotationIndex ( 0 ) ) , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 126 ) , id: mirConstId ( 70 ) ) ) ) , args: operandCopy ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 1 ) , mutability: mutabilityMut ) ) , ty: ty ( 127 ) , id: mirConstId ( 74 ) ) ) ) operandMove ( place ( ... local: local ( 3 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityNot ) ) , ty: ty ( 131 ) , id: mirConstId ( 75 ) ) ) ) .Operands , destination: place ( ... local: local ( 11 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 4 ) ) , unwind: unwindActionContinue ) , span: span ( 661 ) ) ) +│ +│ +│ ty ( 125 ) +│ +│ +│ +│ ty ( 155 ) +│ +│ +│ place ( ... local: local ( 0 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Integer ( 100 , 64 , false ) , ty ( 52 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , .List ) , ty ( 115 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 132 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 13 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 129 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 65 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 64 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( ty ( -1 ) , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 16 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 52 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ #execStmts ( statement ( ... kind: statementKindStorageLive ( local ( 4 ) ) , sp +│ function: ::from_elem:: +│ span: lloc/src/vec/spec_from_elem.rs:55 +│ +│ (10 steps) +├─ 8 +│ +│ +│ +│ #execStmts ( .Statements ) +│ ~> #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 660 ) , userTy: someUserTypeAnnotationIndex ( userTypeAnnotationIndex ( 0 ) ) , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 126 ) , id: mirConstId ( 70 ) ) ) ) , args: operandCopy ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 1 ) , mutability: mutabilityMut ) ) , ty: ty ( 127 ) , id: mirConstId ( 74 ) ) ) ) operandMove ( place ( ... local: local ( 3 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityNot ) ) , ty: ty ( 131 ) , id: mirConstId ( 75 ) ) ) ) .Operands , destination: place ( ... local: local ( 11 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 4 ) ) , unwind: unwindActionContinue ) , span: span ( 661 ) ) ) +│ +│ +│ ty ( 125 ) +│ +│ +│ +│ ty ( 155 ) +│ +│ +│ place ( ... local: local ( 0 ) , projection: .ProjectionElems ) +│ +│ +│ someBasicBlockIdx ( basicBlockIdx ( 1 ) ) +│ +│ +│ unwindActionContinue +│ +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Integer ( 100 , 64 , false ) , ty ( 52 ) , mutabilityNot )) +│ +│ ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , .List ) , ty ( 115 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 132 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 13 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 129 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 65 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ +│ ListItem (newLocal ( ty ( 64 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) +│ +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ +│ ... +│ +│ +│ ListItem (StackFrame ( ty ( -1 ) , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 16 ) , mutabilityMut )) +│ ListItem (typedValue ( Moved , ty ( 52 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) +│ ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) +│ ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) +│ )) +│ +│ ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) +│ )) +│ +│ ... +│ +│ ... +│ +│ #execStmts ( .Statements ) +~> #execTerminator ( terminator ( ... kind: terminato +│ function: ::from_elem:: +│ span: t/library/alloc/src/raw_vec.rs:448 +│ +│ (1 step) +└─ 9 (stuck, leaf) + + + + #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandConstant ( constOperand ( ... span: span ( 660 ) , userTy: someUserTypeAnnotationIndex ( userTypeAnnotationIndex ( 0 ) ) , const: mirConst ( ... kind: constantKindZeroSized , ty: ty ( 126 ) , id: mirConstId ( 70 ) ) ) ) , args: operandCopy ( place ( ... local: local ( 2 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 1 ) , mutability: mutabilityMut ) ) , ty: ty ( 127 ) , id: mirConstId ( 74 ) ) ) ) operandMove ( place ( ... local: local ( 3 ) , projection: .ProjectionElems ) ) operandConstant ( constOperand ( ... span: span ( 48 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityNot ) ) , ty: ty ( 131 ) , id: mirConstId ( 75 ) ) ) ) .Operands , destination: place ( ... local: local ( 11 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 4 ) ) , unwind: unwindActionContinue ) , span: span ( 661 ) ) ) ~> .K + + + ty ( 125 ) + + + + ty ( 155 ) + + + place ( ... local: local ( 0 ) , projection: .ProjectionElems ) + + + someBasicBlockIdx ( basicBlockIdx ( 1 ) ) + + + unwindActionContinue + + + ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + + ListItem (typedValue ( Integer ( 0 , 8 , false ) , ty ( 16 ) , mutabilityNot )) + + ListItem (typedValue ( Integer ( 100 , 64 , false ) , ty ( 52 ) , mutabilityNot )) + + ListItem (typedValue ( Aggregate ( variantIdx ( 0 ) , .List ) , ty ( 115 ) , mutabilityNot )) + + ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + + ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 132 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 13 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 129 ) , mutabilityNot )) + + ListItem (newLocal ( ty ( 65 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 90 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 118 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 45 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 53 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + + ListItem (newLocal ( ty ( 64 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 119 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 120 ) , mutabilityMut )) + + ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) + + ... + + + ListItem (StackFrame ( ty ( -1 ) , place ( ... local: local ( 1 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 16 ) , mutabilityMut )) + ListItem (typedValue ( Moved , ty ( 52 ) , mutabilityMut )) + )) + + ListItem (StackFrame ( CURRENTFUNC_CELL:Ty , place ( ... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem (newLocal ( ty ( 2 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 117 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 80 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 117 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 163 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 81 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 82 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 5 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 124 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 164 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 161 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 148 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 47 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 3 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 2 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 146 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 52 ) , mutabilityNot )) + ListItem (newLocal ( ty ( 52 ) , mutabilityMut )) + ListItem (newLocal ( ty ( 43 ) , mutabilityMut )) + )) + + ListItem (StackFrame ( CALLER_CELL:Ty , DEST_CELL:Place , TARGET_CELL:MaybeBasicBlockIdx , UNWIND_CELL:UnwindAction , ListItem (newLocal ( ty ( 0 ) , mutabilityNot )) + )) + + ... + + ... + + #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC + function: ::from_elem:: + span: t/library/alloc/src/raw_vec.rs:448 + + +┌─ 2 (root, leaf, target, terminal) +│ +│ +│ +│ #EndProgram ~> .K +│ +│ ... +│ +│ ... +│ +│ #EndProgram ~> .K + + + diff --git a/tests/mock_borrow_data_unchecked_failed.rs b/tests/mock_borrow_data_unchecked_failed.rs new file mode 100644 index 000000000..90c8c43f6 --- /dev/null +++ b/tests/mock_borrow_data_unchecked_failed.rs @@ -0,0 +1,74 @@ +#[repr(C)] +#[derive(Clone, Copy, Default)] +pub(crate) struct Account { + /// Length of the data. Modifiable by programs. + pub(crate) data_len: u64, +} + +#[repr(C)] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AccountInfo { + /// Raw (pointer to) account data. + /// + /// Note that this is a pointer can be shared across multiple `AccountInfo`. + pub(crate) raw: *mut Account, +} + +impl AccountInfo { + #[inline(always)] + pub unsafe fn borrow_data_unchecked(&self) -> &[u8] { + core::slice::from_raw_parts(self.data_ptr(), self.data_len()) + } + + /// Returns the memory address of the account data. + fn data_ptr(&self) -> *mut u8 { + unsafe { (self.raw as *const _ as *mut u8).add(core::mem::size_of::()) } + } + + /// Returns the size of the data in the account. + #[inline(always)] + pub fn data_len(&self) -> usize { + unsafe { (*self.raw).data_len as usize } + } +} + +// Test function for deref functionality +fn test_deref(account: &AccountInfo) { + unsafe { + assert_eq!(account.borrow_data_unchecked(), &[0; 100]); + } +} + +fn main() { + // Create test data with actual data storage + let account_data1 = vec![0u8; 100]; + let account_data2 = vec![0u8; 200]; + let account_data3 = vec![0u8; 300]; + + // Create accounts with data + let account1 = Account { data_len: 100 }; + let account2 = Account { data_len: 200 }; + let account3 = Account { data_len: 300 }; + + // Create a combined structure: Account + data + let mut combined1 = vec![]; + combined1.extend_from_slice(&account1.data_len.to_ne_bytes()); + combined1.extend_from_slice(&account_data1); + + let mut combined2 = vec![]; + combined2.extend_from_slice(&account2.data_len.to_ne_bytes()); + combined2.extend_from_slice(&account_data2); + + let mut combined3 = vec![]; + combined3.extend_from_slice(&account3.data_len.to_ne_bytes()); + combined3.extend_from_slice(&account_data3); + + // Create AccountInfo with pointers to the combined data + let accounts = [ + AccountInfo { raw: combined1.as_mut_ptr() as *mut Account }, + AccountInfo { raw: combined2.as_mut_ptr() as *mut Account }, + AccountInfo { raw: combined3.as_mut_ptr() as *mut Account }, + ]; + + test_deref(&accounts[0]); +} \ No newline at end of file From 2d5bd4d9d4c8f0e43a99a68437ea88b3e4758395 Mon Sep 17 00:00:00 2001 From: Stevengre Date: Wed, 20 Aug 2025 20:41:51 +0800 Subject: [PATCH 5/6] Add tests for `closure` feature in Rust --- tests/closure/closure_array_access.rs | 15 +++ tests/closure/closure_async.rs | 28 +++++ tests/closure/closure_borrow_checker.rs | 16 +++ tests/closure/closure_capture.rs | 12 ++ tests/closure/closure_complex_capture.rs | 151 +++++++++++++++++++++++ tests/closure/closure_concurrency.rs | 122 ++++++++++++++++++ tests/closure/closure_error_handling.rs | 111 +++++++++++++++++ tests/closure/closure_iterators.rs | 82 ++++++++++++ tests/closure/closure_lifetimes.rs | 41 ++++++ tests/closure/closure_move.rs | 15 +++ tests/closure/closure_mut_capture.rs | 17 +++ tests/closure/closure_recursive.rs | 86 +++++++++++++ tests/closure/closure_return.rs | 13 ++ tests/closure/closure_struct_access.rs | 25 ++++ tests/closure/closure_traits.rs | 72 +++++++++++ tests/closure/closure_unsafe.rs | 94 ++++++++++++++ 16 files changed, 900 insertions(+) create mode 100644 tests/closure/closure_array_access.rs create mode 100644 tests/closure/closure_async.rs create mode 100644 tests/closure/closure_borrow_checker.rs create mode 100644 tests/closure/closure_capture.rs create mode 100644 tests/closure/closure_complex_capture.rs create mode 100644 tests/closure/closure_concurrency.rs create mode 100644 tests/closure/closure_error_handling.rs create mode 100644 tests/closure/closure_iterators.rs create mode 100644 tests/closure/closure_lifetimes.rs create mode 100644 tests/closure/closure_move.rs create mode 100644 tests/closure/closure_mut_capture.rs create mode 100644 tests/closure/closure_recursive.rs create mode 100644 tests/closure/closure_return.rs create mode 100644 tests/closure/closure_struct_access.rs create mode 100644 tests/closure/closure_traits.rs create mode 100644 tests/closure/closure_unsafe.rs diff --git a/tests/closure/closure_array_access.rs b/tests/closure/closure_array_access.rs new file mode 100644 index 000000000..b8426791f --- /dev/null +++ b/tests/closure/closure_array_access.rs @@ -0,0 +1,15 @@ +fn main() { + // Simple data structure + let numbers = [10, 20, 30, 40, 50]; + + // Keep closure function and list call style + let get_value = |index: usize| { + numbers[index] + }; + + // Use list call style + let result = get_value(2); + + // Verify result + assert_eq!(result, 30); +} \ No newline at end of file diff --git a/tests/closure/closure_async.rs b/tests/closure/closure_async.rs new file mode 100644 index 000000000..8d54b7d87 --- /dev/null +++ b/tests/closure/closure_async.rs @@ -0,0 +1,28 @@ +// This example demonstrates async closures +// Note: This requires an async runtime like tokio to actually execute + +fn main() { + let numbers = [1, 2, 3, 4, 5]; + + // Async closure that captures by value + let async_process = |index: usize| async move { + // Simulate async operation (e.g., network request, file I/O) + std::thread::sleep(std::time::Duration::from_millis(10)); + numbers[index] * 2 + }; + + // Async closure that captures by reference (requires 'static lifetime) + let async_process_ref = |index: usize| async move { + // This would work if numbers had 'static lifetime + // For demonstration, we'll use a different approach + index * 2 + }; + + // Note: To actually run these async closures, you would need: + // 1. tokio or another async runtime + // 2. #[tokio::main] attribute on main function + // 3. .await calls to execute the futures + + println!("Async closures defined successfully"); + println!("To execute: use tokio::spawn(async_process(2).await)"); +} \ No newline at end of file diff --git a/tests/closure/closure_borrow_checker.rs b/tests/closure/closure_borrow_checker.rs new file mode 100644 index 000000000..24d8f3715 --- /dev/null +++ b/tests/closure/closure_borrow_checker.rs @@ -0,0 +1,16 @@ +fn main() { + let mut data = vec![1, 2, 3, 4, 5]; + + // Test borrow checker + let get_value = |index: usize| { + data[index] + }; + + let result = get_value(2); + assert_eq!(result, 3); + + // Can modify data because closure only borrows + data[2] = 10; + let new_result = get_value(2); + assert_eq!(new_result, 10); +} \ No newline at end of file diff --git a/tests/closure/closure_capture.rs b/tests/closure/closure_capture.rs new file mode 100644 index 000000000..7030f7214 --- /dev/null +++ b/tests/closure/closure_capture.rs @@ -0,0 +1,12 @@ +fn main() { + let multiplier = 5; + let numbers = [1, 2, 3, 4, 5]; + + // Closure capturing external variables + let multiply_by = |x: i32| { + x * multiplier + }; + + let result = multiply_by(numbers[2]); + assert_eq!(result, 15); +} \ No newline at end of file diff --git a/tests/closure/closure_complex_capture.rs b/tests/closure/closure_complex_capture.rs new file mode 100644 index 000000000..f5a49c760 --- /dev/null +++ b/tests/closure/closure_complex_capture.rs @@ -0,0 +1,151 @@ +// Test complex capture patterns + +fn main() { + // Test 1: Partial move - some fields moved, others borrowed + struct Person { + name: String, + age: i32, + scores: Vec, + } + + let person = Person { + name: "Alice".to_string(), + age: 25, + scores: vec![85, 90, 88], + }; + + // Move name and scores, borrow age + let name_and_scores = move || { + (person.name, person.scores) + }; + + let result = name_and_scores(); + assert_eq!(result.0, "Alice"); + assert_eq!(result.1, vec![85, 90, 88]); + + // Test 2: Mixed capture - some by value, some by reference + let mut counter = 0; + let data = vec![1, 2, 3, 4, 5]; + + let mixed_closure = move |index: usize| { + // data is moved into closure + // counter is captured by mutable reference + counter += 1; + data[index] + counter + }; + + // This won't compile because counter is captured by reference + // but data is moved. Let's fix this: + + let mut counter2 = 0; + let data2 = vec![1, 2, 3, 4, 5]; + + let mixed_closure2 = |index: usize| { + counter2 += 1; + data2[index] + counter2 + }; + + let result1 = mixed_closure2(2); + let result2 = mixed_closure2(2); + + assert_eq!(result1, 4); // 3 + 1 + assert_eq!(result2, 5); // 3 + 2 + + // Test 3: Closure capturing different parts of a struct + struct ComplexData { + numbers: Vec, + metadata: String, + flag: bool, + } + + let complex = ComplexData { + numbers: vec![10, 20, 30], + metadata: "test".to_string(), + flag: true, + }; + + // Capture numbers by value, metadata by reference + let numbers_closure = move || { + complex.numbers + }; + + let numbers_result = numbers_closure(); + assert_eq!(numbers_result, vec![10, 20, 30]); + + // Test 4: Closure with conditional capture + let condition = true; + let value1 = vec![1, 2, 3]; + let value2 = vec![4, 5, 6]; + + let conditional_closure = if condition { + move || value1 + } else { + move || value2 + }; + + let conditional_result = conditional_closure(); + assert_eq!(conditional_result, vec![1, 2, 3]); + + // Test 5: Closure capturing enum variants + enum Data { + Numbers(Vec), + Text(String), + } + + let enum_data = Data::Numbers(vec![1, 2, 3]); + + let enum_closure = move || { + match enum_data { + Data::Numbers(nums) => nums, + Data::Text(_) => vec![], + } + }; + + let enum_result = enum_closure(); + assert_eq!(enum_result, vec![1, 2, 3]); + + // Test 6: Closure with nested captures + let outer_data = vec![1, 2, 3]; + let inner_data = vec![4, 5, 6]; + + let nested_closure = move || { + let inner_closure = move |index: usize| { + outer_data[index] + inner_data[index] + }; + inner_closure(0) + }; + + let nested_result = nested_closure(); + assert_eq!(nested_result, 5); // 1 + 4 + + // Test 7: Closure capturing tuple with mixed ownership + let tuple_data = (vec![1, 2, 3], "hello".to_string(), 42); + + let tuple_closure = move |index: usize| { + (tuple_data.0[index], tuple_data.1.clone(), tuple_data.2) + }; + + let tuple_result = tuple_closure(1); + assert_eq!(tuple_result, (2, "hello".to_string(), 42)); + + // Test 8: Closure with reference counting for shared ownership + use std::rc::Rc; + + let shared_data = Rc::new(vec![1, 2, 3, 4, 5]); + + let rc_closure1 = { + let data = Rc::clone(&shared_data); + move |index: usize| data[index] + }; + + let rc_closure2 = { + let data = Rc::clone(&shared_data); + move |index: usize| data[index] * 2 + }; + + let rc_result1 = rc_closure1(2); + let rc_result2 = rc_closure2(2); + + assert_eq!(rc_result1, 3); + assert_eq!(rc_result2, 6); +} diff --git a/tests/closure/closure_concurrency.rs b/tests/closure/closure_concurrency.rs new file mode 100644 index 000000000..e3c71d6c3 --- /dev/null +++ b/tests/closure/closure_concurrency.rs @@ -0,0 +1,122 @@ +// Test closure concurrency and Send/Sync traits + +use std::thread; +use std::sync::{Arc, Mutex}; + +fn main() { + // Test 1: Closure that implements Send (can be moved to another thread) + let data = vec![1, 2, 3, 4, 5]; + let send_closure = move |index: usize| { + data[index] * 2 + }; + + // This closure can be sent to another thread + let handle = thread::spawn(move || { + let result = send_closure(2); + assert_eq!(result, 6); + }); + + handle.join().unwrap(); + + // Test 2: Closure with Arc for shared state + let shared_data = Arc::new(Mutex::new(vec![0, 0, 0, 0, 0])); + let mut handles = vec![]; + + for i in 0..5 { + let data_clone = Arc::clone(&shared_data); + let thread_closure = move || { + let mut data = data_clone.lock().unwrap(); + data[i] = i as i32 * 2; + }; + + let handle = thread::spawn(thread_closure); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + let final_data = shared_data.lock().unwrap(); + assert_eq!(*final_data, vec![0, 2, 4, 6, 8]); + + // Test 3: Closure that captures by value (implements Send) + let numbers = vec![10, 20, 30, 40, 50]; + let sum_closure = move |start: usize, end: usize| { + numbers[start..end].iter().sum::() + }; + + let handle1 = thread::spawn(move || { + let result = sum_closure(0, 2); + assert_eq!(result, 30); // 10 + 20 + }); + + handle1.join().unwrap(); + + // Test 4: Closure with static data (always Send + Sync) + let static_closure = |x: i32| x * 3; + + let handle2 = thread::spawn(move || { + let result = static_closure(5); + assert_eq!(result, 15); + }); + + handle2.join().unwrap(); + + // Test 5: Closure that doesn't implement Send (demonstrates what NOT to do) + let mut local_data = vec![1, 2, 3]; + let non_send_closure = move |index: usize| { + local_data[index] // This captures local_data by value + }; + + // This would work in single-threaded context + let result = non_send_closure(1); + assert_eq!(result, 2); + + // Test 6: Closure with thread-local storage + use std::cell::RefCell; + use std::thread_local; + + thread_local! { + static THREAD_COUNTER: RefCell = RefCell::new(0); + } + + let thread_local_closure = || { + THREAD_COUNTER.with(|counter| { + let mut count = counter.borrow_mut(); + *count += 1; + *count + }) + }; + + let handle3 = thread::spawn(move || { + let result1 = thread_local_closure(); + let result2 = thread_local_closure(); + assert_eq!(result1, 1); + assert_eq!(result2, 2); + }); + + handle3.join().unwrap(); + + // Test 7: Closure with atomic operations + use std::sync::atomic::{AtomicI32, Ordering}; + + let atomic_counter = Arc::new(AtomicI32::new(0)); + let mut atomic_handles = vec![]; + + for _ in 0..5 { + let counter_clone = Arc::clone(&atomic_counter); + let atomic_closure = move || { + counter_clone.fetch_add(1, Ordering::SeqCst); + }; + + let handle = thread::spawn(atomic_closure); + atomic_handles.push(handle); + } + + for handle in atomic_handles { + handle.join().unwrap(); + } + + assert_eq!(atomic_counter.load(Ordering::SeqCst), 5); +} diff --git a/tests/closure/closure_error_handling.rs b/tests/closure/closure_error_handling.rs new file mode 100644 index 000000000..824e8154f --- /dev/null +++ b/tests/closure/closure_error_handling.rs @@ -0,0 +1,111 @@ +// Test closure error handling + +fn main() { + // Test 1: Closure with Result handling + let safe_divide = |a: i32, b: i32| -> Result { + if b == 0 { + Err("Division by zero".to_string()) + } else { + Ok(a / b) + } + }; + + let result1 = safe_divide(10, 2); + let result2 = safe_divide(10, 0); + + assert_eq!(result1, Ok(5)); + assert_eq!(result2, Err("Division by zero".to_string())); + + // Test 2: Closure with Option handling + let safe_get = |index: usize, data: &[i32]| -> Option { + data.get(index).copied() + }; + + let numbers = vec![1, 2, 3, 4, 5]; + let valid_result = safe_get(2, &numbers); + let invalid_result = safe_get(10, &numbers); + + assert_eq!(valid_result, Some(3)); + assert_eq!(invalid_result, None); + + // Test 3: Closure with map_err for error transformation + let parse_number = |s: &str| -> Result { + s.parse::() + .map_err(|e| format!("Failed to parse '{}': {}", s, e)) + }; + + let parse_result1 = parse_number("123"); + let parse_result2 = parse_number("abc"); + + assert_eq!(parse_result1, Ok(123)); + assert!(parse_result2.is_err()); + + // Test 4: Closure with unwrap_or for default values + let get_with_default = |index: usize, data: &[i32], default: i32| -> i32 { + data.get(index).copied().unwrap_or(default) + }; + + let result3 = get_with_default(1, &numbers, -1); + let result4 = get_with_default(10, &numbers, -1); + + assert_eq!(result3, 2); + assert_eq!(result4, -1); + + // Test 5: Closure with and_then for chaining operations + let process_data = |input: &str| -> Result { + input + .parse::() + .map_err(|_| "Parse error".to_string()) + .and_then(|n| { + if n > 0 { + Ok(n * 2) + } else { + Err("Number must be positive".to_string()) + } + }) + }; + + let chain_result1 = process_data("5"); + let chain_result2 = process_data("-1"); + let chain_result3 = process_data("abc"); + + assert_eq!(chain_result1, Ok(10)); + assert_eq!(chain_result2, Err("Number must be positive".to_string())); + assert_eq!(chain_result3, Err("Parse error".to_string())); + + // Test 6: Closure with panic handling (demonstrates what NOT to do) + let dangerous_divide = |a: i32, b: i32| -> i32 { + if b == 0 { + panic!("Division by zero!"); + } + a / b + }; + + // This would panic: dangerous_divide(10, 0); + // Instead, we test the safe case + let safe_result = dangerous_divide(10, 2); + assert_eq!(safe_result, 5); + + // Test 7: Closure with custom error types + #[derive(Debug, PartialEq)] + enum MathError { + DivisionByZero, + Overflow, + } + + let math_divide = |a: i32, b: i32| -> Result { + if b == 0 { + Err(MathError::DivisionByZero) + } else if a == i32::MIN && b == -1 { + Err(MathError::Overflow) + } else { + Ok(a / b) + } + }; + + let math_result1 = math_divide(10, 2); + let math_result2 = math_divide(10, 0); + + assert_eq!(math_result1, Ok(5)); + assert_eq!(math_result2, Err(MathError::DivisionByZero)); +} diff --git a/tests/closure/closure_iterators.rs b/tests/closure/closure_iterators.rs new file mode 100644 index 000000000..e45f2b52f --- /dev/null +++ b/tests/closure/closure_iterators.rs @@ -0,0 +1,82 @@ +// Test closures with iterators + +fn main() { + let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + // Test 1: map with closure + let doubled: Vec = numbers.iter() + .map(|&x| x * 2) + .collect(); + + assert_eq!(doubled, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + // Test 2: filter with closure + let evens: Vec = numbers.iter() + .filter(|&&x| x % 2 == 0) + .cloned() + .collect(); + + assert_eq!(evens, vec![2, 4, 6, 8, 10]); + + // Test 3: fold with closure + let sum: i32 = numbers.iter() + .fold(0, |acc, &x| acc + x); + + assert_eq!(sum, 55); + + // Test 4: chain multiple iterator operations with closures + let result: Vec = numbers.iter() + .filter(|&&x| x > 5) + .map(|&x| x * x) + .collect(); + + assert_eq!(result, vec![36, 49, 64, 81, 100]); + + // Test 5: any and all with closures + let has_even = numbers.iter().any(|&x| x % 2 == 0); + let all_positive = numbers.iter().all(|&x| x > 0); + + assert!(has_even); + assert!(all_positive); + + // Test 6: find with closure + let first_divisible_by_3 = numbers.iter().find(|&&x| x % 3 == 0); + assert_eq!(first_divisible_by_3, Some(&3)); + + // Test 7: enumerate with closure + let indexed: Vec<(usize, i32)> = numbers.iter() + .enumerate() + .map(|(i, &x)| (i, x * 2)) + .collect(); + + assert_eq!(indexed[0], (0, 2)); + assert_eq!(indexed[1], (1, 4)); + + // Test 8: zip with closure + let letters = vec!['a', 'b', 'c', 'd', 'e']; + let combined: Vec = numbers.iter() + .zip(letters.iter()) + .map(|(&num, &letter)| format!("{}{}", letter, num)) + .collect(); + + assert_eq!(combined[0], "a1"); + assert_eq!(combined[1], "b2"); + + // Test 9: flat_map with closure + let ranges = vec![1..4, 5..7, 8..11]; + let flattened: Vec = ranges.iter() + .flat_map(|range| range.clone()) + .collect(); + + assert_eq!(flattened, vec![1, 2, 3, 5, 6, 8, 9, 10]); + + // Test 10: scan with closure (stateful iterator) + let running_sum: Vec = numbers.iter() + .scan(0, |state, &x| { + *state += x; + Some(*state) + }) + .collect(); + + assert_eq!(running_sum, vec![1, 3, 6, 10, 15, 21, 28, 36, 45, 55]); +} diff --git a/tests/closure/closure_lifetimes.rs b/tests/closure/closure_lifetimes.rs new file mode 100644 index 000000000..2215e2d5a --- /dev/null +++ b/tests/closure/closure_lifetimes.rs @@ -0,0 +1,41 @@ +// Test closure lifetime scenarios + +fn main() { + // Test 1: Closure capturing reference with lifetime + let data = vec![1, 2, 3, 4, 5]; + + // This closure captures a reference to data + let get_value = |index: usize| { + &data[index] + }; + + let result = get_value(2); + assert_eq!(*result, 3); + + // Test 2: Closure returning reference (requires careful lifetime management) + let numbers = [10, 20, 30, 40, 50]; + + // This works because numbers lives long enough + let get_ref = |index: usize| { + &numbers[index] + }; + + let ref_result = get_ref(1); + assert_eq!(*ref_result, 20); + + // Test 3: Closure with explicit lifetime annotation + fn create_closure<'a>(data: &'a [i32]) -> impl Fn(usize) -> &'a i32 { + move |index| &data[index] + } + + let test_data = [100, 200, 300]; + let lifetime_closure = create_closure(&test_data); + let lifetime_result = lifetime_closure(1); + assert_eq!(*lifetime_result, 200); + + // Test 4: Closure that doesn't capture any references + let no_ref_closure = |x: i32| x * 2; + let no_ref_result = no_ref_closure(5); + assert_eq!(no_ref_result, 10); + +} diff --git a/tests/closure/closure_move.rs b/tests/closure/closure_move.rs new file mode 100644 index 000000000..2f03b275b --- /dev/null +++ b/tests/closure/closure_move.rs @@ -0,0 +1,15 @@ +fn main() { + let data = vec![1, 2, 3, 4, 5]; + + // Closure with move semantics + let consume_data = move |index: usize| { + data[index] + }; + + let result = consume_data(2); + assert_eq!(result, 3); + + // Note: data has been moved into the closure and cannot be used here + // The following line would cause a compilation error: + // println!("Data: {:?}", data); // Error: use of moved value: `data` +} \ No newline at end of file diff --git a/tests/closure/closure_mut_capture.rs b/tests/closure/closure_mut_capture.rs new file mode 100644 index 000000000..d0973922e --- /dev/null +++ b/tests/closure/closure_mut_capture.rs @@ -0,0 +1,17 @@ +fn main() { + let mut counter = 0; + let numbers = [10, 20, 30]; + + // Closure with mutable capture + let mut increment_and_get = |x: i32| { + counter += 1; + x + counter + }; + + let result1 = increment_and_get(numbers[0]); + let result2 = increment_and_get(numbers[1]); + + assert_eq!(result1, 11); // 10 + 1 + assert_eq!(result2, 22); // 20 + 2 + assert_eq!(counter, 2); +} \ No newline at end of file diff --git a/tests/closure/closure_recursive.rs b/tests/closure/closure_recursive.rs new file mode 100644 index 000000000..fa9bd36e9 --- /dev/null +++ b/tests/closure/closure_recursive.rs @@ -0,0 +1,86 @@ +// Test recursive closures + +fn main() { + // Test 1: Recursive closure using a helper function + fn factorial(n: u32) -> u32 { + if n <= 1 { + 1 + } else { + n * factorial(n - 1) + } + } + + let factorial_closure = |n: u32| factorial(n); + + assert_eq!(factorial_closure(5), 120); + assert_eq!(factorial_closure(0), 1); + + // Test 2: Recursive closure using a struct with FnMut + struct RecursiveClosure { + func: Option u32>>, + } + + let mut fib_closure = RecursiveClosure { func: None }; + fib_closure.func = Some(Box::new(move |n: u32| { + if n <= 1 { + n + } else { + // This is a simplified version - in practice you'd need more complex setup + n + } + })); + + // Test 3: Recursive closure using a fixed-point combinator pattern + fn fix(f: F) -> impl Fn(T) -> T + where + F: Fn(&dyn Fn(T) -> T, T) -> T, + { + move |x| f(&fix(&f), x) + } + + let factorial_fix = fix(|f, n: u32| { + if n <= 1 { + 1 + } else { + n * f(n - 1) + } + }); + + assert_eq!(factorial_fix(5), 120); + + // Test 4: Recursive closure with memoization + use std::collections::HashMap; + use std::cell::RefCell; + + let memo = RefCell::new(HashMap::new()); + let mut fib_memo = |n: u32| -> u32 { + if let Some(&result) = memo.borrow().get(&n) { + return result; + } + + let result = if n <= 1 { + n + } else { + fib_memo(n - 1) + fib_memo(n - 2) + }; + + memo.borrow_mut().insert(n, result); + result + }; + + assert_eq!(fib_memo(10), 55); + + // Test 5: Recursive closure with accumulator + let sum_range = |start: i32, end: i32| { + fn helper(acc: i32, current: i32, end: i32) -> i32 { + if current > end { + acc + } else { + helper(acc + current, current + 1, end) + } + } + helper(0, start, end) + }; + + assert_eq!(sum_range(1, 5), 15); +} diff --git a/tests/closure/closure_return.rs b/tests/closure/closure_return.rs new file mode 100644 index 000000000..f2ae299e7 --- /dev/null +++ b/tests/closure/closure_return.rs @@ -0,0 +1,13 @@ +fn main() { + let numbers = [1, 2, 3, 4, 5]; + + // Function that returns a closure + fn create_adder(addend: i32) -> impl Fn(i32) -> i32 { + move |x| x + addend + } + + let add_five = create_adder(5); + let result = add_five(numbers[2]); + + assert_eq!(result, 8); // 3 + 5 +} \ No newline at end of file diff --git a/tests/closure/closure_struct_access.rs b/tests/closure/closure_struct_access.rs new file mode 100644 index 000000000..f82c80c0f --- /dev/null +++ b/tests/closure/closure_struct_access.rs @@ -0,0 +1,25 @@ +struct MyStruct { + data: i32 +} + +fn main() { + // List of MyStruct instances + let struct_list = [ + MyStruct { data: 10 }, + MyStruct { data: 20 }, + MyStruct { data: 30 }, + MyStruct { data: 40 }, + MyStruct { data: 50 } + ]; + + // Closure function that takes &MyStruct reference + let get_value = |struct_ref: &MyStruct| { + struct_ref.data + }; + + // Use list call style, passing reference + let result = get_value(&struct_list[2]); + + // Verify result + assert_eq!(result, 30); +} \ No newline at end of file diff --git a/tests/closure/closure_traits.rs b/tests/closure/closure_traits.rs new file mode 100644 index 000000000..7dd748bc3 --- /dev/null +++ b/tests/closure/closure_traits.rs @@ -0,0 +1,72 @@ +// Test closure traits: Fn, FnMut, FnOnce + +fn main() { + // Test 1: Fn trait - can be called multiple times, captures by reference + let numbers = [1, 2, 3, 4, 5]; + let fn_closure = |index: usize| numbers[index]; + + // Can call multiple times + assert_eq!(fn_closure(0), 1); + assert_eq!(fn_closure(1), 2); + assert_eq!(fn_closure(2), 3); + + // Test 2: FnMut trait - can be called multiple times, captures by mutable reference + let mut counter = 0; + let mut fnmut_closure = |x: i32| { + counter += 1; + x + counter + }; + + assert_eq!(fnmut_closure(10), 11); // 10 + 1 + assert_eq!(fnmut_closure(10), 12); // 10 + 2 + assert_eq!(counter, 2); + + // Test 3: FnOnce trait - can only be called once, takes ownership + let data = vec![1, 2, 3]; + let fnonce_closure = move |index: usize| { + data[index] // data is moved into closure + }; + + // Can only call once + let result = fnonce_closure(1); + assert_eq!(result, 2); + + // Test 4: Trait objects with closures + let closures: Vec i32>> = vec![ + Box::new(|x| x * 2), + Box::new(|x| x + 10), + Box::new(|x| x * x), + ]; + + for (i, closure) in closures.iter().enumerate() { + let result = closure(5); + match i { + 0 => assert_eq!(result, 10), // 5 * 2 + 1 => assert_eq!(result, 15), // 5 + 10 + 2 => assert_eq!(result, 25), // 5 * 5 + _ => unreachable!(), + } + } + + // Test 5: Generic function with closure trait bounds + fn apply_operation(f: F, x: i32) -> i32 + where + F: Fn(i32) -> i32 + { + f(x) + } + + let add_five = |x| x + 5; + let result = apply_operation(add_five, 10); + assert_eq!(result, 15); + + // Test 6: Closure that implements multiple traits + let mut state = 0; + let multi_trait_closure = |x: i32| { + state += x; + state + }; + + assert_eq!(multi_trait_closure(5), 5); + assert_eq!(multi_trait_closure(3), 8); +} diff --git a/tests/closure/closure_unsafe.rs b/tests/closure/closure_unsafe.rs new file mode 100644 index 000000000..fcd83009c --- /dev/null +++ b/tests/closure/closure_unsafe.rs @@ -0,0 +1,94 @@ +// Test unsafe closures + +fn main() { + // Test 1: Unsafe closure with raw pointer manipulation + let data = vec![1, 2, 3, 4, 5]; + let ptr = data.as_ptr(); + + let unsafe_closure = |index: usize| unsafe { + *ptr.add(index) + }; + + let result = unsafe_closure(2); + assert_eq!(result, 3); + + // Test 2: Unsafe closure with transmute + let number: u32 = 0x12345678; + + let transmute_closure = || unsafe { + std::mem::transmute::(number) + }; + + let bytes = transmute_closure(); + assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]); // Little-endian + + // Test 3: Unsafe closure with static mut + static mut COUNTER: i32 = 0; + + let unsafe_counter = || unsafe { + COUNTER += 1; + COUNTER + }; + + let count1 = unsafe_counter(); + let count2 = unsafe_counter(); + + assert_eq!(count1, 1); + assert_eq!(count2, 2); + + // Test 4: Unsafe closure with manual memory management + let unsafe_alloc = || unsafe { + let ptr = std::alloc::alloc( + std::alloc::Layout::from_size_align(4, 4).unwrap() + ); + if !ptr.is_null() { + *(ptr as *mut i32) = 42; + *(ptr as *mut i32) + } else { + 0 + } + }; + + let alloc_result = unsafe_alloc(); + assert_eq!(alloc_result, 42); + + // Test 5: Unsafe closure with FFI simulation + extern "C" { + fn strlen(s: *const i8) -> usize; + } + + let string = b"hello\0"; + let unsafe_strlen = |s: *const i8| unsafe { + strlen(s) + }; + + let len = unsafe_strlen(string.as_ptr() as *const i8); + assert_eq!(len, 5); + + // Test 6: Unsafe closure with union + union IntOrFloat { + i: i32, + f: f32, + } + + let value = IntOrFloat { i: 42 }; + + let unsafe_union = || unsafe { + value.i + }; + + let union_result = unsafe_union(); + assert_eq!(union_result, 42); + + // Test 7: Unsafe closure with uninitialized memory + let unsafe_uninit = || unsafe { + let mut data: [i32; 3] = std::mem::uninitialized(); + data[0] = 1; + data[1] = 2; + data[2] = 3; + data + }; + + let uninit_result = unsafe_uninit(); + assert_eq!(uninit_result, [1, 2, 3]); +} From 0adb631bf8abb12f9cf25203ae948f7fa973a4fc Mon Sep 17 00:00:00 2001 From: Stevengre Date: Wed, 20 Aug 2025 20:47:46 +0800 Subject: [PATCH 6/6] Add documentation for removed test cases in `moved2dev.md` - Documented test cases that have been merged or are being addressed, indicating they should be removed. - Noted specific tests related to `closure/closure_struct_access.rs` that are currently under fix. --- tests/moved2dev.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/moved2dev.md diff --git a/tests/moved2dev.md b/tests/moved2dev.md new file mode 100644 index 000000000..3f329a9fb --- /dev/null +++ b/tests/moved2dev.md @@ -0,0 +1,4 @@ + +The following test cases have either been merged into master or are currently being addressed, so they should be removed. Additionally, if any new tests added in this branch are already handled by the current semantics and there are corresponding tests in the original semantics, they should also be removed. + +- closure/closure_struct_access.rs: currently being fixed with jh/deref-aggregate \ No newline at end of file