address 0x1 { module TestMutRefs { struct T has copy, drop { value: u64 } // Resource to track the sum of values in T struct TSum has key { sum: u64 } public fun new(x: u64): T acquires TSum { let r = borrow_global_mut(@0x0); r.sum = r.sum + x; T{value: x} } public fun delete(x: T) acquires TSum { let r = borrow_global_mut(@0x0); let T{value: v} = x; r.sum = r.sum - v; } public fun increment(x: &mut T) acquires TSum { x.value = x.value + 1; let r = borrow_global_mut(@0x0); r.sum = r.sum + 1; } public fun increment_invalid(x: &mut T) { x.value = x.value + 1; } public fun decrement_invalid(x: &mut T) acquires TSum { x.value = x.value - 1; let r = borrow_global_mut(@0x0); r.sum = r.sum - 1; } fun private_decrement(x: &mut T) acquires TSum { x.value = x.value - 1; let r = borrow_global_mut(@0x0); r.sum = r.sum - 1; } public fun data_invariant(_x: &mut T) { } fun private_data_invariant_invalid(_x: &mut T) { } fun private_to_public_caller(r: &mut T) acquires TSum { increment(r); } fun private_to_public_caller_invalid_data_invariant() acquires TSum { let x = new(1); let r = &mut x; private_decrement(r); increment(r); } } module TestMutRefsUser { use 0x1::TestMutRefs; public fun valid() { let x = TestMutRefs::new(4); TestMutRefs::increment(&mut x); TestMutRefs::delete(x); } } }