diff --git a/third_party/move/move-compiler-v2/src/bytecode_generator.rs b/third_party/move/move-compiler-v2/src/bytecode_generator.rs index 19d571863998a..38f9a04bc5c9d 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -2,6 +2,7 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 +use crate::{experiments::Experiment, Options}; use codespan_reporting::diagnostic::Severity; use ethnum::U256; use itertools::Itertools; @@ -324,6 +325,14 @@ impl<'env> Generator<'env> { let loc = env.get_node_loc(id); env.diag(severity, &loc, msg.as_ref()) } + + fn check_if_lambdas_enabled(&self) -> bool { + let options = self + .env() + .get_extension::() + .expect("Options is available"); + options.experiment_on(Experiment::LAMBDA_VALUES) + } } // ====================================================================================== @@ -480,14 +489,23 @@ impl<'env> Generator<'env> { self.emit_with(*id, |attr| Bytecode::SpecBlock(attr, spec)); }, // TODO(LAMBDA) - ExpData::Lambda(id, _, _, _, _) => self.error( + ExpData::Lambda(id, _, _, _, _) => + self.error( *id, - "Function-typed values not yet supported except as parameters to calls to inline functions", + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + } ), // TODO(LAMBDA) ExpData::Invoke(id, _exp, _) => self.error( *id, - "Calls to function values other than inline function parameters not yet supported", + if self.check_if_lambdas_enabled() { + "Calls to function values other than inline function parameters not yet implemented" + } else { + "Calls to function values other than inline function parameters not yet supported" + } ), ExpData::Quant(id, _, _, _, _, _) => { self.internal_error(*id, "unsupported specification construct") @@ -564,10 +582,16 @@ impl<'env> Generator<'env> { Constant::Bool(false) } }, + // TODO(LAMBDA) Value::Function(_mid, _fid) => { self.error( id, - "Function-typed values not yet supported except as parameters to calls to inline functions"); + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + } + ); Constant::Bool(false) }, } @@ -794,7 +818,11 @@ impl<'env> Generator<'env> { // TODO(LAMBDA) Operation::EarlyBind => self.error( id, - "Function-typed values not yet supported except as parameters to calls to inline functions", + if self.check_if_lambdas_enabled() { + "Function-typed values not yet implemented except as parameters to calls to inline functions" + } else { + "Function-typed values not yet supported except as parameters to calls to inline functions" + }, ), Operation::TestVariants(mid, sid, variants) => { self.gen_test_variants(targets, id, mid.qualified(*sid), variants, args) @@ -1336,9 +1364,12 @@ impl<'env> Generator<'env> { }; self.gen_borrow_field_operation(id, borrow_dest, str, fields, oper_temp); if need_read_ref { - self.emit_call(id, vec![target], BytecodeOperation::ReadRef, vec![ - borrow_dest, - ]) + self.emit_call( + id, + vec![target], + BytecodeOperation::ReadRef, + vec![borrow_dest], + ) } } @@ -1526,10 +1557,13 @@ enum MatchMode { impl MatchMode { /// Whether this match is in probing mode. fn is_probing(&self) -> bool { - matches!(self, MatchMode::Refutable { - probing_vars: Some(_), - .. - }) + matches!( + self, + MatchMode::Refutable { + probing_vars: Some(_), + .. + } + ) } /// Whether a variable appearing in the pattern should be bound to a temporary. @@ -1657,9 +1691,12 @@ impl<'env> Generator<'env> { ReferenceKind::Immutable, Box::new(value_ty.clone()), )); - self.emit_call(id, vec![value_ref], BytecodeOperation::BorrowLoc, vec![ - value, - ]); + self.emit_call( + id, + vec![value_ref], + BytecodeOperation::BorrowLoc, + vec![value], + ); needs_probing = true; value_ref } @@ -1781,10 +1818,11 @@ impl<'env> Generator<'env> { ), ); return Some( - ExpData::Call(id, Operation::Deref, vec![ExpData::LocalVar( - new_id, var, + ExpData::Call( + id, + Operation::Deref, + vec![ExpData::LocalVar(new_id, var).into_exp()], ) - .into_exp()]) .into_exp(), ); } diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs b/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs index b58d3318cc230..3802e194de2c7 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/lambda_lifter.rs @@ -13,8 +13,8 @@ //! not modify free variables. //! //! Lambda lifting rewrites lambda expressions into construction -//! of *closures*. A closure refers to a function and contains a partial list -//! of arguments for that function, essentially currying it. We use the +//! of *closures* using the `EarlyBind` operation. A closure refers to a function and contains a list +//! of "early bound" leading arguments for that function, essentially currying it. We use the //! `EarlyBind` operation to construct a closure from a function and set of arguemnts, //! which must be the first `k` arguments to the function argument list. //! @@ -204,7 +204,9 @@ impl<'a> LambdaLifter<'a> { /// - `closure_args` = corresponding expressions to provide as actual arg for each param /// - `param_index_mapping` = for each free var which is a Parameter from the enclosing function, /// a mapping from index there to index in the params list - fn get_params_for_freevars(&mut self) -> (Vec, Vec, BTreeMap) { + fn get_params_for_freevars( + &mut self, + ) -> Option<(Vec, Vec, BTreeMap)> { let env = self.fun_env.module_env.env; let mut closure_args = vec![]; @@ -213,6 +215,9 @@ impl<'a> LambdaLifter<'a> { // functions (courtesy of #12317) let mut param_index_mapping = BTreeMap::new(); let mut params = vec![]; + let ty_params = self.fun_env.get_type_parameters_ref(); + let ability_inferer = AbilityInferer::new(env, ty_params); + let mut saw_error = false; for (used_param_count, (param, var_info)) in mem::take(&mut self.free_params).into_iter().enumerate() @@ -229,6 +234,18 @@ impl<'a> LambdaLifter<'a> { name.display(env.symbol_pool()) ), ); + saw_error = true; + } + let param_abilities = ability_inferer.infer_abilities(&ty).1; + if !param_abilities.has_copy() { + env.error( + &loc, + &format!( + "captured variable `{}` must have a value with `copy` ability", // TODO(LAMBDA) + name.display(env.symbol_pool()) + ), + ); + saw_error = true; } params.push(Parameter(name, ty.clone(), loc.clone())); let new_id = env.new_node(loc, ty); @@ -252,6 +269,7 @@ impl<'a> LambdaLifter<'a> { name.display(env.symbol_pool()) ), ); + saw_error = true; } params.push(Parameter(name, ty.clone(), loc.clone())); let new_id = env.new_node(loc, ty); @@ -261,7 +279,11 @@ impl<'a> LambdaLifter<'a> { closure_args.push(ExpData::LocalVar(new_id, name).into_exp()) } - (params, closure_args, param_index_mapping) + if !saw_error { + Some((params, closure_args, param_index_mapping)) + } else { + None + } } fn get_arg_if_simple(arg: &Exp) -> Option<&Exp> { @@ -606,10 +628,13 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { fn rewrite_assign(&mut self, _node_id: NodeId, lhs: &Pattern, _rhs: &Exp) -> Option { for (node_id, name) in lhs.vars() { - self.free_locals.insert(name, VarInfo { - node_id, - modified: true, - }); + self.free_locals.insert( + name, + VarInfo { + node_id, + modified: true, + }, + ); } None } @@ -618,16 +643,22 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { if matches!(oper, Operation::Borrow(ReferenceKind::Mutable)) { match args[0].as_ref() { ExpData::LocalVar(node_id, name) => { - self.free_locals.insert(*name, VarInfo { - node_id: *node_id, - modified: true, - }); + self.free_locals.insert( + *name, + VarInfo { + node_id: *node_id, + modified: true, + }, + ); }, ExpData::Temporary(node_id, param) => { - self.free_params.insert(*param, VarInfo { - node_id: *node_id, - modified: true, - }); + self.free_params.insert( + *param, + VarInfo { + node_id: *node_id, + modified: true, + }, + ); }, _ => {}, } @@ -669,7 +700,11 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { // param_index_mapping = for each free var which is a Parameter from the enclosing function, // a mapping from index there to index in the params list; other free vars are // substituted automatically by using the same symbol for the param - let (mut params, mut closure_args, param_index_mapping) = self.get_params_for_freevars(); + let Some((mut params, mut closure_args, param_index_mapping)) = + self.get_params_for_freevars() + else { + return None; + }; // Some(ExpData::Invalid(env.clone_node(id)).into_exp()); // Add lambda args. For dealing with patterns in lambdas (`|S{..}|e`) we need @@ -732,6 +767,15 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { let body = ExpRewriter::new(env, &mut replacer).rewrite_exp(body.clone()); let fun_id = FunId::new(fun_name); let params_types = params.iter().map(|param| param.get_type()).collect(); + if abilities.has_store() { + let loc = env.get_node_loc(id); + env.error( + &loc, + // TODO(LAMBDA) + "Lambdas expressions with `store` ability currently may only be a simple call to an existing `public` function. This lambda expression requires defining a `public` helper function, which might affect module upgradeability and is not yet supported." + ); + return None; + }; self.lifted.push(ClosureFunction { loc: lambda_loc.clone(), fun_id, diff --git a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs index ce120a5ca1170..96b2904f042a9 100644 --- a/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs +++ b/third_party/move/move-compiler-v2/src/file_format_generator/module_generator.rs @@ -372,7 +372,7 @@ impl ModuleGenerator { ctx.error( loc, format!( - "Unexpected type: {}", + "Unimplemented type: {}", ty.display(&ctx.env.get_type_display_ctx()) ), ); diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp new file mode 100644 index 0000000000000..c0a5cb1e19658 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.exp @@ -0,0 +1,36 @@ + +Diagnostics: +warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f` + ┌─ tests/checking/inlining/function_name_shadowing.move:8:28 + │ +8 │ public inline fun quux(f:|u64, u64|u64, a: u64, b: u64): u64 { + │ ^ + +// -- Model dump before bytecode pipeline +module 0x42::Test { + public fun f(a: u64,b: u64): u64 { + Mul(a, b) + } + public inline fun quux(f: |(u64, u64)|u64,a: u64,b: u64): u64 { + Test::f(a, b) + } + public fun test_shadowing(): u64 { + Test::f(10, 2) + } +} // end 0x42::Test + +// -- Sourcified model before bytecode pipeline +module 0x42::Test { + public fun f(a: u64, b: u64): u64 { + a * b + } + public inline fun quux(f: |(u64, u64)|u64, a: u64, b: u64): u64 { + f(a, b) + } + public fun test_shadowing(): u64 { + f(10, 2) + } +} + + +============ bytecode verification succeeded ======== diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..4867cdfbb3f88 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/function_name_shadowing.move @@ -0,0 +1,17 @@ +//# publish +module 0x42::Test { + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, a: u64, b: u64): u64 { + f(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp index 34b3ca287ce26..b67c9c02c40a7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/checking/typing/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp index d51f9b2f10bd8..53e3dfebb1e8f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda_typed.exp @@ -35,11 +35,3 @@ error: cannot pass `|&u64|u64 with copy+drop+store` to a function which expects │ 73 │ foreach(&v, |e: &u64| { sum = sum + *e; *e }) // expected to have wrong result type of lambda │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/checking/typing/lambda_typed.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp index 13fdcad48d3be..9db6927c3bd50 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/subtype_args.lambda.exp @@ -532,13 +532,13 @@ module 0x8675309::M { Diagnostics: -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/inline-parity/subtype_args.move:24:9 │ 24 │ f(&mut 0, &mut 0); │ ^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/inline-parity/subtype_args.move:25:9 │ 25 │ f(&0, &mut 0); diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda.exp index 7ee15c1c31f1f..5f6730f2fae3e 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/lambda/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp index 7ee15c1c31f1f..5f6730f2fae3e 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda.lambda.exp @@ -48,11 +48,3 @@ error: tuple type `()` is not allowed as a type argument (type was inferred) │ ^ │ = required by instantiating type parameter `T` of function `foreach` - -error: function type `|u64|u64` is not allowed as a field type - ┌─ tests/lambda/lambda.move:81:12 - │ -81 │ f: |u64|u64, // expected lambda not allowed - │ ^^^^^^^^ - │ - = required by declaration of field `f` diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp index f374630d851fb..07f8e32499a97 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda4.lambda.exp @@ -177,7 +177,7 @@ public fun M::fun_result_lambda_not_allowed(): |u64| { Diagnostics: -error: Unexpected type: |u64| +error: Unimplemented type: |u64| ┌─ tests/lambda/lambda4.move:89:16 │ 89 │ public fun fun_result_lambda_not_allowed(): |u64| { // expected lambda not allowed diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp index 0d1e3054ff2d6..799a2cceab87f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp @@ -42,41 +42,41 @@ module 0x42::test { move|y: u64| mod4::alt_multiply(5, y) } else { if Eq(key, 4) { - move|y: u64| mod3::multiply(y, 6) + move|y: u64| mod3::multiply(6, y) } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) } else { if Eq(key, 9) { - move|z: u64| test::multiply3(2, 5, z) + move|z: u64| test::multiply3(3, 5, z) } else { if Eq(key, 10) { - move|x: u64| mod4::alt_multiply(x, 11) with copy, drop + move|x: u64| mod4::alt_multiply(11, x) with copy, drop } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -85,7 +85,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -175,21 +175,21 @@ module 0x42::test { z * (x + y) } fun choose_function1(key: u64, x: u64): u64 { - let f = if (key == 0) mod2::double else if (key == 1) mod1::triple else if (key == 2) move |x| mod3::multiply(4, x) else if (key == 3) move |y| mod4::alt_multiply(5, y) else if (key == 4) move |y| mod3::multiply(y, 6) else if (key == 5) move |x| multiply3(x, 3, 2) else if (key == 6) move |x| mod3::multiply(x, 7) else if (key == 7) move |x| multiply3(4, x, 2) else if (key == 8) move |x| multiply3(3, 3, x) else if (key == 9) move |z| multiply3(2, 5, z) else if (key == 10) move |x| mod4::alt_multiply(x, 11) has copy, drop else if (key == 11) { + let f = if (key == 0) mod2::double else if (key == 1) mod1::triple else if (key == 2) move |x| mod3::multiply(4, x) else if (key == 3) move |y| mod4::alt_multiply(5, y) else if (key == 4) move |y| mod3::multiply(6, y) else if (key == 5) move |x| multiply3(3, 2, x) else if (key == 6) move |x| mod3::multiply(7, x) else if (key == 7) move |x| multiply3(4, 2, x) else if (key == 8) move |x| multiply3(3, 3, x) else if (key == 9) move |z| multiply3(3, 5, z) else if (key == 10) move |x| mod4::alt_multiply(11, x) has copy, drop else if (key == 11) { let g = move |(x,y)| mod3::multiply(x, y) has copy, drop; - move |x| g(x, 11) + move |x| g(11, x) } else if (key == 12) { - let h = move |x| mod3::multiply(x, 12) has copy, drop; + let h = move |x| mod3::multiply(12, x) has copy, drop; move |x| h(x) has copy, drop } else if (key == 14) { - let i = move |x| multiply3(2, x, 2); + let i = move |x| multiply3(2, 2, x); move |z| i(z) } else { let i = move |(x,y)| { let q = y - 1; mod3::multiply(x, q + 1) }; - move |x| i(x, 15) + move |x| i(15, x) }; f(x) } @@ -238,26 +238,26 @@ error: Function-typed values not yet supported except as parameters to calls to error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:49:17 │ -49 │ move |y| mod3::multiply(y, x) +49 │ move |y| mod3::multiply(x, y) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:51:17 │ -51 │ move |x| multiply3(x, 3, 2) +51 │ move |x| multiply3(3, 2, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:53:17 │ -53 │ move |x| mod3::multiply(x, 7) +53 │ move |x| mod3::multiply(7, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:55:17 │ -55 │ move |x| multiply3(4, x, 2) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +55 │ move |x| { multiply3(4, 2, x) } + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:57:17 @@ -268,13 +268,13 @@ error: Function-typed values not yet supported except as parameters to calls to error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:61:17 │ -61 │ move |z| multiply3(x, y, z) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +61 │ move |z| multiply3(x + 1, y, z) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:64:17 │ -64 │ move |x| alt_multiply(x, z) with copy +64 │ move |x| alt_multiply(z, x) with copy │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions @@ -286,13 +286,13 @@ error: Function-typed values not yet supported except as parameters to calls to error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:67:17 │ -67 │ move |x| g(x, 11) +67 │ move |x| g(11, x) │ ^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:69:25 │ -69 │ let h = move |x| mod3::multiply(x, 12) with copy; +69 │ let h = move |x| mod3::multiply(12, x) with copy; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions @@ -304,7 +304,7 @@ error: Function-typed values not yet supported except as parameters to calls to error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:72:25 │ -72 │ let i = move |x| multiply3(2, x, 2); +72 │ let i = move |x| multiply3(2, 2, x); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Function-typed values not yet supported except as parameters to calls to inline functions @@ -322,7 +322,7 @@ error: Function-typed values not yet supported except as parameters to calls to error: Function-typed values not yet supported except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:76:17 │ -76 │ move |x| i(x, 15) +76 │ move |x| i(15, x) │ ^^^^^^^^^^^^^^^^^ error: Calls to function values other than inline function parameters not yet supported diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp index 011277f2f46c6..27b4cb079609f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp @@ -47,17 +47,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -67,31 +67,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -100,7 +100,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -214,17 +214,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -234,31 +234,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -267,7 +267,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -381,17 +381,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -401,31 +401,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -434,7 +434,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -548,17 +548,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -568,31 +568,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -601,7 +601,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -715,17 +715,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -735,31 +735,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -768,7 +768,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -882,17 +882,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -902,31 +902,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -935,7 +935,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1049,17 +1049,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1069,31 +1069,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1102,7 +1102,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1216,17 +1216,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1236,31 +1236,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1269,7 +1269,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1383,17 +1383,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1403,31 +1403,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1436,7 +1436,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1550,17 +1550,17 @@ module 0x42::test { if Eq(key, 4) { { let x: u64 = 6; - move|y: u64| mod3::multiply(y, x) + move|y: u64| mod3::multiply(x, y) } } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) @@ -1570,31 +1570,31 @@ module 0x42::test { let x: u64 = 2; { let y: u64 = 5; - move|z: u64| test::multiply3(x, y, z) + move|z: u64| test::multiply3(Add(x, 1), y, z) } } } else { if Eq(key, 10) { { let z: u64 = 11; - move|x: u64| mod4::alt_multiply(x, z) with copy, drop + move|x: u64| mod4::alt_multiply(z, x) with copy, drop } } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1603,7 +1603,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1712,41 +1712,41 @@ module 0x42::test { move|y: u64| mod4::alt_multiply(5, y) } else { if Eq(key, 4) { - move|y: u64| mod3::multiply(y, 6) + move|y: u64| mod3::multiply(6, y) } else { if Eq(key, 5) { - move|x: u64| test::multiply3(x, 3, 2) + move|x: u64| test::multiply3(3, 2, x) } else { if Eq(key, 6) { - move|x: u64| mod3::multiply(x, 7) + move|x: u64| mod3::multiply(7, x) } else { if Eq(key, 7) { - move|x: u64| test::multiply3(4, x, 2) + move|x: u64| test::multiply3(4, 2, x) } else { if Eq(key, 8) { move|x: u64| test::multiply3(3, 3, x) } else { if Eq(key, 9) { - move|z: u64| test::multiply3(2, 5, z) + move|z: u64| test::multiply3(3, 5, z) } else { if Eq(key, 10) { - move|x: u64| mod4::alt_multiply(x, 11) with copy, drop + move|x: u64| mod4::alt_multiply(11, x) with copy, drop } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; - move|x: u64| (g)(x, 11) + move|x: u64| (g)(11, x) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + let h: |u64|u64 with copy+drop+store = move|x: u64| mod3::multiply(12, x) with copy, drop; move|x: u64| (h)(x) with copy, drop } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, x, 2); + let i: |u64|u64 with copy+drop+store = move|x: u64| test::multiply3(2, 2, x); move|z: u64| (i)(z) } } else { @@ -1755,7 +1755,7 @@ module 0x42::test { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) }; - move|x: u64| (i)(x, 15) + move|x: u64| (i)(15, x) } } } @@ -1858,47 +1858,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+drop+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+drop+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -1954,39 +1954,12 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test @@ -2034,47 +2007,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+drop+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+drop+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -2130,39 +2103,12 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test @@ -2210,47 +2156,47 @@ module 0x42::test { earlybind(mod4::alt_multiply, 5) } else { if Eq(key, 4) { - test::choose_function1$lambda$1 + earlybind(mod3::multiply, 6) } else { if Eq(key, 5) { - test::choose_function1$lambda$2 + earlybind(test::multiply3, 3, 2) } else { if Eq(key, 6) { - test::choose_function1$lambda$3 + earlybind(mod3::multiply, 7) } else { if Eq(key, 7) { - test::choose_function1$lambda$4 + earlybind(test::multiply3, 4, 2) } else { if Eq(key, 8) { earlybind(test::multiply3, 3, 3) } else { if Eq(key, 9) { - earlybind(test::multiply3, 2, 5) + earlybind(test::multiply3, 3, 5) } else { if Eq(key, 10) { - test::choose_function1$lambda$5 + earlybind(mod4::alt_multiply, 11) } else { if Eq(key, 11) { { let g: |(u64, u64)|u64 with copy+drop+store = mod3::multiply; - earlybind(test::choose_function1$lambda$6, g) + earlybind(g, 11) } } else { if Eq(key, 12) { { - let h: |u64|u64 with copy+drop+store = test::choose_function1$lambda$7; + let h: |u64|u64 with copy+drop+store = earlybind(mod3::multiply, 12); h } } else { if Eq(key, 14) { { - let i: |u64|u64 with copy+drop+store = test::choose_function1$lambda$8; + let i: |u64|u64 with copy+drop+store = earlybind(test::multiply3, 2, 2); i } } else { { - let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$9; - earlybind(test::choose_function1$lambda$10, i) + let i: |(u64, u64)|u64 with copy+drop+store = test::choose_function1$lambda$1; + earlybind(i, 15) } } } @@ -2306,159 +2252,120 @@ module 0x42::test { } } } - private fun choose_function1$lambda$1(y: u64): u64 { - mod3::multiply(y, 6) - } - private fun choose_function1$lambda$2(x: u64): u64 { - test::multiply3(x, 3, 2) - } - private fun choose_function1$lambda$3(x: u64): u64 { - mod3::multiply(x, 7) - } - private fun choose_function1$lambda$4(x: u64): u64 { - test::multiply3(4, x, 2) - } - private fun choose_function1$lambda$5(x: u64): u64 { - mod4::alt_multiply(x, 11) - } - private fun choose_function1$lambda$6(g: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (g)(x, 11) - } - private fun choose_function1$lambda$7(x: u64): u64 { - mod3::multiply(x, 12) - } - private fun choose_function1$lambda$8(x: u64): u64 { - test::multiply3(2, x, 2) - } - private fun choose_function1$lambda$9(x: u64,y: u64): u64 { + private fun choose_function1$lambda$1(x: u64,y: u64): u64 { { let q: u64 = Sub(y, 1); mod3::multiply(x, Add(q, 1)) } } - private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+drop+store,x: u64): u64 { - (i)(x, 15) - } } // end 0x42::test Diagnostics: -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:39:17 │ 39 │ mod2::double │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:41:17 │ 41 │ mod1::triple │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:43:17 │ 43 │ move |x| mod3::multiply(4, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:46:17 │ 46 │ move |y| alt_multiply(x, y) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:49:17 │ -49 │ move |y| mod3::multiply(y, x) +49 │ move |y| mod3::multiply(x, y) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:51:17 │ -51 │ move |x| multiply3(x, 3, 2) +51 │ move |x| multiply3(3, 2, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:53:17 │ -53 │ move |x| mod3::multiply(x, 7) +53 │ move |x| mod3::multiply(7, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:55:17 │ -55 │ move |x| multiply3(4, x, 2) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +55 │ move |x| { multiply3(4, 2, x) } + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:57:17 │ 57 │ move |x| multiply3(3, 3, x) │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:61:17 │ -61 │ move |z| multiply3(x, y, z) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +61 │ move |z| multiply3(x + 1, y, z) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:64:17 │ -64 │ move |x| alt_multiply(x, z) with copy +64 │ move |x| alt_multiply(z, x) with copy │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:66:37 │ 66 │ let g = move |x, y| mod3::multiply(x, y) with copy+drop; │ ^^^^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/storable/doable_func.move:67:26 - │ -67 │ move |x| g(x, 11) - │ ^^^^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:67:17 │ -67 │ move |x| g(x, 11) +67 │ move |x| g(11, x) │ ^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:69:25 │ -69 │ let h = move |x| mod3::multiply(x, 12) with copy; +69 │ let h = move |x| mod3::multiply(12, x) with copy; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:72:25 │ -72 │ let i = move |x| multiply3(2, x, 2); +72 │ let i = move |x| multiply3(2, 2, x); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:75:25 │ 75 │ let i = move |x, y| { let q = y - 1; 0x42::mod3::multiply(x, q + 1) }; │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/storable/doable_func.move:76:26 - │ -76 │ move |x| i(x, 15) - │ ^^^^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Function-typed values not yet implemented except as parameters to calls to inline functions ┌─ tests/lambda/storable/doable_func.move:76:17 │ -76 │ move |x| i(x, 15) +76 │ move |x| i(15, x) │ ^^^^^^^^^^^^^^^^^ -error: Calls to function values other than inline function parameters not yet supported +error: Calls to function values other than inline function parameters not yet implemented ┌─ tests/lambda/storable/doable_func.move:78:9 │ 78 │ f(x) diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move index aa699a91d949f..bedfeff20188d 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move @@ -46,34 +46,34 @@ module 0x42::test { move |y| alt_multiply(x, y) } else if (key == 4) { let x = 6; - move |y| mod3::multiply(y, x) + move |y| mod3::multiply(x, y) } else if (key == 5) { - move |x| multiply3(x, 3, 2) + move |x| multiply3(3, 2, x) } else if (key == 6) { - move |x| mod3::multiply(x, 7) + move |x| mod3::multiply(7, x) } else if (key == 7) { - move |x| multiply3(4, x, 2) + move |x| { multiply3(4, 2, x) } } else if (key == 8) { move |x| multiply3(3, 3, x) } else if (key == 9) { let x = 2; let y = 5; - move |z| multiply3(x, y, z) + move |z| multiply3(x + 1, y, z) } else if (key == 10) { let z = 11; - move |x| alt_multiply(x, z) with copy + move |x| alt_multiply(z, x) with copy } else if (key == 11) { let g = move |x, y| mod3::multiply(x, y) with copy+drop; - move |x| g(x, 11) + move |x| g(11, x) } else if (key == 12) { - let h = move |x| mod3::multiply(x, 12) with copy; + let h = move |x| mod3::multiply(12, x) with copy; move |x| { h(x) } with copy + drop } else if (key == 14) { - let i = move |x| multiply3(2, x, 2); + let i = move |x| multiply3(2, 2, x); move |z| i(z) } else { let i = move |x, y| { let q = y - 1; 0x42::mod3::multiply(x, q + 1) }; - move |x| i(x, 15) + move |x| i(15, x) }; f(x) } diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp index ecf9d3ef2b24e..cbc13fef38936 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp @@ -1,23 +1,10 @@ Diagnostics: -error: function type `|u64|u64 with drop+store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_errors.move:9:12 - │ -9 │ f: |u64| u64 with store, - │ ^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_errors.move:22:21 - │ -13 │ enum Option { - │ - declaration of type parameter `T` - · -22 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ +error: cannot return `Option<|u64|u64 with drop+store>` from a function with result type `Option` + ┌─ tests/lambda/storable/registry_errors.move:25:9 │ - = required by instantiating type parameter `T` of struct `Option` +25 │ x + │ ^ error: expected `&mut Function` but found a value of type `|u64|u64 with drop+store` ┌─ tests/lambda/storable/registry_errors.move:32:17 diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp index ecf9d3ef2b24e..cbc13fef38936 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp @@ -1,23 +1,10 @@ Diagnostics: -error: function type `|u64|u64 with drop+store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_errors.move:9:12 - │ -9 │ f: |u64| u64 with store, - │ ^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_errors.move:22:21 - │ -13 │ enum Option { - │ - declaration of type parameter `T` - · -22 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ +error: cannot return `Option<|u64|u64 with drop+store>` from a function with result type `Option` + ┌─ tests/lambda/storable/registry_errors.move:25:9 │ - = required by instantiating type parameter `T` of struct `Option` +25 │ x + │ ^ error: expected `&mut Function` but found a value of type `|u64|u64 with drop+store` ┌─ tests/lambda/storable/registry_errors.move:32:17 diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp index 06a87d33176e8..986618ee47883 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp @@ -1,77 +1,266 @@ +// -- Model dump before bytecode pipeline +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } -Diagnostics: -error: function type `|u64|u64 with drop+store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_ok.move:9:12 - │ -9 │ f: |u64| u64 with store, - │ ^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_ok.move:22:21 - │ -13 │ enum Option { - │ - declaration of type parameter `T` - · -22 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ - │ - = required by instantiating type parameter `T` of struct `Option` - -error: expected `&mut Function` but found a value of type `|u64|u64 with drop+store` - ┌─ tests/lambda/storable/registry_ok.move:32:17 - │ -32 │ f.f = f; - │ ^^^ - -error: undeclared receiver function `append` for type `vector` - ┌─ tests/lambda/storable/registry_ok.move:38:13 - │ -38 │ v.append(new_record); - │ ^^^^^^^^^^^^^^^^^^^^ + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } -error: cannot return nothing from a function with result type `Option` - ┌─ tests/lambda/storable/registry_ok.move:38:33 - │ -38 │ v.append(new_record); - │ ^ + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test -error: cannot return nothing from a function with result type `Option` - ┌─ tests/lambda/storable/registry_ok.move:36:9 - │ -36 │ ╭ if (!done) { -37 │ │ let new_record = Function { f: f, key: k }; -38 │ │ v.append(new_record); -39 │ │ } - │ ╰─────────^ +// -- Sourcified model before bytecode pipeline +module 0x42::test { + struct FunctionEntry has copy, drop, store { + f: FunctionValue, + key: u64, + } + struct FunctionValue has copy, drop, store { + 0: |u64|u64 with copy+drop+store, + } + enum Option has copy, store { + None, + Some { + 0: T, + } + } + struct Registry has key { + functions: vector, + } + fun double(x: u64): u64 { + x * 2 + } + fun get_function(v: &vector, k: u64): Option { + let x = Option::None{}; + { + let (v) = (v); + let i = 0; + while (i < 0x1::vector::length(v)) { + { + let (f) = (0x1::vector::borrow(v, i)); + if (f.key == k) x = Option::Some(f.f) + }; + i = i + 1 + } + }; + x + } + fun invoke(addr: address, k: u64, x: u64): Option + acquires Registry + { + if (!exists(addr)) return Option::None{}; + let registry = borrow_global(addr); + match (get_function(®istry.functions, k)) { + Option::Some(f) => Option::Some(f.0(x)), + _ => Option::None{}, + } + } + public fun multiply(x: u64, y: u64): u64 { + x * y + } + fun multiply_by_x(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) + } + fun multiply_by_x2(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) + } + fun register(owner: &signer, f: FunctionValue, k: u64) + acquires Registry + { + let addr = 0x1::signer::address_of(owner); + if (!exists(addr)) { + let new_registry = Registry{functions: vector[]}; + move_to(owner, new_registry); + }; + let registry = borrow_global_mut(addr); + replace_or_add_function(&mut registry.functions, k, f); + } + fun replace_or_add_function(v: &mut vector, k: u64, f: FunctionValue): Option { + let result = Option::None{}; + { + let (v) = (v); + let i = 0; + while (i < 0x1::vector::length(/*freeze*/v)) { + { + let (record) = (0x1::vector::borrow_mut(v, i)); + if (record.key == k) { + let old_f = record.f; + record.f = f; + result = Option::Some(old_f); + } + }; + i = i + 1 + } + }; + match (result) { + Option::None{} => { + let new_record = FunctionEntry{f: f,key: k}; + 0x1::vector::push_back(v, new_record); + Option::None{} + }, + Option::Some(_) => result, + } + } + fun triple(x: u64): u64 { + x * 3 + } +} -error: expected a struct with field `address` but found `signer` - ┌─ tests/lambda/storable/registry_ok.move:43:20 - │ -43 │ let addr = owner.address; - │ ^^^^^ -error: undeclared `registry` - ┌─ tests/lambda/storable/registry_ok.move:48:38 - │ -48 │ move_to(owner, registry); - │ ^^^^^^^^ - -error: cannot pass `vector` to a function which expects argument of type `&vector` - ┌─ tests/lambda/storable/registry_ok.move:59:29 +Diagnostics: +error: Calls to function values other than inline function parameters not yet supported + ┌─ tests/lambda/storable/registry_ok.move:71:30 │ -59 │ match (get_function(registry.functions, k)) { - │ ^^^^^^^^^^^^^^^^^^ +71 │ Option::Some((f.0)(x)) + │ ^^^^^^^^ -error: undeclared struct `test::Some` - ┌─ tests/lambda/storable/registry_ok.move:60:13 +error: Function-typed values not yet supported except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok.move:92:23 │ -60 │ Some(func) => { - │ ^^^^ +92 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^^^^^^^^^^^^^^^^^^^^ -error: undeclared `func` - ┌─ tests/lambda/storable/registry_ok.move:61:51 +error: Function-typed values not yet supported except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok.move:96:23 │ -61 │ let Function { f: f, key: key } = func; - │ ^^^^ +96 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp index 06a87d33176e8..0eada787c0a80 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp @@ -1,77 +1,1909 @@ +// -- Model dump before env processor pipeline: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } -Diagnostics: -error: function type `|u64|u64 with drop+store` is not allowed as a field type - ┌─ tests/lambda/storable/registry_ok.move:9:12 - │ -9 │ f: |u64| u64 with store, - │ ^^^^^^^^^^^^^^^^^^^^ - │ - = required by declaration of field `f` - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/registry_ok.move:22:21 - │ -13 │ enum Option { - │ - declaration of type parameter `T` - · -22 │ x = Option::Some(f.f) - │ ^^^^^^^^^^^^ - │ - = required by instantiating type parameter `T` of struct `Option` + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } -error: expected `&mut Function` but found a value of type `|u64|u64 with drop+store` - ┌─ tests/lambda/storable/registry_ok.move:32:17 - │ -32 │ f.f = f; - │ ^^^ + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test -error: undeclared receiver function `append` for type `vector` - ┌─ tests/lambda/storable/registry_ok.move:38:13 - │ -38 │ v.append(new_record); - │ ^^^^^^^^^^^^^^^^^^^^ -error: cannot return nothing from a function with result type `Option` - ┌─ tests/lambda/storable/registry_ok.move:38:33 - │ -38 │ v.append(new_record); - │ ^ +// -- Model dump after env processor unused checks: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } -error: cannot return nothing from a function with result type `Option` - ┌─ tests/lambda/storable/registry_ok.move:36:9 - │ -36 │ ╭ if (!done) { -37 │ │ let new_record = Function { f: f, key: k }; -38 │ │ v.append(new_record); -39 │ │ } - │ ╰─────────^ - -error: expected a struct with field `address` but found `signer` - ┌─ tests/lambda/storable/registry_ok.move:43:20 - │ -43 │ let addr = owner.address; - │ ^^^^^ + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test -error: undeclared `registry` - ┌─ tests/lambda/storable/registry_ok.move:48:38 - │ -48 │ move_to(owner, registry); - │ ^^^^^^^^ -error: cannot pass `vector` to a function which expects argument of type `&vector` - ┌─ tests/lambda/storable/registry_ok.move:59:29 +// -- Model dump after env processor inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue( move|y: u64| test::multiply(x, y)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor lambda-lifting: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification checker: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification rewriter: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: FunctionValue, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option { + { + let x: Option = pack test::Option::None(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option = pack test::Option::Some(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some{ 0: f } => { + pack test::Option::Some((select test::FunctionValue.0(f))(x)) + } + _: Option => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun multiply_by_x2(x: u64): FunctionValue { + pack test::FunctionValue(earlybind(test::multiply, x)) + } + private fun register(owner: &signer,f: FunctionValue,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: FunctionValue): Option { + { + let result: Option = pack test::Option::None(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: FunctionValue = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option = pack test::Option::Some(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None() + } + } + test::Option::Some{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + + +Diagnostics: +error: Calls to function values other than inline function parameters not yet implemented + ┌─ tests/lambda/storable/registry_ok.move:71:30 │ -59 │ match (get_function(registry.functions, k)) { - │ ^^^^^^^^^^^^^^^^^^ +71 │ Option::Some((f.0)(x)) + │ ^^^^^^^^ -error: undeclared struct `test::Some` - ┌─ tests/lambda/storable/registry_ok.move:60:13 +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok.move:92:23 │ -60 │ Some(func) => { - │ ^^^^ +92 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^^^^^^^^^^^^^^^^^^^^ -error: undeclared `func` - ┌─ tests/lambda/storable/registry_ok.move:61:51 +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok.move:96:23 │ -61 │ let Function { f: f, key: key } = func; - │ ^^^^ +96 │ FunctionValue(move |y| multiply(x, y)) + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move index 94bbb7c7afdfe..33df5f2465f73 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move @@ -1,23 +1,26 @@ module 0x42::test { + use std::signer; use std::vector; + struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + struct Registry has key { - functions: vector + functions: vector } - struct Function has store { - f: |u64| u64 with store, + struct FunctionEntry has store, copy, drop { + f: FunctionValue, key: u64 } - enum Option { + enum Option has store, copy { None(), Some(T) } - fun get_function(v: &vector, k: u64): Option { + fun get_function(v: &vector, k: u64): Option { let x = Option::None; - vector::for_each_ref(v, |f: &Function| { + vector::for_each_ref(v, |f: &FunctionEntry| { if (f.key == k) { x = Option::Some(f.f) } @@ -25,27 +28,34 @@ module 0x42::test { x } - fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store): Option { - let done = false; - vector::for_each_mut(v, |f: &mut Function| { - if (f.key == k) { - f.f = f; - done = true; + fun replace_or_add_function(v: &mut vector, k: u64, f: FunctionValue): Option { + let result = Option::None; + vector::for_each_mut(v, |record: &mut FunctionEntry| { + if (record.key == k) { + let old_f = record.f; + record.f = f; + result = Option::Some(old_f); } }); - if (!done) { - let new_record = Function { f: f, key: k }; - v.append(new_record); + match (result) { + Option::None => { + let new_record = FunctionEntry { f: f, key: k }; + vector::push_back(v, new_record); + Option::None + }, + Option::Some(_) => { + result + } } } - fun register(owner: &signer, f: |u64| u64 with store, k: u64) acquires Registry { - let addr = owner.address; + fun register(owner: &signer, f: FunctionValue, k: u64) acquires Registry { + let addr = signer::address_of(owner); if (!exists(addr)) { let new_registry = Registry { functions: vector[] }; - move_to(owner, registry); + move_to(owner, new_registry); }; let registry = borrow_global_mut(addr); replace_or_add_function(&mut registry.functions, k, f); @@ -56,10 +66,9 @@ module 0x42::test { return Option::None }; let registry = borrow_global(addr); - match (get_function(registry.functions, k)) { - Some(func) => { - let Function { f: f, key: key } = func; - Some(f(x)) + match (get_function(®istry.functions, k)) { + Option::Some(f) => { + Option::Some((f.0)(x)) }, _ => { Option::None @@ -79,12 +88,12 @@ module 0x42::test { x * y } - fun multiply_by_x(x: u64): |u64|u64 with store { - |y| multiply(x, y) + fun multiply_by_x(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) } - fun multiply_by_x2(x: u64): |u64|u64 with store { - move |y| multiply(x, y) + fun multiply_by_x2(x: u64): FunctionValue { + FunctionValue(move |y| multiply(x, y)) } #[test(a = @0x42)] diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp new file mode 100644 index 0000000000000..1287939adff35 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: Only inline functions may have function-typed parameters, but non-inline function `test::replace_or_add_function` has a function parameter: + ┌─ tests/lambda/storable/registry_ok2.move:31:9 + │ +31 │ fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^^^^^^^^^ - Parameter `f` has function-valued type `|u64|u64 with copy+drop+store`. + +error: Only inline functions may have function-typed parameters, but non-inline function `test::register` has a function parameter: + ┌─ tests/lambda/storable/registry_ok2.move:52:9 + │ +52 │ fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { + │ ^^^^^^^^ - Parameter `f` has function-valued type `|u64|u64 with copy+drop+store`. + +error: Functions may not return function-typed values, but function `test::multiply_by_x` return type is the function type `|u64|u64 with copy+drop+store`: + ┌─ tests/lambda/storable/registry_ok2.move:91:32 + │ +91 │ fun multiply_by_x(x: u64): |u64| u64 with store+copy { + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Functions may not return function-typed values, but function `test::multiply_by_x2` return type is the function type `|u64|u64 with copy+drop+store`: + ┌─ tests/lambda/storable/registry_ok2.move:95:33 + │ +95 │ fun multiply_by_x2(x: u64): |u64| u64 with store+copy { + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp new file mode 100644 index 0000000000000..b80a2428f9a87 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.lambda.exp @@ -0,0 +1,1909 @@ +// -- Model dump before env processor pipeline: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused checks: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_ref(v, |f: &FunctionEntry| if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + }); + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + vector::for_each_mut(v, |record: &mut FunctionEntry| if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + }); + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + move|y: u64| test::multiply(x, y) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor lambda-lifting: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification checker: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor specification rewriter: +module 0x42::test { + use std::signer; + use std::vector; + struct FunctionEntry { + f: |u64|u64 with copy+drop+store, + key: u64, + } + struct FunctionValue { + 0: |u64|u64 with copy+drop+store, + } + enum Option { + None, + Some { + 0: T, + } + } + struct Registry { + functions: vector, + } + private fun double(x: u64): u64 { + Mul(x, 2) + } + private fun get_function(v: &vector,k: u64): Option<|u64|u64 with copy+drop+store> { + { + let x: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &vector): (&vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(v)) { + { + let (f: &FunctionEntry): (&FunctionEntry) = Tuple(vector::borrow(v, i)); + if Eq(select test::FunctionEntry.key<&FunctionEntry>(f), k) { + x: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(select test::FunctionEntry.f<&FunctionEntry>(f)) + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + x + } + } + private fun invoke(addr: address,k: u64,x: u64): Option + acquires Registry(*) + { + if Not(exists(addr)) { + return pack test::Option::None() + } else { + Tuple() + }; + { + let registry: &Registry = BorrowGlobal(Immutable)(addr); + match (test::get_function(Borrow(Immutable)(select test::Registry.functions<&Registry>(registry)), k)) { + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: f } => { + pack test::Option::Some((f)(x)) + } + _: Option<|u64|u64 with copy+drop+store> => { + pack test::Option::None() + } + } + + } + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + private fun multiply_by_x(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun multiply_by_x2(x: u64): |u64|u64 with copy+drop+store { + earlybind(test::multiply, x) + } + private fun register(owner: &signer,f: |u64|u64 with copy+drop+store,k: u64) + acquires Registry(*) + { + { + let addr: address = signer::address_of(owner); + if Not(exists(addr)) { + { + let new_registry: Registry = pack test::Registry(Vector()); + MoveTo(owner, new_registry); + Tuple() + } + } else { + Tuple() + }; + { + let registry: &mut Registry = BorrowGlobal(Mutable)(addr); + test::replace_or_add_function(Borrow(Mutable)(select test::Registry.functions<&mut Registry>(registry)), k, f); + Tuple() + } + } + } + private fun replace_or_add_function(v: &mut vector,k: u64,f: |u64|u64 with copy+drop+store): Option<|u64|u64 with copy+drop+store> { + { + let result: Option<|u64|u64 with copy+drop+store> = pack test::Option::None<|u64|u64 with copy+drop+store>(); + { + let (v: &mut vector): (&mut vector) = Tuple(v); + { + let i: u64 = 0; + loop { + if Lt(i, vector::length(Freeze(false)(v))) { + { + let (record: &mut FunctionEntry): (&mut FunctionEntry) = Tuple(vector::borrow_mut(v, i)); + if Eq(select test::FunctionEntry.key<&mut FunctionEntry>(record), k) { + { + let old_f: |u64|u64 with copy+drop+store = select test::FunctionEntry.f<&mut FunctionEntry>(record); + select test::FunctionEntry.f<&mut FunctionEntry>(record) = f; + result: Option<|u64|u64 with copy+drop+store> = pack test::Option::Some<|u64|u64 with copy+drop+store>(old_f); + Tuple() + } + } else { + Tuple() + } + }; + i: u64 = Add(i, 1) + } else { + break + } + } + } + }; + match (result) { + test::Option::None<|u64|u64 with copy+drop+store> => { + { + let new_record: FunctionEntry = pack test::FunctionEntry(f, k); + vector::push_back(v, new_record); + pack test::Option::None<|u64|u64 with copy+drop+store>() + } + } + test::Option::Some<|u64|u64 with copy+drop+store>{ 0: _ } => { + result + } + } + + } + } + private fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + + +Diagnostics: +error: Calls to function values other than inline function parameters not yet implemented + ┌─ tests/lambda/storable/registry_ok2.move:71:30 + │ +71 │ Option::Some(f(x)) + │ ^^^^ + +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok2.move:92:9 + │ +92 │ move |y| multiply(x, y) + │ ^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet implemented except as parameters to calls to inline functions + ┌─ tests/lambda/storable/registry_ok2.move:96:9 + │ +96 │ move |y| multiply(x, y) + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move new file mode 100644 index 0000000000000..fbfd16c17475d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok2.move @@ -0,0 +1,128 @@ +module 0x42::test { + use std::signer; + use std::vector; + + struct FunctionValue(|u64| u64 with store+copy) has store, copy, drop; + + struct Registry has key { + functions: vector + } + + struct FunctionEntry has store, copy, drop { + f: |u64| u64 with store+copy, + key: u64 + } + + enum Option has store, copy { + None(), + Some(T) + } + + fun get_function(v: &vector, k: u64): Option<|u64| u64 with store+copy> { + let x = Option::None; + vector::for_each_ref(v, |f: &FunctionEntry| { + if (f.key == k) { + x = Option::Some(f.f) + } + }); + x + } + + fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + let result = Option::None; + vector::for_each_mut(v, |record: &mut FunctionEntry| { + if (record.key == k) { + let old_f = record.f; + record.f = f; + result = Option::Some(old_f); + } + }); + match (result) { + Option::None => { + let new_record = FunctionEntry { f: f, key: k }; + vector::push_back(v, new_record); + Option::None + }, + Option::Some(_) => { + result + } + } + } + + fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { + let addr = signer::address_of(owner); + if (!exists(addr)) { + let new_registry = Registry { + functions: vector[] + }; + move_to(owner, new_registry); + }; + let registry = borrow_global_mut(addr); + replace_or_add_function(&mut registry.functions, k, f); + } + + fun invoke(addr: address, k: u64, x: u64): Option acquires Registry { + if (!exists(addr)) { + return Option::None + }; + let registry = borrow_global(addr); + match (get_function(®istry.functions, k)) { + Option::Some(f) => { + Option::Some(f(x)) + }, + _ => { + Option::None + } + } + } + + fun double(x: u64):u64 { + x * 2 + } + + fun triple(x: u64):u64 { + x * 3 + } + + public fun multiply(x: u64, y: u64): u64 { + x * y + } + + fun multiply_by_x(x: u64): |u64| u64 with store+copy { + move |y| multiply(x, y) + } + + fun multiply_by_x2(x: u64): |u64| u64 with store+copy { + move |y| multiply(x, y) + } + + #[test(a = @0x42)] + fun test_registry1(a: signer) { + register(a, double, 2); + register(a, negate, 3); + register(a, multiply_by_x(4), 4); + register(a, multiply_by_x(5), 5); + register(a, multiply_by_x2(6), 6); + + match (invoke(a, 2, 10)) { + Some(x) => { assert!(x == 20); } + _ => assert!(false) + }; + match (invoke(a, 3, 11)) { + Some(x) => { assert!(x == 33); } + _ => assert!(false) + }; + match (invoke(a, 4, 2)) { + Some(x) => { assert!(x == 8); } + _ => assert!(false) + }; + match (invoke(a, 5, 3)) { + Some(x) => { assert!(x == 15); } + _ => assert!(false) + }; + match (invoke(a, 6, 3)) { + Some(x) => { assert!(x == 18); } + _ => assert!(false) + }; + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.exp index ed308fd87bf5e..2c7eee6decfb3 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.exp @@ -29,19 +29,3 @@ error: expected `|integer|_ with copy+drop+store` but found a value of type `u64 │ 87 │ vector::push_back(&mut sum, h(6)); │ ^^^^ - -error: function type `|integer|_` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp index ed308fd87bf5e..2c7eee6decfb3 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.lambda.exp @@ -29,19 +29,3 @@ error: expected `|integer|_ with copy+drop+store` but found a value of type `u64 │ 87 │ vector::push_back(&mut sum, h(6)); │ ^^^^ - -error: function type `|integer|_` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter - -error: function type `|u64|u64 with drop+store` is not allowed as a type argument (type was inferred) - ┌─ tests/lambda/storable/return_func.move:89:21 - │ -89 │ let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; - │ ^^^^^^ - │ - = required by instantiating vector type parameter diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp new file mode 100644 index 0000000000000..8c981a7cca003 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.exp @@ -0,0 +1,37 @@ + +Diagnostics: +error: Functions may not return function-typed values, but function `test::multiply_by_x` return type is the function type `|u64|u64 with drop+store`: + ┌─ tests/lambda/storable/return_func_ok.move:20:32 + │ +20 │ fun multiply_by_x(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^^^^^^^^^^ + +error: Functions may not return function-typed values, but function `test::choose_function` return type is the function type `|u64|u64 with drop+store`: + ┌─ tests/lambda/storable/return_func_ok.move:24:37 + │ +24 │ fun choose_function(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^^^^^^^^^^ + +error: Functions may not return function-typed values, but function `test::choose_function2` return type is the function type `|u64|u64 with drop+store`: + ┌─ tests/lambda/storable/return_func_ok.move:34:37 + │ +34 │ fun choose_function2(key: u64): |u64|u64 with store { + │ ^^^^^^^^^^^^^^^^^^^ + +error: Functions may not return function-typed values, but function `test::choose_function3` return type is the function type `|u64|u64 with drop+store`: + ┌─ tests/lambda/storable/return_func_ok.move:61:38 + │ +61 │ fun choose_function3(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^^^^^^^^^^ + +error: Functions may not return function-typed values, but function `test::test_functions` has a parameter of function type with function-typed result: + ┌─ tests/lambda/storable/return_func_ok.move:74:16 + │ +74 │ public fun test_functions(choose_function_arg: |u64|(|u64|u64 with store)) { + │ ^^^^^^^^^^^^^^ ------------------- Parameter `choose_function_arg` has type `|u64||u64|u64 with drop+store`, which has function type `|u64|u64 with drop+store` as a function result type + +error: Only inline functions may have function-typed parameters, but non-inline function `test::test_functions` has a function parameter: + ┌─ tests/lambda/storable/return_func_ok.move:74:16 + │ +74 │ public fun test_functions(choose_function_arg: |u64|(|u64|u64 with store)) { + │ ^^^^^^^^^^^^^^ ------------------- Parameter `choose_function_arg` has function-valued type `|u64||u64|u64 with drop+store`. diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp new file mode 100644 index 0000000000000..480b3c11e7a60 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.lambda.exp @@ -0,0 +1,1572 @@ +// -- Model dump before env processor pipeline: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused checks: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + { + let x: u64 = 3; + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(x)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(x)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, Vector(6, 9, 12, 10, 21, 24, 18, 33, 52)) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::test { + use std::vector; + private fun choose_function(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + test::double + } else { + if Eq(key, 1) { + test::triple + } else { + test::multiply_by_x(4) + } + } + } + private fun choose_function2(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + move|x: u64| test::double(x) with drop, store + } else { + if Eq(key, 1) { + move|x: u64| test::triple(x) with drop, store + } else { + if Eq(key, 2) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(4); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 3) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 4) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + f + } + } else { + if Eq(key, 5) { + move|y: u64| test::multiply(y, 7) with drop, store + } else { + if Eq(key, 6) { + { + let f: |u64|u64 with copy+drop+store = move|y: u64| test::multiply(6, y) with drop, store; + move|x: u64| (f)(x) with drop, store + } + } else { + if Eq(key, 7) { + { + let f: |u64|u64 with drop+store = test::multiply_by_x(5); + move|x: u64| (f)(x) with drop, store + } + } else { + move|y: u64| test::multiply3(y, 3, 4) with drop, store + } + } + } + } + } + } + } + } + } + private fun choose_function3(key: u64): |u64|u64 with drop+store { + if Eq(key, 0) { + { + let f: |u64|u64 with copy+drop+store = move|x: u64| test::double(x) with drop, store; + f + } + } else { + if Eq(key, 1) { + { + let g: |u64|u64 with copy+drop+store = move|x: u64| test::triple(x) with drop, store; + g + } + } else { + { + let h: |u64|u64 with drop+store = test::multiply_by_x(4); + h + } + } + } + } + public fun double(x: u64): u64 { + Mul(x, 2) + } + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } + public fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + private fun multiply_by_x(x: u64): |u64|u64 with drop+store { + move|y: u64| test::multiply(x, y) with drop, store + } + public fun test_function_choosers() { + test::test_functions(test::choose_function); + test::test_functions(test::choose_function2); + test::test_functions(test::choose_function3); + Tuple() + } + public fun test_functions(choose_function_arg: |u64||u64|u64 with drop+store) { + { + let sum: vector = Vector(); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(0))(3)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(1))(3)); + vector::push_back(Borrow(Mutable)(sum), ((choose_function_arg)(2))(3)); + { + let g: |u64|u64 with drop+store = test::choose_function(1); + { + let h: |u64|u64 with drop+store = test::choose_function(2); + { + let f: |u64|u64 with drop+store = test::choose_function(0); + vector::push_back(Borrow(Mutable)(sum), (f)(5)); + vector::push_back(Borrow(Mutable)(sum), (g)(7)); + vector::push_back(Borrow(Mutable)(sum), (h)(6)); + { + let funcs: vector<|u64|u64 with drop+store> = Vector<|u64|u64 with drop+store>(test::choose_function(0), test::choose_function(1), test::choose_function(2)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 0)))(9)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 1)))(11)); + vector::push_back(Borrow(Mutable)(sum), (Deref(vector::borrow<|u64|u64>(Borrow(Immutable)(funcs), 2)))(13)); + if Eq>(sum, [Number(6), Number(9), Number(12), Number(10), Number(21), Number(24), Number(18), Number(33), Number(52)]) { + Tuple() + } else { + Abort(14566554180833181696) + } + } + } + } + } + } + } + public fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::test + + + +Diagnostics: +error: Lambdas expressions with `store` ability currently may only be a simple call to an existing `public` function. This lambda expression requires defining a `public` helper function, which might affect module upgradeability and is not yet supported. + ┌─ tests/lambda/storable/return_func_ok.move:49:13 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Lambdas expressions with `store` ability currently may only be a simple call to an existing `public` function. This lambda expression requires defining a `public` helper function, which might affect module upgradeability and is not yet supported. + ┌─ tests/lambda/storable/return_func_ok.move:57:13 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move new file mode 100644 index 0000000000000..d3524875d9020 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func_ok.move @@ -0,0 +1,106 @@ +module 0x42::test { + use std::vector; + + public fun double(x: u64): u64 { + x * 2 + } + + public fun triple(x: u64) : u64 { + x * 3 + } + + public fun multiply(x: u64, y: u64): u64 { + x * y + } + + public fun multiply3(x: u64, y: u64, z: u64): u64 { + x * y * z + } + + fun multiply_by_x(x: u64): |u64|u64 with store { + move |y| multiply(x, y) with store + } + + fun choose_function(key: u64) : |u64|u64 with store { + if (key == 0) { + double + } else if (key == 1) { + triple + } else { + multiply_by_x(4) + } + } + + fun choose_function2(key: u64): |u64|u64 with store { + if (key == 0) { + move |x| double(x) with store + } else if (key == 1) { + move |x| triple(x) with store + } else if (key == 2) { + let f = multiply_by_x(4); + move |x| f(x) with store + } else if (key == 3) { + let f = multiply_by_x(5); + move |x| f(x) with store + } else if (key == 4) { + let f = move |y| multiply(6, y) with store; + f + } else if (key == 5) { + move |y| multiply(y, 7) with store + } else if (key == 6) { + let f = move |y| multiply(6, y) with store; + move |x| f(x) with store + } else if (key == 7) { + let f = multiply_by_x(5); + move |x| f(x) with store + } else { + move |y| multiply3(y, 3, 4) with store + } + } + + fun choose_function3(key: u64) : |u64|u64 with store { + if (key == 0) { + let f = move |x| double(x) with store; + f + } else if (key == 1) { + let g = move |x| triple(x) with store; + g + } else { + let h = multiply_by_x(4); + h + } + } + + public fun test_functions(choose_function_arg: |u64|(|u64|u64 with store)) { + let sum = vector[]; + let x = 3; + // Note that currently we can only resolve a local var as a + // function value in a call if (1) there is no existing function with that name, + // or (2) the function name is in parentheses, to distinguish from an + // old-fashioned function call. + vector::push_back(&mut sum, (choose_function_arg(0))(x)); + vector::push_back(&mut sum, choose_function_arg(1)(x)); + vector::push_back(&mut sum, (choose_function_arg(2))(x)); + + let g = choose_function(1); + let h = choose_function(2); + let f = choose_function(0); + + vector::push_back(&mut sum, f(5)); + vector::push_back(&mut sum, g(7)); + vector::push_back(&mut sum, h(6)); + + let funcs = vector[choose_function(0), choose_function(1), choose_function(2)]; + vector::push_back(&mut sum, funcs[0](9)); + vector::push_back(&mut sum, funcs[1](11)); + vector::push_back(&mut sum, funcs[2](13)); + + assert!(sum == vector[6, 9, 12, 10, 21, 24, 18, 33, 52]) + } + + public fun test_function_choosers() { + test_functions(choose_function); + test_functions(choose_function2); + test_functions(choose_function3); + } +} diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp new file mode 100644 index 0000000000000..09aafe1f066eb --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.exp @@ -0,0 +1,15 @@ +comparison between v1 and v2 failed: += processed 2 tasks += ++ task 0 'publish'. lines 1-15: ++ warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f` ++ ┌─ TEMPFILE:6:28 ++ │ ++ 6 │ public inline fun quux(f:|u64, u64|u64, a: u64, b: u64): u64 { ++ │ ^ ++ ++ ++ += task 1 'run'. lines 17-17: += return values: 20 += diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move new file mode 100644 index 0000000000000..4867cdfbb3f88 --- /dev/null +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/function_name_shadowing.move @@ -0,0 +1,17 @@ +//# publish +module 0x42::Test { + + public fun f(a: u64, b: u64): u64 { + a * b + } + + public inline fun quux(f:|u64, u64|u64, a: u64, b: u64): u64 { + f(a, b) + } + + public fun test_shadowing(): u64 { + quux(|a, b| a - b, 10, 2) + } +} + +//# run 0x42::Test::test_shadowing diff --git a/third_party/move/move-model/src/sourcifier.rs b/third_party/move/move-model/src/sourcifier.rs index d8f4fa88aefa9..13de8c8d28e82 100644 --- a/third_party/move/move-model/src/sourcifier.rs +++ b/third_party/move/move-model/src/sourcifier.rs @@ -241,15 +241,18 @@ impl<'a> Sourcifier<'a> { Value::Number(int) => { emit!(self.writer, "{}", int); if let Some(Type::Primitive(prim)) = ty { - emit!(self.writer, match prim { - PrimitiveType::U8 => "u8", - PrimitiveType::U16 => "u16", - PrimitiveType::U32 => "u32", - PrimitiveType::U64 => "", - PrimitiveType::U128 => "u128", - PrimitiveType::U256 => "u256", - _ => "", - }) + emit!( + self.writer, + match prim { + PrimitiveType::U8 => "u8", + PrimitiveType::U16 => "u16", + PrimitiveType::U32 => "u32", + PrimitiveType::U64 => "", + PrimitiveType::U128 => "u128", + PrimitiveType::U256 => "u256", + _ => "", + } + ) } }, Value::Bool(b) => emit!(self.writer, "{}", b), diff --git a/third_party/move/move-model/src/ty.rs b/third_party/move/move-model/src/ty.rs index 600b9f08a49da..9f0f7f06b98d0 100644 --- a/third_party/move/move-model/src/ty.rs +++ b/third_party/move/move-model/src/ty.rs @@ -164,9 +164,6 @@ pub enum Constraint { /// a pseudo constraint which never fails, but used to generate a default for /// inference. WithDefault(Type), - /// The type must not be function because it is used as the type of some field or - /// as a type argument. - NoFunction, } /// Scope of ability checking. @@ -409,10 +406,7 @@ impl Constraint { /// for internal constraints which would be mostly confusing to users. pub fn hidden(&self) -> bool { use Constraint::*; - matches!( - self, - NoPhantom | NoReference | NoTuple | NoFunction | WithDefault(..) - ) + matches!(self, NoPhantom | NoReference | NoTuple | WithDefault(..)) } /// Returns true if this context is accumulating. When adding a new constraint @@ -430,7 +424,6 @@ impl Constraint { | Constraint::NoPhantom | Constraint::NoTuple | Constraint::NoReference - | Constraint::NoFunction ) } @@ -449,10 +442,7 @@ impl Constraint { /// the same type. pub fn report_only_once(&self) -> bool { use Constraint::*; - matches!( - self, - HasAbilities(..) | NoReference | NoFunction | NoPhantom | NoTuple - ) + matches!(self, HasAbilities(..) | NoReference | NoPhantom | NoTuple) } /// Joins the two constraints. If they are incompatible, produces a type unification error. @@ -537,7 +527,6 @@ impl Constraint { )) } }, - (Constraint::NoFunction, Constraint::NoFunction) => Ok(true), (Constraint::NoReference, Constraint::NoReference) => Ok(true), (Constraint::NoTuple, Constraint::NoTuple) => Ok(true), (Constraint::NoPhantom, Constraint::NoPhantom) => Ok(true), @@ -560,14 +549,10 @@ impl Constraint { } /// Returns the constraints which need to be satisfied to instantiate the given type - /// parameter. This creates NoReference, NoFunction, NoTuple, NoPhantom unless the type + /// parameter. This creates NoReference, NoTuple, NoPhantom unless the type /// parameter is phantom, and HasAbilities if any abilities need to be met. pub fn for_type_parameter(param: &TypeParameter) -> Vec { - let mut result = vec![ - Constraint::NoReference, - Constraint::NoTuple, - Constraint::NoFunction, // TODO(LAMBDA) - remove when implement LAMBDA_AS_TYPE_PARAMETERS - ]; + let mut result = vec![Constraint::NoReference, Constraint::NoTuple]; let TypeParameter( _, TypeParameterKind { @@ -594,7 +579,6 @@ impl Constraint { Constraint::NoPhantom, Constraint::NoReference, Constraint::NoTuple, - Constraint::NoFunction, // TODO(LAMBDA) - remove when we implement LAMBDA_IN_VECTORS ] } @@ -605,7 +589,6 @@ impl Constraint { Constraint::NoPhantom, Constraint::NoTuple, Constraint::NoReference, - Constraint::NoFunction, ]; let abilities = if struct_abilities.has_ability(Ability::Key) { struct_abilities.remove(Ability::Key).add(Ability::Store) @@ -675,7 +658,6 @@ impl Constraint { ) }, Constraint::NoReference => "no-ref".to_string(), - Constraint::NoFunction => "no-func".to_string(), Constraint::NoTuple => "no-tuple".to_string(), Constraint::NoPhantom => "no-phantom".to_string(), Constraint::HasAbilities(required_abilities, _) => { @@ -1893,13 +1875,6 @@ impl Substitution { Ok(()) } }, - (Constraint::NoFunction, ty) => { - if ty.is_function() { - constraint_unsatisfied_error() - } else { - Ok(()) - } - }, (Constraint::NoTuple, ty) => { if ty.is_tuple() { constraint_unsatisfied_error() @@ -3122,13 +3097,6 @@ impl TypeUnificationError { item_name() ) }, - Constraint::NoFunction => { - format!( - "function type `{}` is not allowed {}", - ty.display(display_context), - item_name() - ) - }, Constraint::NoPhantom => { format!( "phantom type `{}` can only be used as an argument for another phantom type parameter", diff --git a/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs b/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs index 0b58373ba8267..8a921e15b66be 100644 --- a/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs +++ b/third_party/move/move-prover/boogie-backend/src/boogie_helpers.rs @@ -592,7 +592,7 @@ pub fn boogie_value(env: &GlobalEnv, _options: &BoogieOptions, val: &Value) -> S .collect_vec(), ), Value::Tuple(vec) => format!("<>", vec), - Value::Function(mid, fid) => format!("", mid, fid), // TODO(LAMBDA) + Value::Function(mid, fid) => format!("", mid, fid), // TODO(LAMBDA) } } diff --git a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs index b674d30b855b9..d3157c01a7161 100644 --- a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs +++ b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs @@ -270,8 +270,12 @@ impl<'env> SpecTranslator<'env> { // so we don't need to translate it. return; } - if let Type::Tuple(..) | Type::Fun(..) = fun.result_type { - self.error(&fun.loc, "function or tuple result type not yet supported"); + if let Type::Tuple(..) = fun.result_type { + self.error(&fun.loc, "tuple result type not yet supported"); + return; + } + if let Type::Fun(..) = fun.result_type { + self.error(&fun.loc, "function result type not yet supported"); // TODO(LAMBDA) return; } let qid = module_env.get_id().qualified(id); @@ -684,6 +688,7 @@ impl<'env> SpecTranslator<'env> { }, ExpData::Invoke(node_id, ..) => { self.error(&self.env.get_node_loc(*node_id), "Invoke not yet supported"); + // TODO(LAMBDA) }, ExpData::Lambda(node_id, ..) => self.error( &self.env.get_node_loc(*node_id), @@ -1020,8 +1025,7 @@ impl<'env> SpecTranslator<'env> { self.env.error( &self.env.get_node_loc(node_id), &format!( - "bug: operation {} is not supported \ - in the current context", + "bug: operation {} is not supported in the current context", oper.display(self.env, node_id) ), );