//# publish module 0x1.Tester { import 0x1.signer; struct Data has key { v1: u64, v2: u64 } struct Box has key { f: u64 } // the key struct is here to just give a feeling why the computation might not be reorderable bump_and_pick(account: &signer, b1: &mut Self.Box, b2: &mut Self.Box): &u64 acquires Data { let sender: address; let data: &mut Self.Data; label b0: sender = signer.address_of(move(account)); data = borrow_global_mut(move(sender)); *&mut copy(b1).Box::f = *©(data).Data::v1; *&mut copy(b2).Box::f = *&move(data).Data::v2; jump_if (*©(b1).Box::f >= *©(b2).Box::f) b2; label b1: _ = move(b1); return &move(b2).Box::f; label b2: _ = move(b2); return &move(b1).Box::f; } larger_field(account: &signer, drop: address, result: &mut u64) acquires Box, Data { let b1: Self.Box; let b2: Self.Box; let returned_ref: &u64; let dump: u64; label b0: b1 = move_from(signer.address_of(copy(account))); b2 = move_from(move(drop)); assert(*&(&b1).Box::f == 0, 42); assert(*&(&b2).Box::f == 0, 42); returned_ref = Self.bump_and_pick(copy(account), &mut b1, &mut b2); // it is valid to immutably extend the reference // even though a mut extension + freeze would be invalid assert( // (*copy(returned_ref) == *&(&b1).Box::f) ^ (*copy(returned_ref) == *&(&b2).Box::f), (*copy(returned_ref) == *&(&mut b1).Box::f) != (*copy(returned_ref) == *&(&mut b2).Box::f), 42 ); *move(result) = *move(returned_ref); move_to(copy(account), move(b1)); Box { dump } = move(b2); return; } }