//# 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_1(account: &signer, point_ref: &mut Self.Point): &u64 acquires Initializer { let field_ref: &mut u64; let returned_ref: &u64; let x_val: 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)); // this borrow is invalid because of field_ref x_val = *freeze(&mut move(point_ref).Point::x); returned_ref = Self.bump_and_give(move(field_ref)); // imagine some more interesting check than this assert assert( *copy(returned_ref) == (move(x_val) + 1), 42 ); return move(returned_ref); } } //# publish module 0x1.Tester2 { 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_2(account: &signer, point_ref: &mut Self.Point): &u64 acquires Initializer { let field_ref: &mut u64; let returned_ref: &u64; let x_val: 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)); // this freeze is invalid because of field_ref x_val = *(&freeze(move(point_ref)).Point::x); returned_ref = Self.bump_and_give(move(field_ref)); // imagine some more interesting check than this assert assert( *copy(returned_ref) == (move(x_val) + 1), 42 ); return move(returned_ref); } }