//# publish module 0x1.Tester { import 0x1.signer; struct Initializer has key { x: u64, y: u64 } struct Point { x: u64, y: u64 } // the key struct is here to just give a feeling why the computation might not be reorderable set_and_pick(account: &signer, p: &mut Self.Point): &mut u64 acquires Initializer { let sender: address; let init: &mut Self.Initializer; label b0: sender = signer.address_of(move(account)); init = borrow_global_mut(move(sender)); *&mut copy(p).Point::x = *©(init).Initializer::x; *&mut copy(p).Point::y = *&move(init).Initializer::y; jump_if (*©(p).Point::x >= *©(p).Point::y) b2; label b1: return &mut move(p).Point::y; label b2: return &mut move(p).Point::x; } bump_and_give(u: &mut u64): &u64 { label b0: *copy(u) = *copy(u) + 1; return freeze(move(u)); } larger_field(account: &signer, point_ref: &mut Self.Point): &u64 acquires Initializer { let field_ref: &mut u64; let returned_ref: &u64; label b0: assert(*©(point_ref).Point::x == 0, 42); assert(*©(point_ref).Point::y == 0, 42); field_ref = Self.set_and_pick(move(account), copy(point_ref)); returned_ref = Self.bump_and_give(move(field_ref)); // it is valid to immutably extend the reference // even though a mut extension + freeze would be invalid assert( (*copy(returned_ref) == *©(point_ref).Point::x) && (*copy(returned_ref) != *&move(point_ref).Point::y), 42 ); return move(returned_ref); } }