diff --git a/crates/sui-framework/packages/move-stdlib/sources/macros.move b/crates/sui-framework/packages/move-stdlib/sources/macros.move index 48680c899d702..4aa571d426b67 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/macros.move +++ b/crates/sui-framework/packages/move-stdlib/sources/macros.move @@ -84,7 +84,7 @@ public macro fun num_to_string($x: _): String { buffer.to_string() } -public macro fun range_do($start: _, $stop: _, $f: |_|) { +public macro fun range_do($start: _, $stop: _, $f: |_| -> _) { let mut i = $start; let stop = $stop; while (i < stop) { @@ -93,7 +93,7 @@ public macro fun range_do($start: _, $stop: _, $f: |_|) { } } -public macro fun range_do_eq($start: _, $stop: _, $f: |_|) { +public macro fun range_do_eq($start: _, $stop: _, $f: |_| -> _) { let mut i = $start; let stop = $stop; // we check `i >= stop` inside the loop instead of `i <= stop` as `while` condition to avoid @@ -108,11 +108,11 @@ public macro fun range_do_eq($start: _, $stop: _, $f: |_|) { } } -public macro fun do($stop: _, $f: |_|) { +public macro fun do($stop: _, $f: |_| -> _) { range_do!(0, $stop, $f) } -public macro fun do_eq($stop: _, $f: |_|) { +public macro fun do_eq($stop: _, $f: |_| -> _) { range_do_eq!(0, $stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/option.move b/crates/sui-framework/packages/move-stdlib/sources/option.move index 857e76ae0d2bb..7c992b022d389 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/option.move +++ b/crates/sui-framework/packages/move-stdlib/sources/option.move @@ -144,26 +144,26 @@ public fun to_vec(t: Option): vector { // === Macro Functions === /// Destroy `Option` and call the closure `f` on the value inside if it holds one. -public macro fun destroy<$T>($o: Option<$T>, $f: |$T|) { +public macro fun destroy<$T>($o: Option<$T>, $f: |$T| -> _) { let o = $o; o.do!($f); } /// Destroy `Option` and call the closure `f` on the value inside if it holds one. -public macro fun do<$T>($o: Option<$T>, $f: |$T|) { +public macro fun do<$T>($o: Option<$T>, $f: |$T| -> _) { let o = $o; if (o.is_some()) $f(o.destroy_some()) else o.destroy_none() } /// Execute a closure on the value inside `t` if it holds one. -public macro fun do_ref<$T>($o: &Option<$T>, $f: |&$T|) { +public macro fun do_ref<$T>($o: &Option<$T>, $f: |&$T| -> _) { let o = $o; if (o.is_some()) $f(o.borrow()); } /// Execute a closure on the mutable reference to the value inside `t` if it holds one. -public macro fun do_mut<$T>($o: &mut Option<$T>, $f: |&mut $T|) { +public macro fun do_mut<$T>($o: &mut Option<$T>, $f: |&mut $T| -> _) { let o = $o; if (o.is_some()) $f(o.borrow_mut()); } diff --git a/crates/sui-framework/packages/move-stdlib/sources/vector.move b/crates/sui-framework/packages/move-stdlib/sources/vector.move index a24d0cd3db9e3..2a8019ab7274d 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/vector.move @@ -172,7 +172,7 @@ public macro fun tabulate<$T>($n: u64, $f: |u64| -> $T): vector<$T> { /// Destroy the vector `v` by calling `f` on each element and then destroying the vector. /// Does not preserve the order of elements in the vector (starts from the end of the vector). -public macro fun destroy<$T>($v: vector<$T>, $f: |$T|) { +public macro fun destroy<$T>($v: vector<$T>, $f: |$T| -> _) { let mut v = $v; while (v.length() != 0) $f(v.pop_back()); v.destroy_empty(); @@ -180,7 +180,7 @@ public macro fun destroy<$T>($v: vector<$T>, $f: |$T|) { /// Destroy the vector `v` by calling `f` on each element and then destroying the vector. /// Preserves the order of elements in the vector. -public macro fun do<$T>($v: vector<$T>, $f: |$T|) { +public macro fun do<$T>($v: vector<$T>, $f: |$T| -> _) { let mut v = $v; v.reverse(); v.length().do!(|_| $f(v.pop_back())); @@ -188,14 +188,14 @@ public macro fun do<$T>($v: vector<$T>, $f: |$T|) { } /// Perform an action `f` on each element of the vector `v`. The vector is not modified. -public macro fun do_ref<$T>($v: &vector<$T>, $f: |&$T|) { +public macro fun do_ref<$T>($v: &vector<$T>, $f: |&$T| -> _) { let v = $v; v.length().do!(|i| $f(&v[i])) } /// Perform an action `f` on each element of the vector `v`. /// The function `f` takes a mutable reference to the element. -public macro fun do_mut<$T>($v: &mut vector<$T>, $f: |&mut $T|) { +public macro fun do_mut<$T>($v: &mut vector<$T>, $f: |&mut $T| -> _) { let v = $v; v.length().do!(|i| $f(&mut v[i])) } @@ -295,19 +295,20 @@ public macro fun all<$T>($v: &vector<$T>, $f: |&$T| -> bool): bool { /// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. /// Aborts if the vectors are not of the same length. /// The order of elements in the vectors is preserved. -public macro fun zip_do<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { +public macro fun zip_do<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2| -> _) { let v1 = $v1; let mut v2 = $v2; v2.reverse(); let len = v1.length(); assert!(len == v2.length()); v1.do!(|el1| $f(el1, v2.pop_back())); + v2.destroy_empty(); } /// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. /// Aborts if the vectors are not of the same length. /// Starts from the end of the vectors. -public macro fun zip_do_reverse<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { +public macro fun zip_do_reverse<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2| -> _) { let v1 = $v1; let mut v2 = $v2; let len = v1.length(); @@ -319,7 +320,7 @@ public macro fun zip_do_reverse<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f /// elements. The vectors are not modified. /// Aborts if the vectors are not of the same length. /// The order of elements in the vectors is preserved. -public macro fun zip_do_ref<$T1, $T2>($v1: &vector<$T1>, $v2: &vector<$T2>, $f: |&$T1, &$T2|) { +public macro fun zip_do_ref<$T1, $T2>($v1: &vector<$T1>, $v2: &vector<$T2>, $f: |&$T1, &$T2| -> _) { let v1 = $v1; let v2 = $v2; let len = v1.length(); @@ -334,7 +335,7 @@ public macro fun zip_do_ref<$T1, $T2>($v1: &vector<$T1>, $v2: &vector<$T2>, $f: public macro fun zip_do_mut<$T1, $T2>( $v1: &mut vector<$T1>, $v2: &mut vector<$T2>, - $f: |&mut $T1, &mut $T2|, + $f: |&mut $T1, &mut $T2| -> _, ) { let v1 = $v1; let v2 = $v2; diff --git a/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move b/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move index cc1d041f4a077..5d2caa9a689f4 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move @@ -645,6 +645,11 @@ fun test_do_macro() { assert!(vec == vector[11, 21, 31, 41]); } +#[test] +fun test_do_macro_with_return_value() { + vector[10, 20, 30].do!(|e| e); +} + #[test] fun test_map_macro() { let e = vector[]; @@ -741,6 +746,17 @@ fun zip_do_macro() { assert!(res == vector[5, 7, 9]); } +#[test] +fun zip_do_undroppable_macro() { + let v1 = vector[NotDroppable {}, NotDroppable {}]; + let v2 = vector[NotDroppable {}, NotDroppable {}]; + + v1.zip_do!(v2, |a, b| { + let NotDroppable {} = a; + let NotDroppable {} = b; + }); +} + #[test, expected_failure] fun zip_do_reverse_macro_fail() { let v1 = vector[1u64];