From 5d87d94cba896628ac75e979c6e66a2d65347642 Mon Sep 17 00:00:00 2001 From: "Brian R. Murphy" <132495859+brmataptos@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:28:06 -0800 Subject: [PATCH] [move-compiler-v2] add parser code for lambda types (#14792) Add parser code for function values and non-inline lambdas Extend syntax - for lambda: `move |args| body with copy+store` - Add function types: `|T1, T2| T3 with copy+store` - curry construction: - from lambda: `|a, b| f(x, 3, a, b)` - `EarlyBind` operation takes a function value and values for any number of leading parameters. - arbitrary function calls: - `(|x, y| x + y)(2, 3)` - suppress printing common abilities (all functions have drop) Modify exp_builder and lambda_lifter to generate function values, model to track "used" functions in addition to "called" functions. Attaches an `AbilitySet` to `Type::Fun` and `Exp::Lambda` based on source. Adds a new `ExpCall` operation in parser/expansion ASTs to be able to carry more generalized function calls through to move-model, which already can support this through `Invoke`, which previously was underutilized. Added basic type checking for function abilities. Added more lambda tests under `move-compiler-v2/tests/lambda/` which are run "with" and "without" lambda features enabled. Currently, many things pass through to hit "not yet implemented" errors in bytecode gen, etc. Tricky features are: - In some cases, abilities may not be inferred well yet, so examples may need to be over-annotated with abilities. - in `ty.rs`: unification checks `Fun` abilities as well as other things. - in `lambda_lifter.rs`, we (1) reject lambdas without `move` free-var handling, (2) try to reduce lambda to curry, by checking for a simple function call with simple args, the last of which are identical to the lambda parameters. --- Cargo.lock | 1 + .../move/evm/move-to-yul/src/context.rs | 2 +- .../move/evm/move-to-yul/src/solidity_ty.rs | 2 +- .../move-binary-format/src/file_format.rs | 10 +- .../src/bytecode_generator.rs | 23 +- .../src/env_pipeline/ast_simplifier.rs | 5 +- .../env_pipeline/flow_insensitive_checkers.rs | 2 +- .../src/env_pipeline/function_checker.rs | 14 +- .../src/env_pipeline/inliner.rs | 4 +- .../src/env_pipeline/lambda_lifter.rs | 521 +++- .../src/env_pipeline/rewrite_target.rs | 6 +- .../src/env_pipeline/spec_rewriter.rs | 9 +- .../src/env_pipeline/unused_params_checker.rs | 2 +- .../file_format_generator/module_generator.rs | 4 +- .../tests/checking/inlining/lambda3.exp | 2 +- .../checking/inlining/lambda_cast_err.exp | 2 +- .../inlining/lambda_param_mismatch.exp | 2 +- .../tests/checking/specs/expressions_err.exp | 2 +- .../tests/checking/typing/lambda.exp | 2 +- .../tests/checking/typing/lambda3.exp | 2 +- .../tests/checking/typing/lambda_typed.exp | 4 +- .../tests/lambda-lifting/basic.lambda.exp | 99 +- .../tests/lambda-lifting/modify.lambda.exp | 58 +- .../tests/lambda-lifting/nested.lambda.exp | 76 +- .../tests/lambda-lifting/pattern.lambda.exp | 77 +- .../break_continue_in_lambda.lambda.exp | 348 +-- .../lambda/inline-parity/bug_10991.lambda.exp | 100 +- .../bug_10991_noparam.lambda.exp | 118 +- .../bug_10991_noparam2.lambda.exp | 100 +- .../inline-parity/bug_10991a.lambda.exp | 134 +- .../inline-parity/bug_10991b.lambda.exp | 74 +- .../inline-parity/bug_10991c.lambda.exp | 83 +- .../inline-parity/dotdot_valid.lambda.exp | 933 +------ .../lambda/inline-parity/eq_inline.lambda.exp | 52 +- .../eval_ignored_param.lambda.exp | 154 +- .../inline-parity/generic_calls.lambda.exp | 143 +- .../lambda/inline-parity/generics.lambda.exp | 6 +- .../inline_fun_in_spec.lambda.exp | 163 +- .../lambda/inline-parity/inlining1.lambda.exp | 83 +- .../lambda/inline-parity/lambda.lambda.exp | 51 +- .../inline-parity/lambda_cast.lambda.exp | 18 +- .../lambda/inline-parity/lambda_cast_err.exp | 2 +- .../inline-parity/lambda_cast_err.lambda.exp | 2 +- .../inline-parity/lambda_no_param.lambda.exp | 91 +- .../inline-parity/lambda_param.lambda.exp | 215 +- .../inline-parity/lambda_param_mismatch.exp | 2 +- .../lambda_param_mismatch.lambda.exp | 2 +- .../inline-parity/lambda_return.lambda.exp | 74 +- .../inline-parity/lambda_typed.lambda.exp | 326 +-- .../lambda/inline-parity/masking.lambda.exp | 85 +- .../inline-parity/multi_param.lambda.exp | 18 +- .../inline-parity/nested_lambda.lambda.exp | 61 +- .../nested_lambda_module.lambda.exp | 70 +- .../inline-parity/non_lambda_arg.lambda.exp | 10 - .../op_with_side_effect_49.lambda.exp | 12 +- .../lambda/inline-parity/options.lambda.exp | 95 +- .../inline-parity/return_in_lambda.lambda.exp | 59 +- .../inline-parity/same_names.lambda.exp | 116 +- .../lambda/inline-parity/shadowing.lambda.exp | 12 +- .../shadowing_renamed.lambda.exp | 12 +- .../shadowing_renamed_param.lambda.exp | 48 +- .../inline-parity/shadowing_unused.lambda.exp | 30 +- .../shadowing_unused_nodecl.lambda.exp | 30 +- .../inline-parity/simple_map_keys.lambda.exp | 16 +- .../inline-parity/spec_inlining.lambda.exp | 145 +- .../inline-parity/subtype_args.lambda.exp | 4 +- ...erical_extreme_comparisons_warn.lambda.exp | 398 +-- .../unpack_generic_struct.lambda.exp | 172 +- .../unused_lambda_param.lambda.exp | 110 +- .../move-compiler-v2/tests/lambda/lambda.exp | 2 +- .../tests/lambda/lambda.lambda.exp | 2 +- .../move-compiler-v2/tests/lambda/lambda3.exp | 2 +- .../tests/lambda/lambda3.lambda.exp | 66 +- .../tests/lambda/non_lambda_arg.lambda.exp | 10 - .../tests/lambda/storable/doable_func.exp | 127 + .../lambda/storable/doable_func.lambda.exp | 2465 +++++++++++++++++ .../tests/lambda/storable/doable_func.move | 93 + .../tests/lambda/storable/parse_errors.exp | 10 + .../lambda/storable/parse_errors.lambda.exp | 10 + .../tests/lambda/storable/parse_errors.move | 107 + .../tests/lambda/storable/registry.exp | 9 - .../tests/lambda/storable/registry.lambda.exp | 9 - .../tests/lambda/storable/registry.move | 109 - .../tests/lambda/storable/registry_errors.exp | 37 + .../storable/registry_errors.lambda.exp | 83 + .../lambda/storable/registry_errors.move | 128 + .../tests/lambda/storable/registry_ok.exp | 43 + .../lambda/storable/registry_ok.lambda.exp | 42 + .../tests/lambda/storable/registry_ok.move | 182 ++ .../tests/lambda/storable/retain_funcs.exp | 7 + .../lambda/storable/retain_funcs.lambda.exp | 7 + .../tests/lambda/storable/retain_funcs.move | 20 + .../tests/lambda/storable/return_func.exp | 193 +- .../lambda/storable/return_func.lambda.exp | 53 +- .../tests/lambda/storable/return_func.move | 89 +- .../tests/lambda/storable/simplifier_func.exp | 51 + .../storable/simplifier_func.lambda.exp | 206 ++ .../lambda/storable/simplifier_func.move | 10 + .../invalid_call_lhs_complex_expression.exp | 21 +- .../invalid_call_lhs_complex_expression2.exp | 21 +- .../invalid_call_lhs_parens_around_name.exp | 9 +- .../invalid_call_lhs_parens_around_name2.exp | 9 +- .../parser/invalid_call_lhs_return.exp | 9 +- .../parser/invalid_call_lhs_return2.exp | 9 +- .../more-v1/parser/invalid_call_lhs_value.exp | 15 +- .../parser/invalid_call_lhs_value2.exp | 15 +- .../tests/more-v1/parser/spec_parsing_ok.exp | 2 +- ...oken_after_ability_function_constraint.exp | 7 +- .../move/move-compiler-v2/tests/testsuite.rs | 3 +- .../tests/inlining/multi_param_typed.exp | 2 +- .../move/move-compiler/src/expansion/ast.rs | 50 +- .../src/expansion/dependency_ordering.rs | 8 +- .../move-compiler/src/expansion/translate.rs | 21 +- .../move-compiler/src/naming/translate.rs | 21 +- .../move/move-compiler/src/parser/ast.rs | 57 +- .../move/move-compiler/src/parser/syntax.rs | 204 +- .../move-compiler/src/shared/ast_debug.rs | 1 + .../invalid_call_lhs_complex_expression.exp | 21 +- .../invalid_call_lhs_complex_expression2.exp | 15 +- .../invalid_call_lhs_parens_around_name.exp | 15 +- .../invalid_call_lhs_parens_around_name2.exp | 9 +- .../parser/invalid_call_lhs_return.exp | 15 +- .../parser/invalid_call_lhs_return2.exp | 9 +- .../parser/invalid_call_lhs_value.exp | 21 +- .../parser/invalid_call_lhs_value2.exp | 15 +- ...oken_after_ability_function_constraint.exp | 7 +- third_party/move/move-model/Cargo.toml | 1 + .../ast-generator-tests/tests/testsuite.rs | 8 +- .../bytecode/src/function_target_pipeline.rs | 2 +- third_party/move/move-model/src/ast.rs | 264 +- .../move-model/src/builder/exp_builder.rs | 186 +- .../move-model/src/builder/model_builder.rs | 14 +- .../move-model/src/builder/module_builder.rs | 39 +- .../move/move-model/src/exp_rewriter.rs | 26 +- third_party/move/move-model/src/metadata.rs | 5 + third_party/move/move-model/src/model.rs | 204 +- third_party/move/move-model/src/sourcifier.rs | 52 +- third_party/move/move-model/src/ty.rs | 72 +- .../tests/sources/expressions_err.exp | 2 +- .../tests/sources/expressions_err.v2_exp | 2 +- .../boogie-backend/src/boogie_helpers.rs | 1 + .../boogie-backend/src/boogie_wrapper.rs | 2 +- .../boogie-backend/src/bytecode_translator.rs | 20 +- .../boogie-backend/src/spec_translator.rs | 12 +- .../src/memory_instrumentation.rs | 2 +- .../move-prover/move-abigen/src/abigen.rs | 2 +- .../move-prover/move-docgen/src/docgen.rs | 4 +- 147 files changed, 5915 insertions(+), 5496 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.move delete mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry.exp delete mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry.lambda.exp delete mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.move create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.lambda.exp create mode 100644 third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.move diff --git a/Cargo.lock b/Cargo.lock index dbe8b1c7df442..59c962d5ccc1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11452,6 +11452,7 @@ dependencies = [ "codespan", "codespan-reporting", "datatest-stable", + "either", "internment", "itertools 0.13.0", "log", diff --git a/third_party/move/evm/move-to-yul/src/context.rs b/third_party/move/evm/move-to-yul/src/context.rs index ef8e251ee89e8..a8e9b29deef17 100644 --- a/third_party/move/evm/move-to-yul/src/context.rs +++ b/third_party/move/evm/move-to-yul/src/context.rs @@ -784,7 +784,7 @@ impl<'a> Context<'a> { Tuple(_) | TypeParameter(_) | Reference(_, _) - | Fun(_, _) + | Fun(..) | TypeDomain(_) | ResourceDomain(_, _, _) | Error diff --git a/third_party/move/evm/move-to-yul/src/solidity_ty.rs b/third_party/move/evm/move-to-yul/src/solidity_ty.rs index b47d59e5dfa48..7f44b34c35e4e 100644 --- a/third_party/move/evm/move-to-yul/src/solidity_ty.rs +++ b/third_party/move/evm/move-to-yul/src/solidity_ty.rs @@ -368,7 +368,7 @@ impl SolidityType { }, TypeParameter(_) | Reference(_, _) - | Fun(_, _) + | Fun(..) | TypeDomain(_) | ResourceDomain(_, _, _) | Error diff --git a/third_party/move/move-binary-format/src/file_format.rs b/third_party/move/move-binary-format/src/file_format.rs index 3037cec1eaea5..468bdcca9fd32 100644 --- a/third_party/move/move-binary-format/src/file_format.rs +++ b/third_party/move/move-binary-format/src/file_format.rs @@ -851,11 +851,19 @@ impl AbilitySet { ); /// The empty ability set pub const EMPTY: Self = Self(0); - /// Abilities for `Functions` + /// Minimal abilities for all `Functions` pub const FUNCTIONS: AbilitySet = Self(Ability::Drop as u8); + /// Maximal abilities for all `Functions`. This is used for identity when unifying function types. + pub const MAXIMAL_FUNCTIONS: AbilitySet = Self::PUBLIC_FUNCTIONS; /// Abilities for `Bool`, `U8`, `U64`, `U128`, and `Address` pub const PRIMITIVES: AbilitySet = Self((Ability::Copy as u8) | (Ability::Drop as u8) | (Ability::Store as u8)); + /// Abilities for `private` user-defined/"primitive" functions (not closures). + /// These can be be changed in module upgrades, so should not be stored + pub const PRIVATE_FUNCTIONS: AbilitySet = Self((Ability::Copy as u8) | (Ability::Drop as u8)); + /// Abilities for `public` user-defined/"primitive" functions (not closures) + pub const PUBLIC_FUNCTIONS: AbilitySet = + Self((Ability::Copy as u8) | (Ability::Drop as u8) | (Ability::Store as u8)); /// Abilities for `Reference` and `MutableReference` pub const REFERENCES: AbilitySet = Self((Ability::Copy as u8) | (Ability::Drop as u8)); /// Abilities for `Signer` 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 9cb45341d9743..19d571863998a 100644 --- a/third_party/move/move-compiler-v2/src/bytecode_generator.rs +++ b/third_party/move/move-compiler-v2/src/bytecode_generator.rs @@ -480,13 +480,13 @@ 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", ), // TODO(LAMBDA) - ExpData::Invoke(_, exp, _) => self.error( - exp.as_ref().node_id(), + ExpData::Invoke(id, _exp, _) => self.error( + *id, "Calls to function values other than inline function parameters not yet supported", ), ExpData::Quant(id, _, _, _, _, _) => { @@ -564,6 +564,12 @@ impl<'env> Generator<'env> { Constant::Bool(false) } }, + Value::Function(_mid, _fid) => { + self.error( + id, + "Function-typed values not yet supported except as parameters to calls to inline functions"); + Constant::Bool(false) + }, } } } @@ -785,6 +791,11 @@ impl<'env> Generator<'env> { Operation::MoveFunction(m, f) => { self.gen_function_call(targets, id, m.qualified(*f), args) }, + // TODO(LAMBDA) + Operation::EarlyBind => self.error( + id, + "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) }, @@ -813,12 +824,6 @@ impl<'env> Generator<'env> { Operation::NoOp => {}, // do nothing - // TODO(LAMBDA) - Operation::Closure(..) => self.error( - id, - "Function-typed values not yet supported except as parameters to calls to inline functions", - ), - // Non-supported specification related operations Operation::Exists(Some(_)) | Operation::SpecFunction(_, _, _) diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs b/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs index f60012a917544..62c9a6cf63d12 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/ast_simplifier.rs @@ -359,7 +359,7 @@ fn find_possibly_modified_vars( _ => {}, } }, - Lambda(node_id, pat, _) => { + Lambda(node_id, pat, _, _, _) => { // Define a new scope for bound vars, and turn off `modifying` within. match pos { VisitorPosition::Pre => { @@ -978,7 +978,8 @@ impl<'env> ExpRewriterFunctions for SimplifierRewriter<'env> { let ability_set = self .env() .type_abilities(&ty, self.func_env.get_type_parameters_ref()); - ability_set.has_ability(Ability::Drop) + // Don't drop a function-valued expression so we don't lose errors. + !ty.has_function() && ability_set.has_ability(Ability::Drop) } else { // We're missing type info, be conservative false diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/flow_insensitive_checkers.rs b/third_party/move/move-compiler-v2/src/env_pipeline/flow_insensitive_checkers.rs index dd6dabec91723..72bbd295d5853 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/flow_insensitive_checkers.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/flow_insensitive_checkers.rs @@ -147,7 +147,7 @@ impl<'env, 'params> SymbolVisitor<'env, 'params> { Pre | Post | BeforeBody | MidMutate | BeforeThen | BeforeElse | PreSequenceValue => {}, }, - Lambda(_, pat, _) => { + Lambda(_, pat, _, _, _) => { match position { Pre => self.seen_uses.enter_scope(), Post => { diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs b/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs index d7dbcc3cfce2b..958a13bde6425 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/function_checker.rs @@ -11,7 +11,7 @@ use move_model::{ model::{FunId, FunctionEnv, GlobalEnv, Loc, ModuleEnv, NodeId, Parameter, QualifiedId}, ty::Type, }; -use std::{collections::BTreeSet, iter::Iterator, ops::Deref, vec::Vec}; +use std::{collections::BTreeSet, iter::Iterator, vec::Vec}; type QualifiedFunId = QualifiedId; @@ -20,8 +20,8 @@ fn identify_function_types_with_functions_in_args(func_types: Vec) -> Vec< func_types .into_iter() .filter_map(|ty| { - if let Type::Fun(argt, _) = &ty { - if argt.deref().has_function() { + if let Type::Fun(args, _, _) = &ty { + if args.as_ref().has_function() { Some(ty) } else { None @@ -41,8 +41,8 @@ fn identify_function_typed_params_with_functions_in_rets( func_types .iter() .filter_map(|param| { - if let Type::Fun(_argt, rest) = ¶m.1 { - let rest_unboxed = rest.deref(); + if let Type::Fun(_args, result, _) = ¶m.1 { + let rest_unboxed = result.as_ref(); if rest_unboxed.has_function() { Some((*param, rest_unboxed)) } else { @@ -270,7 +270,7 @@ fn check_privileged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv }, ExpData::Assign(_, pat, _) | ExpData::Block(_, pat, _, _) - | ExpData::Lambda(_, pat, _) => { + | ExpData::Lambda(_, pat, _, _, _) => { pat.visit_pre_post(&mut |_, pat| { if let Pattern::Struct(id, str, _, _) = pat { let module_id = str.module_id; @@ -344,7 +344,7 @@ pub fn check_access_and_use(env: &mut GlobalEnv, before_inlining: bool) { // Check that functions being called are accessible. if let Some(def) = caller_func.get_def() { - let callees_with_sites = def.called_funs_with_callsites(); + let callees_with_sites = def.used_funs_with_uses(); for (callee, sites) in &callees_with_sites { let callee_func = env.get_function(*callee); // Check visibility. diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs b/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs index 636f0d95d6728..06eaa909705dd 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/inliner.rs @@ -90,7 +90,7 @@ pub fn run_inlining(env: &mut GlobalEnv, scope: RewritingScope, keep_inline_func let mut visited_targets = BTreeSet::new(); while let Some(target) = todo.pop_first() { if visited_targets.insert(target.clone()) { - let callees_with_sites = target.called_funs_with_call_sites(env); + let callees_with_sites = target.used_funs_with_uses(env); for (callee, sites) in callees_with_sites { todo.insert(RewriteTarget::MoveFun(callee)); targets.entry(RewriteTarget::MoveFun(callee)); @@ -1161,7 +1161,7 @@ impl<'env, 'rewriter> ExpRewriterFunctions for InlinedRewriter<'env, 'rewriter> }; let call_loc = self.env.get_node_loc(id); if let Some(lambda_target) = optional_lambda_target { - if let ExpData::Lambda(_, pat, body) = lambda_target.as_ref() { + if let ExpData::Lambda(_, pat, body, _, _) = lambda_target.as_ref() { let args_vec: Vec = args.to_vec(); Some(InlinedRewriter::construct_inlined_call_expression( self.env, 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 8326c3e8af618..d16593bac2da0 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,15 +13,17 @@ //! 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. Example: +//! 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 arguments, +//! which must be the first `k` arguments to the function argument list. //! //! ```ignore //! let c = 1; //! vec.any(|x| x > c) //! ==> //! let c = 1; -//! vec.any(Closure(lifted, c)) +//! vec.any(EarlyBind(lifted, c)) //! where //! fun lifted(c: u64, x: u64): bool { x > c } //! ``` @@ -34,19 +36,19 @@ //! vec.any(|S{x}| x > c) //! ==> //! let c = 1; -//! vec.any(Closure(lifted, c)) +//! vec.any(EarlyBind(lifted, c)) //! where //! fun lifted(c: u64, arg$2: S): bool { let S{x} = arg$2; x > y } //! ``` use itertools::Itertools; -use move_binary_format::file_format::Visibility; +use move_binary_format::file_format::{AbilitySet, Visibility}; use move_model::{ - ast::{Exp, ExpData, Operation, Pattern, TempIndex}, + ast::{self, Exp, ExpData, LambdaCaptureKind, Operation, Pattern, TempIndex}, exp_rewriter::{ExpRewriter, ExpRewriterFunctions, RewriteTarget}, - model::{FunId, FunctionEnv, GlobalEnv, Loc, NodeId, Parameter, TypeParameter}, + model::{FunId, FunctionEnv, GlobalEnv, Loc, ModuleId, NodeId, Parameter, TypeParameter}, symbol::Symbol, - ty::{ReferenceKind, Type}, + ty::{AbilityInference, AbilityInferer, ReferenceKind, Type}, }; use std::{ collections::{BTreeMap, BTreeSet}, @@ -185,13 +187,360 @@ impl<'a> LambdaLifter<'a> { let env = self.fun_env.module_env.env; let body = self.bind(bindings, exp); let loc = env.get_node_loc(pat.node_id()); - let ty = env.get_node_type(body.node_id()); + let body_id = body.node_id(); + let ty = env.get_node_type(body_id); let new_id = env.new_node(loc, ty); + if let Some(inst) = env.get_node_instantiation_opt(body_id) { + env.set_node_instantiation(new_id, inst); + } ExpData::Block(new_id, pat, Some(binding), body).into_exp() } else { exp } } + + /// For the current state, calculate: (params, closure_args, param_index_mapping), where + /// - `params` = new Parameter for each free var to represent it in the lifted function + /// - `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, + ) -> Option<(Vec, Vec, BTreeMap)> { + let env = self.fun_env.module_env.env; + let mut closure_args = vec![]; + + // Add captured parameters. We also need to record a mapping of + // parameter indices in the lambda context to indices in the lifted + // 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() + { + let name = self.fun_env.get_local_name(param); + let var_node_id = var_info.node_id; + let ty = env.get_node_type(var_node_id); + let loc = env.get_node_loc(var_node_id); + if var_info.modified { + env.error( + &loc, + &format!( + "captured variable `{}` cannot be modified inside of a lambda", // TODO(LAMBDA) + 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); + if let Some(inst) = env.get_node_instantiation_opt(var_node_id) { + env.set_node_instantiation(new_id, inst); + } + closure_args.push(ExpData::Temporary(new_id, param).into_exp()); + param_index_mapping.insert(param, used_param_count); + } + + // Add captured LocalVar parameters + for (name, var_info) in mem::take(&mut self.free_locals) { + let var_info_id = var_info.node_id; + let ty = env.get_node_type(var_info_id); + let loc = env.get_node_loc(var_info_id); + if var_info.modified { + env.error( + &loc, + &format!( + "captured variable `{}` cannot be modified inside of a lambda", // 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); + if let Some(inst) = env.get_node_instantiation_opt(var_info_id) { + env.set_node_instantiation(new_id, inst); + } + closure_args.push(ExpData::LocalVar(new_id, name).into_exp()) + } + + if !saw_error { + Some((params, closure_args, param_index_mapping)) + } else { + None + } + } + + // If final `args` match `lambda_params`, and all other args are simple, then returns + // the simple prefix of `args`. + fn get_args_if_simple<'b>( + lambda_params: &[Parameter], + args: &'b [Exp], + ) -> Option> { + if lambda_params.len() <= args.len() { + let mut simple_args: Vec<&Exp> = + args.iter().filter(|arg| Self::exp_is_simple(arg)).collect(); + if simple_args.len() == args.len() + && lambda_params + .iter() + .rev() + .zip(simple_args.iter().rev()) + .all(|(param, arg)| { + if let ExpData::LocalVar(_, name) = arg.as_ref() { + *name == param.get_name() + } else { + false + } + }) + { + let remaining_size = args.len() - lambda_params.len(); + simple_args.truncate(remaining_size); + return Some(simple_args); + } + } + None + } + + // Only allow simple expressions which cannot vary or abort, since we are pulling + // them out of the lambda expression and evaluating them in order to bind them to + // the closure eary. + fn exp_is_simple(exp: &Exp) -> bool { + use ExpData::*; + match exp.as_ref() { + Call(_, Operation::EarlyBind, args) => args.iter().all(Self::exp_is_simple), + Call(_, op, args) => { + op.is_ok_to_remove_from_code() && args.iter().all(Self::exp_is_simple) + }, + Sequence(_, exp_vec) => { + if let [exp] = &exp_vec[..] { + Self::exp_is_simple(exp) + } else { + false + } + }, + IfElse(_, e1, e2, e3) => { + Self::exp_is_simple(e1) && Self::exp_is_simple(e2) && Self::exp_is_simple(e3) + }, + Lambda(_, _pat, _body, _capture_kind, _abilities) => { + // Maybe could test lambda_is_direct_curry(pat, body) + // and do something with it, but it is nontrivial. + false + }, + LocalVar(..) | Temporary(..) | Value(..) => true, + Invalid(..) | Invoke(..) | Quant(..) | Block(..) | Match(..) | Return(..) + | Loop(..) | LoopCont(..) | Assign(..) | Mutate(..) | SpecBlock(..) => false, + } + } + + fn make_move_fn_exp( + &mut self, + loc: Loc, + fn_type: Type, + module_id: ModuleId, + fun_id: FunId, + instantiation: Option>, + ) -> Exp { + let env = self.fun_env.module_env.env; + let id = env.new_node(loc, fn_type); + if let Some(inst) = instantiation { + env.set_node_instantiation(id, inst); + } + let fn_exp = ExpData::Value(id, ast::Value::Function(module_id, fun_id)); + fn_exp.into_exp() + } + + fn get_move_fn_type(&mut self, expr_id: NodeId, module_id: ModuleId, fun_id: FunId) -> Type { + let env = self.fun_env.module_env.env; + let fn_env = env.get_function(module_id.qualified(fun_id)); + let fun_abilities = if fn_env.visibility().is_public() { + AbilitySet::PUBLIC_FUNCTIONS + } else { + AbilitySet::PRIVATE_FUNCTIONS + }; + let params = fn_env.get_parameters_ref(); + let param_types = params.iter().map(|param| param.get_type()).collect(); + let node_instantiation = env.get_node_instantiation(expr_id); + let result_type = fn_env.get_result_type(); + Type::Fun( + Box::new(Type::Tuple(param_types)), + Box::new(result_type), + fun_abilities, + ) + .instantiate(&node_instantiation) + } + + // If body is a function call expression with the function value and each parameter a + // simple expression (constant, var, or Move function name), with the last arguments the + // provided `lambda_params` in sequence, then returns the function name and the prefix + // arguments. Otherwise, returns `None`. + fn lambda_reduces_to_curry<'b>( + &mut self, + lambda_params: &Vec, + body: &'b Exp, + ) -> Option<(Exp, Vec<&'b Exp>)> { + use ExpData::*; + let env = self.fun_env.module_env.env; + match body.as_ref() { + Call(id, oper, args) => { + match oper { + Operation::EarlyBind => { + // TODO(LAMBDA): We might be able to to do something with this, + // but skip for now because it will be complicated. + None + }, + Operation::MoveFunction(mid, fid) => { + Self::get_args_if_simple(lambda_params, args).map(|args| { + let fn_type = self.get_move_fn_type(*id, *mid, *fid); + let loc = env.get_node_loc(*id); + let fn_exp = self.make_move_fn_exp( + loc, + fn_type, + *mid, + *fid, + env.get_node_instantiation_opt(*id), + ); + (fn_exp, args) + }) + }, + _ => None, + } + }, + Invoke(_id, fn_exp, args) => { + Self::get_args_if_simple(lambda_params, args).and_then(|args| { + // Function expression may not contain lambda params + let free_vars = fn_exp.as_ref().free_vars(); + if lambda_params + .iter() + .all(|param| !free_vars.contains(¶m.get_name())) + && Self::exp_is_simple(fn_exp) + { + Some((fn_exp.clone(), args)) + } else { + None + } + }) + }, + ExpData::Sequence(_id, exp_vec) => { + if let [exp] = &exp_vec[..] { + self.lambda_reduces_to_curry(lambda_params, exp) + } else { + None + } + }, + _ => None, + } + } + + // We can rewrite a lambda directly into a curry expression if: + // - lambda parameters are a simple variable tuple (v1, v2, ...) === (bindings.is_empty()) + // Caller should already check that, and place the tuple of variables in parameter list lambda_params. + // + // Then, we can reduce to curry if: + // - lambda body is a function call with + // - lambda parameters used (in order) as the last arguments to the function call. + // - the function called and every other argument is a simple expression containing only + // constants and free variables which cannot abort + // Arguments here are + // - id: original lambda expr NodeId + // - body: body of lambda + // - lambda_params: a Parameter corresponding to each lambda param + fn try_to_reduce_lambda_to_curry( + &mut self, + id: NodeId, + body: &Exp, + lambda_params: Vec, + abilities: &AbilitySet, + ) -> Option { + if let Some((fn_exp, args)) = self.lambda_reduces_to_curry(&lambda_params, body) { + // lambda has form |lambda_params| fn_exp(args, ...lambda_params) + // where each arg is a constant or simple variable, not in lambda_params, + // except the trailing k params which are all lambda_params + let mut new_args: Vec<_> = args.into_iter().cloned().collect(); + + let env = self.fun_env.module_env.env; + let fn_id = fn_exp.node_id(); + let fn_type = env.get_node_type(fn_id); + if let Type::Fun(_fn_param_type, _fn_result_type, fun_abilities) = &fn_type { + // First param to EarlyBind is the function expr + new_args.insert(0, fn_exp); + let ty_params = self.fun_env.get_type_parameters_ref(); + // Check bound value abilities + let ability_inferer = AbilityInferer::new(env, ty_params); + let bound_value_abilities: Vec<_> = new_args + .iter() + .map(|exp| { + let node = exp.as_ref().node_id(); + let ty = env.get_node_type(node); + let node_abilities = ability_inferer.infer_abilities(&ty).1; + (env.get_node_loc(node), node_abilities) + }) + .collect(); + let mut bound_value_missing_abilities: Vec<_> = bound_value_abilities + .iter() + .filter_map(|(loc, node_abilities)| { + if !abilities.is_subset(*node_abilities) { + let missing = abilities.setminus(*node_abilities); + Some(( + loc.clone(), + format!("Captured free value is missing abilities: {}", missing), + )) + } else { + None + } + }) + .collect(); + if !abilities.is_subset(*fun_abilities) { + let missing = abilities.setminus(*fun_abilities); + let tdc = env.get_type_display_ctx(); + bound_value_missing_abilities.push(( + env.get_node_loc(fn_id), + format!( + "Base function of closure has type {}, is missing abilities: {}", + fn_type.display(&tdc), + missing + ), + )); + } + let closure_abilities = bound_value_abilities + .iter() + .map(|(_loc, node_abilities)| *node_abilities) + .reduce(|abs1, abs2| abs1.intersect(abs2)) + .unwrap_or(*fun_abilities); + if !bound_value_missing_abilities.is_empty() { + let missing_abilities = abilities.setminus(closure_abilities); + let loc = env.get_node_loc(id); + env.error_with_labels( + &loc, + &format!("Lambda captures free variables with types that do not have some declared abilities: {}", + missing_abilities), + bound_value_missing_abilities); + return None; + }; + if new_args.len() == 1 { + // We have no parameters, just use the function directly. + return Some(new_args.pop().unwrap()); + } else { + return Some(ExpData::Call(id, Operation::EarlyBind, new_args).into_exp()); + } + } + } + None + } } impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { @@ -288,79 +637,92 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { None } - fn rewrite_lambda(&mut self, id: NodeId, pat: &Pattern, body: &Exp) -> Option { + fn rewrite_lambda( + &mut self, + id: NodeId, + pat: &Pattern, + body: &Exp, + capture_kind: LambdaCaptureKind, + abilities: AbilitySet, // TODO(LAMBDA): do something with this + ) -> Option { if self.exempted_lambdas.contains(&id) { return None; } let env = self.fun_env.module_env.env; - let mut params = vec![]; - let mut closure_args = vec![]; - // Add captured parameters. We also need to record a mapping of - // parameter indices in the lambda context to indices in the lifted - // functions (courtesy of #12317) - let mut param_index_mapping = BTreeMap::new(); - for (used_param_count, (param, var_info)) in - mem::take(&mut self.free_params).into_iter().enumerate() - { - let name = self.fun_env.get_local_name(param); - let ty = env.get_node_type(var_info.node_id); - let loc = env.get_node_loc(var_info.node_id); - if var_info.modified { - env.error( - &loc, - &format!( - "captured variable `{}` cannot be modified inside of a lambda", // TODO(LAMBDA) - name.display(env.symbol_pool()) - ), - ); - } - params.push(Parameter(name, ty.clone(), loc.clone())); - let new_id = env.new_node(loc, ty); - closure_args.push(ExpData::Temporary(new_id, param).into_exp()); - param_index_mapping.insert(param, used_param_count); - } - // Add captured locals - for (name, var_info) in mem::take(&mut self.free_locals) { - let ty = env.get_node_type(var_info.node_id); - let loc = env.get_node_loc(var_info.node_id); - if var_info.modified { + let module_id = self.fun_env.module_env.get_id(); + + match capture_kind { + LambdaCaptureKind::Move => { + // OK. + }, + LambdaCaptureKind::Default | LambdaCaptureKind::Copy => { + let loc = env.get_node_loc(id); env.error( &loc, - &format!( - "captured variable `{}` cannot be modified inside of a lambda", // TODO(LAMBDA) - name.display(env.symbol_pool()) - ), + // TODO(LAMBDA) + "Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call." ); - } - params.push(Parameter(name, ty.clone(), loc.clone())); - let new_id = env.new_node(loc, ty); - closure_args.push(ExpData::LocalVar(new_id, name).into_exp()) - } + return None; + }, + }; + + // params = new Parameter for each free var to represent it in the lifted function + // 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; 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()?; + + // Some(ExpData::Invalid(env.clone_node(id)).into_exp()); // Add lambda args. For dealing with patterns in lambdas (`|S{..}|e`) we need // to collect a list of bindings. let mut bindings = vec![]; + let mut lambda_params = vec![]; for (i, arg) in pat.clone().flatten().into_iter().enumerate() { let id = arg.node_id(); let ty = env.get_node_type(id); let loc = env.get_node_loc(id); if let Pattern::Var(_, name) = arg { - params.push(Parameter(name, ty, loc)) + lambda_params.push(Parameter(name, ty, loc)); } else { let name = self.gen_parameter_name(i); - params.push(Parameter(name, ty.clone(), loc.clone())); + lambda_params.push(Parameter(name, ty.clone(), loc.clone())); let new_id = env.new_node(loc, ty); + if let Some(inst) = env.get_node_instantiation_opt(id) { + env.set_node_instantiation(new_id, inst); + } bindings.push((arg.clone(), ExpData::LocalVar(new_id, name).into_exp())) } } + + // We can rewrite a lambda directly into a curry expression if: + // - lambda parameters are a simple variable tuple (v1, v2, ...) === (bindings.is_empty()) + // + // - lambda body is a function call with + // - each lambda parameter used exactly once as a call argument, in order (possibly with gaps) + // - every other argument is a simple expression containing only constants and free variables + if bindings.is_empty() { + let possible_curry_exp = + self.try_to_reduce_lambda_to_curry(id, body, lambda_params.clone(), &abilities); + if possible_curry_exp.is_some() { + return possible_curry_exp; + } + } + + // Following code assumes params include lambda_params + params.append(&mut lambda_params); + // Add new closure function let fun_name = self.gen_closure_function_name(); let lambda_loc = env.get_node_loc(id).clone(); let lambda_type = env.get_node_type(id); - let result_type = if let Type::Fun(_, result_type) = &lambda_type { + let lambda_inst_opt = env.get_node_instantiation_opt(id); + let result_type = if let Type::Fun(_, result_type, _) = &lambda_type { *result_type.clone() } else { Type::Error // type error reported }; + // Rewrite references to Temporary in the new functions body (#12317) let mut replacer = |id: NodeId, target: RewriteTarget| { if let RewriteTarget::Temporary(temp) = target { @@ -370,23 +732,52 @@ impl<'a> ExpRewriterFunctions for LambdaLifter<'a> { None }; 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 is not yet supported." + ); + return None; + }; self.lifted.push(ClosureFunction { loc: lambda_loc.clone(), - fun_id: FunId::new(fun_name), + fun_id, type_params: self.fun_env.get_type_parameters(), params, - result_type, + result_type: result_type.clone(), def: self.bind(bindings, body), }); - // Return closure expression - let id = env.new_node(lambda_loc, lambda_type); - Some( - ExpData::Call( - id, - Operation::Closure(self.fun_env.module_env.get_id(), FunId::new(fun_name)), - closure_args, - ) - .into_exp(), - ) + + // Create an expression for the function reference + let fn_type = Type::Fun( + Box::new(Type::Tuple(params_types)), + Box::new(result_type), + abilities, + ); + let fn_exp = self.make_move_fn_exp( + lambda_loc.clone(), + fn_type, + module_id, + fun_id, + lambda_inst_opt.clone(), + ); + + let bound_param_count = closure_args.len(); + if bound_param_count == 0 { + // No free variables, just return the function reference + Some(fn_exp) + } else { + // Create and return closure expression + let id = env.new_node(lambda_loc, lambda_type); + if let Some(inst) = lambda_inst_opt { + env.set_node_instantiation(id, inst); + } + closure_args.insert(0, fn_exp); + Some(ExpData::Call(id, Operation::EarlyBind, closure_args).into_exp()) + } } } diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs b/third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs index 2851f5c2b79c3..9e7adfe62d3b1 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs @@ -159,8 +159,8 @@ impl RewriteTargets { } impl RewriteTarget { - /// Gets the call sites for the target. - pub fn called_funs_with_call_sites( + /// Gets the functions called or referenced in the target. + pub fn used_funs_with_uses( &self, env: &GlobalEnv, ) -> BTreeMap, BTreeSet> { @@ -179,7 +179,7 @@ impl RewriteTarget { .unwrap_or_default(), SpecBlock(target) => { let spec = env.get_spec_block(target); - spec.called_funs_with_callsites() + spec.used_funs_with_uses() }, } } diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs b/third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs index dd9fd65ae1402..1251e40f021ee 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs @@ -70,7 +70,7 @@ pub fn run_spec_rewriter(env: &mut GlobalEnv) { if let RewriteState::Def(def) = target.get_env_state(env) { let mut spec_callees = BTreeSet::new(); def.visit_inline_specs(&mut |spec| { - spec_callees.extend(spec.called_funs_with_callsites().into_keys()); + spec_callees.extend(spec.used_funs_with_uses().into_keys()); true // keep going }); spec_callees @@ -78,10 +78,9 @@ pub fn run_spec_rewriter(env: &mut GlobalEnv) { BTreeSet::new() } }, - RewriteTarget::SpecFun(_) | RewriteTarget::SpecBlock(_) => target - .called_funs_with_call_sites(env) - .into_keys() - .collect(), + RewriteTarget::SpecFun(_) | RewriteTarget::SpecBlock(_) => { + target.used_funs_with_uses(env).into_keys().collect() + }, }; for callee in callees { called_funs.insert(callee); diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/unused_params_checker.rs b/third_party/move/move-compiler-v2/src/env_pipeline/unused_params_checker.rs index e9da0d5cbb053..a7a22a0186aca 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/unused_params_checker.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/unused_params_checker.rs @@ -60,7 +60,7 @@ fn used_type_parameters_in_ty(ty: &Type) -> BTreeSet { }, Type::TypeParameter(i) => BTreeSet::from([*i]), Type::Vector(ty) => used_type_parameters_in_ty(ty), - Type::Fun(t1, t2) => [t1, t2] + Type::Fun(t1, t2, _) => [t1, t2] .iter() .flat_map(|t| used_type_parameters_in_ty(t)) .collect(), 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 ab7c9b862dbd0..ce120a5ca1170 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 @@ -367,7 +367,7 @@ impl ModuleGenerator { ReferenceKind::Mutable => FF::SignatureToken::MutableReference(target_ty), } }, - Fun(_param_ty, _result_ty) => { + Fun(_param_ty, _result_ty, _abilities) => { // TODO(LAMBDA) ctx.error( loc, @@ -1077,7 +1077,7 @@ impl<'env> ModuleContext<'env> { if fun.is_inline() { continue; } - if let Some(callees) = fun.get_called_functions() { + if let Some(callees) = fun.get_used_functions() { let mut usage = usage_map[&fun.get_id()].clone(); let count = usage.len(); // Extend usage by that of callees from the same module. Acquires is only diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda3.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda3.exp index 7d3fd078fd386..a6dcbc1ea7faf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda3.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda3.exp @@ -2,7 +2,7 @@ module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast_err.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast_err.exp index be195864c9919..0ad81c2553b97 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast_err.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast_err.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|(u64, integer)|u64` to a function which expects argument of type `|(u64, vector)|u64` +error: cannot pass `|(u64, integer)|u64 with copy+store` to a function which expects argument of type `|(u64, vector)|u64` ┌─ tests/checking/inlining/lambda_cast_err.move:7:53 │ 7 │ vector::fold(gas_schedule_blob, (0 as u64), |sum, addend| sum + (addend as u64)) diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_mismatch.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_mismatch.exp index 3ed89d4ab8da6..a4c911fe997fd 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_mismatch.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_param_mismatch.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|u64|u64` to a function which expects argument of type `|u64|` +error: cannot pass `|u64|u64 with copy+store` to a function which expects argument of type `|u64|` ┌─ tests/checking/inlining/lambda_param_mismatch.move:12:33 │ 12 │ vector::for_each(input, |item| { diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/expressions_err.exp b/third_party/move/move-compiler-v2/tests/checking/specs/expressions_err.exp index 3e4cf9f7f3155..fccf940f86384 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/expressions_err.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/expressions_err.exp @@ -36,7 +36,7 @@ error: cannot pass `u256` to a function which expects argument of type `bool` 32 │ wrongly_typed_callee(1, 1) // Wrongly typed function application │ ^ -error: cannot pass `|num|bool` to a function which expects argument of type `|num|num` +error: cannot pass `|num|bool with copy+store` to a function which expects argument of type `|num|num` ┌─ tests/checking/specs/expressions_err.move:37:36 │ 37 │ wrongly_typed_fun_arg_callee(|x| false) // Wrongly typed function argument. 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 ebcdc1fcfcfdb..51ad60912dcd3 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 @@ -24,7 +24,7 @@ error: cannot use `()` with an operator which expects a value of type `u64` 56 │ i = i + action(XVector::borrow(v, i)); // expected to have wrong result type │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot return `u64` from a function with result type `|integer|` +error: cannot return `u64` from a function with result type `|integer| with copy+store` ┌─ tests/checking/typing/lambda.move:61:9 │ 61 │ x(1) // expected to be not a function diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/lambda3.exp b/third_party/move/move-compiler-v2/tests/checking/typing/lambda3.exp index f89935a0c3358..2d5f47f0bb197 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/lambda3.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/lambda3.exp @@ -2,7 +2,7 @@ module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } 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 7817686444d8f..b3c6fa59c5fb7 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 @@ -18,7 +18,7 @@ error: cannot use `()` with an operator which expects a value of type `u64` 56 │ i = i + action(XVector::borrow(v, i)); // expected to have wrong result type │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot return `u64` from a function with result type `|integer|` +error: cannot return `u64` from a function with result type `|integer| with copy+store` ┌─ tests/checking/typing/lambda_typed.move:61:9 │ 61 │ x(1) // expected to be not a function @@ -30,7 +30,7 @@ error: cannot use `&u64` with an operator which expects a value of type `integer 67 │ foreach(&v, |e: &u64| sum = sum + e) // expected to cannot infer type │ ^ -error: cannot pass `|&u64|u64` to a function which expects argument of type `|&u64|` +error: cannot pass `|&u64|u64 with copy+store` to a function which expects argument of type `|&u64|` ┌─ tests/checking/typing/lambda_typed.move:73:21 │ 73 │ foreach(&v, |e: &u64| { sum = sum + *e; *e }) // expected to have wrong result type of lambda diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.lambda.exp index aecce2d0e9059..0571c26b0aa88 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.lambda.exp @@ -218,114 +218,21 @@ module 0xcafe::m { } // end 0xcafe::m -// -- Model dump after env processor lambda-lifting: -module 0xcafe::m { - private fun map(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun no_name_clash(x: u64,c: u64): u64 { - m::map(x, closure m::no_name_clash$lambda$1(c)) - } - private fun with_name_clash1(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash1$lambda$1(c)) - } - private fun with_name_clash2(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash2$lambda$1(c)) - } - private fun no_name_clash$lambda$1(c: u64,y: u64): u64 { - Add(y, c) - } - private fun with_name_clash1$lambda$1(c: u64,x: u64): u64 { - Add(x, c) - } - private fun with_name_clash2$lambda$1(c: u64,x: u64): u64 { - Add({ - let x: u64 = Add(c, 1); - x - }, x) - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification checker: -module 0xcafe::m { - private fun map(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun no_name_clash(x: u64,c: u64): u64 { - m::map(x, closure m::no_name_clash$lambda$1(c)) - } - private fun with_name_clash1(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash1$lambda$1(c)) - } - private fun with_name_clash2(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash2$lambda$1(c)) - } - private fun no_name_clash$lambda$1(c: u64,y: u64): u64 { - Add(y, c) - } - private fun with_name_clash1$lambda$1(c: u64,x: u64): u64 { - Add(x, c) - } - private fun with_name_clash2$lambda$1(c: u64,x: u64): u64 { - Add({ - let x: u64 = Add(c, 1); - x - }, x) - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification rewriter: -module 0xcafe::m { - private fun map(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun no_name_clash(x: u64,c: u64): u64 { - m::map(x, closure m::no_name_clash$lambda$1(c)) - } - private fun with_name_clash1(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash1$lambda$1(c)) - } - private fun with_name_clash2(x: u64,c: u64): u64 { - m::map(x, closure m::with_name_clash2$lambda$1(c)) - } - private fun no_name_clash$lambda$1(c: u64,y: u64): u64 { - Add(y, c) - } - private fun with_name_clash1$lambda$1(c: u64,x: u64): u64 { - Add(x, c) - } - private fun with_name_clash2$lambda$1(c: u64,x: u64): u64 { - Add({ - let x: u64 = Add(c, 1); - x - }, x) - } -} // end 0xcafe::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda-lifting/basic.move:5:9 - │ -5 │ f(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/basic.move:10:16 │ 10 │ map(x, |y| y + c) │ ^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/basic.move:15:16 │ 15 │ map(x, |x| x + c) │ ^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/basic.move:20:16 │ 20 │ map(x, |x| { diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.lambda.exp index 3664bd2e163bb..74dee022d7295 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.lambda.exp @@ -503,26 +503,52 @@ module 0xcafe::m { Diagnostics: -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda-lifting/modify.move:14:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda-lifting/modify.move:13:16 │ -14 │ x = 2; - │ ^ +13 │ map(x, |y| { + │ ╭────────────────^ +14 │ │ x = 2; +15 │ │ y + c +16 │ │ }) + │ ╰─────────^ -error: captured variable `c` cannot be modified inside of a lambda - ┌─ tests/lambda-lifting/modify.move:21:26 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda-lifting/modify.move:20:16 │ -21 │ let r = &mut c; - │ ^ +20 │ map(x, |y| { + │ ╭────────────────^ +21 │ │ let r = &mut c; +22 │ │ y + *r +23 │ │ }) + │ ╰─────────^ -error: captured variable `z` cannot be modified inside of a lambda - ┌─ tests/lambda-lifting/modify.move:29:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda-lifting/modify.move:28:16 │ -29 │ z = 2; - │ ^ +28 │ map(x, |y| { + │ ╭────────────────^ +29 │ │ z = 2; +30 │ │ y + c +31 │ │ }) + │ ╰─────────^ -error: captured variable `z` cannot be modified inside of a lambda - ┌─ tests/lambda-lifting/modify.move:37:26 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda-lifting/modify.move:36:16 │ -37 │ let r = &mut z; - │ ^ +36 │ map(x, |y| { + │ ╭────────────────^ +37 │ │ let r = &mut z; +38 │ │ y + *r +39 │ │ }) + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda-lifting/modify.move:44:16 + │ +44 │ map(x, |y| { + │ ╭────────────────^ +45 │ │ let r = &z; +46 │ │ y + *r +47 │ │ }) + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.lambda.exp index cb00e1c4256e8..8686807511bc5 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.lambda.exp @@ -152,87 +152,15 @@ module 0xcafe::m { } // end 0xcafe::m -// -- Model dump after env processor lambda-lifting: -module 0xcafe::m { - private fun map1(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun map2(x: u8,f: |u8|u8): u8 { - (f)(x) - } - private fun nested(x: u64,c: u64): u64 { - m::map1(x, closure m::nested$lambda$2(c)) - } - private fun nested$lambda$1(c: u64,y: u8): u8 { - Add(y, Cast(c)) - } - private fun nested$lambda$2(c: u64,y: u64): u64 { - Cast(m::map2(Cast(Sub(y, c)), closure m::nested$lambda$1(c))) - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification checker: -module 0xcafe::m { - private fun map1(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun map2(x: u8,f: |u8|u8): u8 { - (f)(x) - } - private fun nested(x: u64,c: u64): u64 { - m::map1(x, closure m::nested$lambda$2(c)) - } - private fun nested$lambda$1(c: u64,y: u8): u8 { - Add(y, Cast(c)) - } - private fun nested$lambda$2(c: u64,y: u64): u64 { - Cast(m::map2(Cast(Sub(y, c)), closure m::nested$lambda$1(c))) - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification rewriter: -module 0xcafe::m { - private fun map1(x: u64,f: |u64|u64): u64 { - (f)(x) - } - private fun map2(x: u8,f: |u8|u8): u8 { - (f)(x) - } - private fun nested(x: u64,c: u64): u64 { - m::map1(x, closure m::nested$lambda$2(c)) - } - private fun nested$lambda$1(c: u64,y: u8): u8 { - Add(y, Cast(c)) - } - private fun nested$lambda$2(c: u64,y: u64): u64 { - Cast(m::map2(Cast(Sub(y, c)), closure m::nested$lambda$1(c))) - } -} // end 0xcafe::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda-lifting/nested.move:5:9 - │ -5 │ f(x) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda-lifting/nested.move:10:9 - │ -10 │ f(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/nested.move:15:42 │ 15 │ map1(x, |y| (map2((y - c as u8), |y| y + (c as u8)) as u64)) │ ^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/nested.move:15:17 │ 15 │ map1(x, |y| (map2((y - c as u8), |y| y + (c as u8)) as u64)) diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.lambda.exp index 6a897fa9ce92d..61e3d5839f064 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.lambda.exp @@ -185,84 +185,9 @@ module 0xcafe::m { } // end 0xcafe::m -// -- Model dump after env processor lambda-lifting: -module 0xcafe::m { - struct S { - x: T, - } - private fun consume(s: S,x: T,f: |(S, T)|T): T { - (f)(s, x) - } - private fun pattern(s: S,x: u64): u64 { - m::consume(s, x, closure m::pattern$lambda$1()) - } - private fun pattern$lambda$1(param$0: S,_y: u64): u64 { - { - let m::S{ x } = param$0; - { - let y: u64 = x; - Add(x, y) - } - } - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification checker: -module 0xcafe::m { - struct S { - x: T, - } - private fun consume(s: S,x: T,f: |(S, T)|T): T { - (f)(s, x) - } - private fun pattern(s: S,x: u64): u64 { - m::consume(s, x, closure m::pattern$lambda$1()) - } - private fun pattern$lambda$1(param$0: S,_y: u64): u64 { - { - let m::S{ x } = param$0; - { - let y: u64 = x; - Add(x, y) - } - } - } -} // end 0xcafe::m - - -// -- Model dump after env processor specification rewriter: -module 0xcafe::m { - struct S { - x: T, - } - private fun consume(s: S,x: T,f: |(S, T)|T): T { - (f)(s, x) - } - private fun pattern(s: S,x: u64): u64 { - m::consume(s, x, closure m::pattern$lambda$1()) - } - private fun pattern$lambda$1(param$0: S,_y: u64): u64 { - { - let m::S{ x } = param$0; - { - let y: u64 = x; - Add(x, y) - } - } - } -} // end 0xcafe::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda-lifting/pattern.move:10:9 - │ -10 │ f(s, x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda-lifting/pattern.move:15:23 │ 15 │ consume(s, x, |S{x}, _y| { let y = x; x + y}) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/break_continue_in_lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/break_continue_in_lambda.lambda.exp index 356f716bf1076..bb292947347d0 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/break_continue_in_lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/break_continue_in_lambda.lambda.exp @@ -1043,364 +1043,22 @@ module 0xc0ffee::m { } // end 0xc0ffee::m -// -- Model dump after env processor lambda-lifting: -module 0xc0ffee::m { - public fun bar(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk2(closure m::bar$lambda$1()); - m::brk2(closure m::bar$lambda$2()); - m::brk2(closure m::bar$lambda$3()); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun brk() { - break; - Tuple() - } - private fun brk2(f: |()|) { - (f)(); - Tuple() - } - private fun brk3() { - loop { - if true { - break; - Tuple() - } else { - break - } - } - } - private fun brk4() { - loop { - if true { - continue; - Tuple() - } else { - break - } - } - } - private fun broken() { - break; - Tuple() - } - private fun continued() { - continue; - Tuple() - } - public fun foo(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk(); - m::brk3(); - m::brk4(); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun bar$lambda$1() { - break - } - private fun bar$lambda$2() { - loop { - if true { - break - } else { - break - } - } - } - private fun bar$lambda$3() { - loop { - if true { - continue - } else { - break - } - } - } -} // end 0xc0ffee::m - - -// -- Model dump after env processor specification checker: -module 0xc0ffee::m { - public fun bar(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk2(closure m::bar$lambda$1()); - m::brk2(closure m::bar$lambda$2()); - m::brk2(closure m::bar$lambda$3()); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun brk() { - break; - Tuple() - } - private fun brk2(f: |()|) { - (f)(); - Tuple() - } - private fun brk3() { - loop { - if true { - break; - Tuple() - } else { - break - } - } - } - private fun brk4() { - loop { - if true { - continue; - Tuple() - } else { - break - } - } - } - private fun broken() { - break; - Tuple() - } - private fun continued() { - continue; - Tuple() - } - public fun foo(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk(); - m::brk3(); - m::brk4(); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun bar$lambda$1() { - break - } - private fun bar$lambda$2() { - loop { - if true { - break - } else { - break - } - } - } - private fun bar$lambda$3() { - loop { - if true { - continue - } else { - break - } - } - } -} // end 0xc0ffee::m - - -// -- Model dump after env processor specification rewriter: -module 0xc0ffee::m { - public fun bar(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk2(closure m::bar$lambda$1()); - m::brk2(closure m::bar$lambda$2()); - m::brk2(closure m::bar$lambda$3()); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun brk() { - break; - Tuple() - } - private fun brk2(f: |()|) { - (f)(); - Tuple() - } - private fun brk3() { - loop { - if true { - break; - Tuple() - } else { - break - } - } - } - private fun brk4() { - loop { - if true { - continue; - Tuple() - } else { - break - } - } - } - private fun broken() { - break; - Tuple() - } - private fun continued() { - continue; - Tuple() - } - public fun foo(): u64 { - { - let i: u64 = 0; - loop { - if Lt(i, 10) { - i: u64 = Add(i, 1); - if Eq(i, 5) { - m::brk(); - m::brk3(); - m::brk4(); - Tuple() - } else { - Tuple() - } - } else { - break - } - }; - i - } - } - private fun bar$lambda$1() { - break - } - private fun bar$lambda$2() { - loop { - if true { - break - } else { - break - } - } - } - private fun bar$lambda$3() { - loop { - if true { - continue - } else { - break - } - } - } -} // end 0xc0ffee::m - - Diagnostics: -error: missing enclosing loop statement - ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:3:9 - │ -3 │ break; - │ ^^^^^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:7:9 - │ -7 │ f(); - │ ^ - -error: missing enclosing loop statement - ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:40:26 - │ -40 │ brk2(| | break); - │ ^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:40:22 │ 40 │ brk2(| | break); │ ^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:41:8 │ 41 │ brk2(| | while (true) { break }); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:42:8 │ 42 │ brk2(| | while (true) { continue }); │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing enclosing loop statement - ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:49:2 - │ -49 │ break; - │ ^^^^^ - -error: missing enclosing loop statement - ┌─ tests/lambda/inline-parity/break_continue_in_lambda.move:53:2 - │ -53 │ continue; - │ ^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991.lambda.exp index fea2410cdc948..b0ca3260fc823 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991.lambda.exp @@ -174,111 +174,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 110) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 110) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 110) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991.move:4:9 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991.move:4:20 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991.move:8:21 │ 8 │ assert!(foo(|x, _| x, |_, y| y, 10, 100) == 110, 0); │ ^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991.move:8:31 │ 8 │ assert!(foo(|x, _| x, |_, y| y, 10, 100) == 110, 0); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam.lambda.exp index b1ce2d980a7d7..613fae6c520e4 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam.lambda.exp @@ -174,129 +174,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 3 - } - } - } - private fun test$lambda$2(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 10 - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 3 - } - } - } - private fun test$lambda$2(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 10 - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 3 - } - } - } - private fun test$lambda$2(param$0: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - { - let _: u64 = param$0; - 10 - } - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991_noparam.move:4:9 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991_noparam.move:4:20 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991_noparam.move:8:21 │ 8 │ assert!(foo(|_, _| 3, |_, _| 10, 10, 100) == 13, 0); │ ^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991_noparam.move:8:31 │ 8 │ assert!(foo(|_, _| 3, |_, _| 10, 10, 100) == 13, 0); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam2.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam2.lambda.exp index f0eec150641eb..e5934586b182d 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam2.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991_noparam2.lambda.exp @@ -174,111 +174,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |u64|u64,g: |u64|u64,x: u64,_: u64): u64 { - Add((f)(x), (g)(x)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } - private fun test$lambda$2(param$0: u64): u64 { - { - let _: u64 = param$0; - 10 - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |u64|u64,g: |u64|u64,x: u64,_: u64): u64 { - Add((f)(x), (g)(x)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } - private fun test$lambda$2(param$0: u64): u64 { - { - let _: u64 = param$0; - 10 - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |u64|u64,g: |u64|u64,x: u64,_: u64): u64 { - Add((f)(x), (g)(x)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 10, 100), 13) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } - private fun test$lambda$2(param$0: u64): u64 { - { - let _: u64 = param$0; - 10 - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991_noparam2.move:4:9 - │ -4 │ f(x) + g(x) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991_noparam2.move:4:16 - │ -4 │ f(x) + g(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991_noparam2.move:8:21 │ 8 │ assert!(foo(|_| 3, |_| 10, 10, 100) == 13, 0); │ ^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991_noparam2.move:8:28 │ 8 │ assert!(foo(|_| 3, |_| 10, 10, 100) == 13, 0); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991a.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991a.lambda.exp index 172a728293cdf..5638e37c59b27 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991a.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991a.lambda.exp @@ -174,153 +174,27 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,h: |(u64, u64)|u64,i: |(u64, u64)|u64,x: u64,y: u64): u64 { - Add(Add(Add((f)(x, y), (g)(x, y)), (h)(x, y)), (i)(x, y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), closure Test::test$lambda$3(), closure Test::test$lambda$4(), 10, 100), 220) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } - private fun test$lambda$3(a: u64,_b: u64): u64 { - a - } - private fun test$lambda$4(_c: u64,d: u64): u64 { - d - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,h: |(u64, u64)|u64,i: |(u64, u64)|u64,x: u64,y: u64): u64 { - Add(Add(Add((f)(x, y), (g)(x, y)), (h)(x, y)), (i)(x, y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), closure Test::test$lambda$3(), closure Test::test$lambda$4(), 10, 100), 220) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } - private fun test$lambda$3(a: u64,_b: u64): u64 { - a - } - private fun test$lambda$4(_c: u64,d: u64): u64 { - d - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,h: |(u64, u64)|u64,i: |(u64, u64)|u64,x: u64,y: u64): u64 { - Add(Add(Add((f)(x, y), (g)(x, y)), (h)(x, y)), (i)(x, y)) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), closure Test::test$lambda$3(), closure Test::test$lambda$4(), 10, 100), 220) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun test$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } - private fun test$lambda$3(a: u64,_b: u64): u64 { - a - } - private fun test$lambda$4(_c: u64,d: u64): u64 { - d - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991a.move:6:13 - │ -6 │ f(x, y) + g(x, y) + h(x, y) + i(x, y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991a.move:6:23 - │ -6 │ f(x, y) + g(x, y) + h(x, y) + i(x, y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991a.move:6:33 - │ -6 │ f(x, y) + g(x, y) + h(x, y) + i(x, y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991a.move:6:43 - │ -6 │ f(x, y) + g(x, y) + h(x, y) + i(x, y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991a.move:10:21 │ 10 │ assert!(foo(|x, _| x, |_, y| y, │ ^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991a.move:10:31 │ 10 │ assert!(foo(|x, _| x, |_, y| y, │ ^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991a.move:11:6 │ 11 │ |a, _b| a, |_c, d| d, │ ^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991a.move:11:17 │ 11 │ |a, _b| a, |_c, d| d, diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991b.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991b.lambda.exp index 4d75c19204ac0..3bacb83364f2b 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991b.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991b.lambda.exp @@ -174,81 +174,9 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - (g)(x, _y) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100), 100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - (g)(x, _y) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100), 100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - (g)(x, _y) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100), 100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991b.move:4:9 - │ -4 │ g(x, _y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991b.move:8:21 │ 8 │ assert!(foo(|_, y| y, diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991c.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991c.lambda.exp index 486526cead33b..43b8d5d0216de 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991c.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/bug_10991c.lambda.exp @@ -174,90 +174,9 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(g: |(u64, u64, u64, u64)|u64,x: u64,y: u64,z: u64,q: u64): u64 { - (g)(x, y, z, q) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100, 1000, 10000), 10100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64,param$2: u64,q: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - Add(y, q) - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(g: |(u64, u64, u64, u64)|u64,x: u64,y: u64,z: u64,q: u64): u64 { - (g)(x, y, z, q) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100, 1000, 10000), 10100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64,param$2: u64,q: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - Add(y, q) - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(g: |(u64, u64, u64, u64)|u64,x: u64,y: u64,z: u64,q: u64): u64 { - (g)(x, y, z, q) - } - public fun test() { - if Eq(Test::foo(closure Test::test$lambda$1(), 10, 100, 1000, 10000), 10100) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - private fun test$lambda$1(param$0: u64,y: u64,param$2: u64,q: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - Add(y, q) - } - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/bug_10991c.move:4:9 - │ -4 │ g(x, y, z, q) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/bug_10991c.move:8:21 │ 8 │ assert!(foo(|_, y, _, q| y + q, diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/dotdot_valid.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/dotdot_valid.lambda.exp index de57ae7f20e1a..1855166775783 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/dotdot_valid.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/dotdot_valid.lambda.exp @@ -3265,940 +3265,9 @@ module 0x42::test { } // end 0x42::test -// -- Model dump after env processor lambda-lifting: -module 0x42::test { - enum E1 { - A { - 0: u8, - 1: bool, - } - B { - 0: u8, - } - C { - x: u8, - y: S1, - } - } - struct S0 { - dummy_field: bool, - } - struct S1 { - 0: u8, - } - struct S2 { - 0: bool, - 1: S0, - } - struct S3 { - x: bool, - y: u8, - } - struct S4 { - x: T, - y: S3, - } - struct S5 { - 0: T, - 1: U, - } - struct S6 { - x: T, - y: U, - } - struct S7 { - 0: u8, - 1: u16, - 2: u32, - 3: u64, - } - private fun lambda_param(f: |S2|bool): bool { - { - let x: S2 = pack test::S2(true, pack test::S0(false)); - (f)(x) - } - } - private fun nested1(x: S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested1_ref(x: &S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested2(x: S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested2_ref(x: &S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested3(x: S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested3_ref(x: &S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested4(x: S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun nested4_ref(x: &S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun simple_0(x: S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_0_ref(x: &S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_1(x: S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_1_ref(x: &mut S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_2(x: S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_2_ref(x: &S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_3(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_3_ref(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_4(x: E1): u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x, y: _ } => { - x - } - } - - } - private fun simple_4_ref(x: &E1): &u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - } - - } - private fun simple_5(x: E1): u8 { - match (x) { - test::E1::A{ 0: _, 1: y } => { - if y { - 1 - } else { - 0 - } - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x: _, y: test::S1{ 0: x } } => { - x - } - } - - } - private fun simple_6(x: &S7) { - { - let test::S7{ 0: _w, 1: _, 2: _, 3: _z } = x; - { - let test::S7{ 0: _w, 1: _x, 2: _y, 3: _z } = x; - Tuple() - } - } - } - private fun test_lambda_param(): bool { - test::lambda_param(closure test::test_lambda_param$lambda$1()) - } - private fun test_lambda_param$lambda$1(param$0: S2): bool { - { - let test::S2{ 0: x, 1: _ } = param$0; - x - } - } -} // end 0x42::test - - -// -- Model dump after env processor specification checker: -module 0x42::test { - enum E1 { - A { - 0: u8, - 1: bool, - } - B { - 0: u8, - } - C { - x: u8, - y: S1, - } - } - struct S0 { - dummy_field: bool, - } - struct S1 { - 0: u8, - } - struct S2 { - 0: bool, - 1: S0, - } - struct S3 { - x: bool, - y: u8, - } - struct S4 { - x: T, - y: S3, - } - struct S5 { - 0: T, - 1: U, - } - struct S6 { - x: T, - y: U, - } - struct S7 { - 0: u8, - 1: u16, - 2: u32, - 3: u64, - } - private fun lambda_param(f: |S2|bool): bool { - { - let x: S2 = pack test::S2(true, pack test::S0(false)); - (f)(x) - } - } - private fun nested1(x: S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested1_ref(x: &S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested2(x: S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested2_ref(x: &S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested3(x: S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested3_ref(x: &S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested4(x: S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun nested4_ref(x: &S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun simple_0(x: S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_0_ref(x: &S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_1(x: S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_1_ref(x: &mut S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_2(x: S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_2_ref(x: &S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_3(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_3_ref(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_4(x: E1): u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x, y: _ } => { - x - } - } - - } - private fun simple_4_ref(x: &E1): &u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - } - - } - private fun simple_5(x: E1): u8 { - match (x) { - test::E1::A{ 0: _, 1: y } => { - if y { - 1 - } else { - 0 - } - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x: _, y: test::S1{ 0: x } } => { - x - } - } - - } - private fun simple_6(x: &S7) { - { - let test::S7{ 0: _w, 1: _, 2: _, 3: _z } = x; - { - let test::S7{ 0: _w, 1: _x, 2: _y, 3: _z } = x; - Tuple() - } - } - } - private fun test_lambda_param(): bool { - test::lambda_param(closure test::test_lambda_param$lambda$1()) - } - private fun test_lambda_param$lambda$1(param$0: S2): bool { - { - let test::S2{ 0: x, 1: _ } = param$0; - x - } - } -} // end 0x42::test - - -// -- Model dump after env processor specification rewriter: -module 0x42::test { - enum E1 { - A { - 0: u8, - 1: bool, - } - B { - 0: u8, - } - C { - x: u8, - y: S1, - } - } - struct S0 { - dummy_field: bool, - } - struct S1 { - 0: u8, - } - struct S2 { - 0: bool, - 1: S0, - } - struct S3 { - x: bool, - y: u8, - } - struct S4 { - x: T, - y: S3, - } - struct S5 { - 0: T, - 1: U, - } - struct S6 { - x: T, - y: U, - } - struct S7 { - 0: u8, - 1: u16, - 2: u32, - 3: u64, - } - private fun lambda_param(f: |S2|bool): bool { - { - let x: S2 = pack test::S2(true, pack test::S0(false)); - (f)(x) - } - } - private fun nested1(x: S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested1_ref(x: &S4) { - { - let test::S4{ x: _x, y: _ } = x; - { - let test::S4{ x: _, y: _y } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _x, y: _ } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - { - let test::S4{ x: _, y: test::S3{ x: _, y: _y } } = x; - { - let test::S4{ x: _x2, y: test::S3{ x: _x1, y: _ } } = x; - Tuple() - } - } - } - } - } - } - } - } - private fun nested2(x: S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested2_ref(x: &S5) { - { - let test::S5{ 0: _, 1: test::S1{ 0: _ } } = x; - Tuple() - } - } - private fun nested3(x: S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested3_ref(x: &S5>) { - { - let test::S5>{ 0: _, 1: test::S4{ x: _, y: _ } } = x; - Tuple() - } - } - private fun nested4(x: S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun nested4_ref(x: &S4) { - { - let test::S4{ x: test::S1{ 0: _ }, y: _ } = x; - Tuple() - } - } - private fun simple_0(x: S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_0_ref(x: &S0) { - { - let test::S0{ dummy_field: _ } = x; - Tuple() - } - } - private fun simple_1(x: S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_1_ref(x: &mut S1) { - { - let test::S1{ 0: _ } = x; - Tuple() - } - } - private fun simple_2(x: S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_2_ref(x: &S2) { - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _ } = x; - { - let test::S2{ 0: _, 1: _x } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _, 1: _ } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - { - let test::S2{ 0: _x, 1: _y } = x; - Tuple() - } - } - } - } - } - } - } - } - } - private fun simple_3(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_3_ref(x: S3) { - { - let test::S3{ x: _, y: _ } = x; - { - let test::S3{ x: _x, y: _ } = x; - { - let test::S3{ x: _, y: _y } = x; - Tuple() - } - } - } - } - private fun simple_4(x: E1): u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x, y: _ } => { - x - } - } - - } - private fun simple_4_ref(x: &E1): &u8 { - match (x) { - test::E1::A{ 0: x, 1: _ } => { - x - } - test::E1::B{ 0: x } => { - x - } - } - - } - private fun simple_5(x: E1): u8 { - match (x) { - test::E1::A{ 0: _, 1: y } => { - if y { - 1 - } else { - 0 - } - } - test::E1::B{ 0: x } => { - x - } - test::E1::C{ x: _, y: test::S1{ 0: x } } => { - x - } - } - - } - private fun simple_6(x: &S7) { - { - let test::S7{ 0: _w, 1: _, 2: _, 3: _z } = x; - { - let test::S7{ 0: _w, 1: _x, 2: _y, 3: _z } = x; - Tuple() - } - } - } - private fun test_lambda_param(): bool { - test::lambda_param(closure test::test_lambda_param$lambda$1()) - } - private fun test_lambda_param$lambda$1(param$0: S2): bool { - { - let test::S2{ 0: x, 1: _ } = param$0; - x - } - } -} // end 0x42::test - - Diagnostics: -error: match not exhaustive - ┌─ tests/lambda/inline-parity/dotdot_valid.move:142:16 - │ -142 │ match (x) { - │ ^ - │ - = missing `E1::C{..}` - -error: match not exhaustive - ┌─ tests/lambda/inline-parity/dotdot_valid.move:153:16 - │ -153 │ match (x) { - │ ^ - │ - = missing `E1::C{..}` - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/dotdot_valid.move:177:9 - │ -177 │ f(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/dotdot_valid.move:181:22 │ 181 │ lambda_param(|S2(x, ..)| x) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eq_inline.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eq_inline.lambda.exp index 7fc8364520041..b512cde064cf7 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eq_inline.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eq_inline.lambda.exp @@ -141,54 +141,6 @@ module 0x42::m { } // end 0x42::m -// -- Model dump after env processor lambda-lifting: -module 0x42::m { - private fun foo(f: |&u64|) { - Tuple() - } - private fun g() { - m::foo(closure m::g$lambda$1()); - Tuple() - } - private fun g$lambda$1(v: &u64) { - Eq(v, Borrow(Immutable)(1)); - Tuple() - } -} // end 0x42::m - - -// -- Model dump after env processor specification checker: -module 0x42::m { - private fun foo(f: |&u64|) { - Tuple() - } - private fun g() { - m::foo(closure m::g$lambda$1()); - Tuple() - } - private fun g$lambda$1(v: &u64) { - Eq(v, Borrow(Immutable)(1)); - Tuple() - } -} // end 0x42::m - - -// -- Model dump after env processor specification rewriter: -module 0x42::m { - private fun foo(f: |&u64|) { - Tuple() - } - private fun g() { - m::foo(closure m::g$lambda$1()); - Tuple() - } - private fun g$lambda$1(v: &u64) { - Eq(v, Borrow(Immutable)(1)); - Tuple() - } -} // end 0x42::m - - Diagnostics: warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f` @@ -197,9 +149,7 @@ warning: Unused parameter `f`. Consider removing or prefixing with an underscore 3 │ fun foo(f: |&u64|) { │ ^ - -Diagnostics: -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/eq_inline.move:7:13 │ 7 │ foo(|v| { diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eval_ignored_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eval_ignored_param.lambda.exp index 2bbc4c4bfd603..678e8fa29367f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eval_ignored_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/eval_ignored_param.lambda.exp @@ -339,165 +339,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |(u64, u64, u64)|u64,g: |(u64, u64, u64)|u64,x: u64,_: u64,y: u64,z: u64): u64 { - { - let r1: u64 = (f)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - { - let r2: u64 = (g)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - Add(Add(Add(Add(r1, r2), Mul(3, x)), Mul(5, y)), Mul(7, z)) - } - } - } - public fun test() { - { - let r: u64 = Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 1, 10, 100, 1000); - if Eq(r, 9637) { - Tuple() - } else { - Abort(r) - }; - Tuple() - } - } - private fun test$lambda$1(x: u64,param$1: u64,z: u64): u64 { - { - let _: u64 = param$1; - Mul(x, z) - } - } - private fun test$lambda$2(param$0: u64,y: u64,param$2: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - y - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |(u64, u64, u64)|u64,g: |(u64, u64, u64)|u64,x: u64,_: u64,y: u64,z: u64): u64 { - { - let r1: u64 = (f)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - { - let r2: u64 = (g)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - Add(Add(Add(Add(r1, r2), Mul(3, x)), Mul(5, y)), Mul(7, z)) - } - } - } - public fun test() { - { - let r: u64 = Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 1, 10, 100, 1000); - if Eq(r, 9637) { - Tuple() - } else { - Abort(r) - }; - Tuple() - } - } - private fun test$lambda$1(x: u64,param$1: u64,z: u64): u64 { - { - let _: u64 = param$1; - Mul(x, z) - } - } - private fun test$lambda$2(param$0: u64,y: u64,param$2: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - y - } - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |(u64, u64, u64)|u64,g: |(u64, u64, u64)|u64,x: u64,_: u64,y: u64,z: u64): u64 { - { - let r1: u64 = (f)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - { - let r2: u64 = (g)(x: u64 = Add(x, 1); - x, y: u64 = Add(y, 1); - y, z: u64 = Add(z, 1); - z); - Add(Add(Add(Add(r1, r2), Mul(3, x)), Mul(5, y)), Mul(7, z)) - } - } - } - public fun test() { - { - let r: u64 = Test::foo(closure Test::test$lambda$1(), closure Test::test$lambda$2(), 1, 10, 100, 1000); - if Eq(r, 9637) { - Tuple() - } else { - Abort(r) - }; - Tuple() - } - } - private fun test$lambda$1(x: u64,param$1: u64,z: u64): u64 { - { - let _: u64 = param$1; - Mul(x, z) - } - } - private fun test$lambda$2(param$0: u64,y: u64,param$2: u64): u64 { - { - let _: u64 = param$2; - { - let _: u64 = param$0; - y - } - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/eval_ignored_param.move:4:11 - │ -4 │ let r1 = f({x = x + 1; x}, {y = y + 1; y}, {z = z + 1; z}); - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/eval_ignored_param.move:5:11 - │ -5 │ let r2 = g({x = x + 1; x}, {y = y + 1; y}, {z = z + 1 ; z}); - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/eval_ignored_param.move:10:14 │ 10 │ let r = foo(|x, _, z| x*z, |_, y, _| y, 1, 10, 100, 1000); │ ^^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/eval_ignored_param.move:10:29 │ 10 │ let r = foo(|x, _, z| x*z, |_, y, _| y, 1, 10, 100, 1000); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generic_calls.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generic_calls.lambda.exp index 3381b1bbcf75c..6f699942c47f1 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generic_calls.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generic_calls.lambda.exp @@ -460,150 +460,9 @@ module 0x42::m { } // end 0x42::m -// -- Model dump after env processor lambda-lifting: -module 0x42::m { - struct S { - x: T, - } - private fun id(self: S): S { - self - } - private fun inlined(f: |S|S,s: S) { - (f)(s); - Tuple() - } - private fun receiver(self: S,y: T) { - select m::S.x>(self) = y; - Tuple() - } - private fun receiver_more_generics(self: S,_y: R) { - Tuple() - } - private fun receiver_needs_type_args(self: S,_y: T) { - Abort(1) - } - private fun receiver_ref(self: &S,_y: T) { - Tuple() - } - private fun receiver_ref_mut(self: &mut S,y: T) { - select m::S.x<&mut S>(self) = y - } - private fun test_call_styles(s: S,x: u64) { - m::receiver(s, x); - m::receiver_ref(Borrow(Immutable)(s), x); - m::receiver_ref_mut(Borrow(Mutable)(s), x); - m::receiver_more_generics(s, 22); - m::receiver_needs_type_args(s, x); - Tuple() - } - private fun test_receiver_inference(s: S) { - m::inlined(closure m::test_receiver_inference$lambda$1(), s) - } - private fun test_receiver_inference$lambda$1(s: S): S { - m::id(s) - } -} // end 0x42::m - - -// -- Model dump after env processor specification checker: -module 0x42::m { - struct S { - x: T, - } - private fun id(self: S): S { - self - } - private fun inlined(f: |S|S,s: S) { - (f)(s); - Tuple() - } - private fun receiver(self: S,y: T) { - select m::S.x>(self) = y; - Tuple() - } - private fun receiver_more_generics(self: S,_y: R) { - Tuple() - } - private fun receiver_needs_type_args(self: S,_y: T) { - Abort(1) - } - private fun receiver_ref(self: &S,_y: T) { - Tuple() - } - private fun receiver_ref_mut(self: &mut S,y: T) { - select m::S.x<&mut S>(self) = y - } - private fun test_call_styles(s: S,x: u64) { - m::receiver(s, x); - m::receiver_ref(Borrow(Immutable)(s), x); - m::receiver_ref_mut(Borrow(Mutable)(s), x); - m::receiver_more_generics(s, 22); - m::receiver_needs_type_args(s, x); - Tuple() - } - private fun test_receiver_inference(s: S) { - m::inlined(closure m::test_receiver_inference$lambda$1(), s) - } - private fun test_receiver_inference$lambda$1(s: S): S { - m::id(s) - } -} // end 0x42::m - - -// -- Model dump after env processor specification rewriter: -module 0x42::m { - struct S { - x: T, - } - private fun id(self: S): S { - self - } - private fun inlined(f: |S|S,s: S) { - (f)(s); - Tuple() - } - private fun receiver(self: S,y: T) { - select m::S.x>(self) = y; - Tuple() - } - private fun receiver_more_generics(self: S,_y: R) { - Tuple() - } - private fun receiver_needs_type_args(self: S,_y: T) { - Abort(1) - } - private fun receiver_ref(self: &S,_y: T) { - Tuple() - } - private fun receiver_ref_mut(self: &mut S,y: T) { - select m::S.x<&mut S>(self) = y - } - private fun test_call_styles(s: S,x: u64) { - m::receiver(s, x); - m::receiver_ref(Borrow(Immutable)(s), x); - m::receiver_ref_mut(Borrow(Mutable)(s), x); - m::receiver_more_generics(s, 22); - m::receiver_needs_type_args(s, x); - Tuple() - } - private fun test_receiver_inference(s: S) { - m::inlined(closure m::test_receiver_inference$lambda$1(), s) - } - private fun test_receiver_inference$lambda$1(s: S): S { - m::id(s) - } -} // end 0x42::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/generic_calls.move:36:9 - │ -36 │ f(s); - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/generic_calls.move:47:17 │ 47 │ inlined(|s| s.id(), s) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generics.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generics.lambda.exp index 2a10fb8eecd8e..e1e6a42e3dc86 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generics.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/generics.lambda.exp @@ -327,8 +327,8 @@ module 0x42::Test { Diagnostics: -error: captured variable `sum` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/generics.move:16:30 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/generics.move:16:26 │ 16 │ foreach(&v, |e| sum = sum + *e); - │ ^^^ + │ ^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inline_fun_in_spec.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inline_fun_in_spec.lambda.exp index d4783a884aa54..10d5cf390bb96 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inline_fun_in_spec.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inline_fun_in_spec.lambda.exp @@ -483,163 +483,10 @@ module 0x42::m { } // end 0x42::m -// -- Model dump after env processor lambda-lifting: -module 0x42::m { - spec { - invariant forall a: address: TypeDomain
(): Implies(exists<0x42::m::S>(a), m::exec(|a: address| Lt(select m::S.f<0x42::m::S>({ - let (a: address): (address) = Tuple(a); - BorrowGlobal(Immutable)<0x42::m::S>(a) - }), 10), a)); - } - - struct S { - f: u64, - } - spec { - invariant m::exec(|x: num| Gt(x, 0), select m::S.f()); - } - - private fun exec(f: |T|R,x: T): R { - { - let r: R = (f)(x); - spec { - assert Eq<#1>(r, (f)($t1)); - } - ; - r - } - } - private fun function_code_spec_block(x: u64): u64 { - spec { - assert m::exec(closure m::function_code_spec_block$lambda$1(), $t0); - } - ; - Add(x, 1) - } - private fun function_spec_block(x: u64): u64 { - Add(x, 1) - } - spec { - ensures Eq(result0(), m::exec(|x: num| Add(x, 1), $t0)); - } - - private inline fun get(a: address): &R { - BorrowGlobal(Immutable)(a) - } - private fun function_code_spec_block$lambda$1(y: num): bool { - Gt(y, 0) - } -} // end 0x42::m - - -// -- Model dump after env processor specification checker: -module 0x42::m { - spec { - invariant forall a: address: TypeDomain
(): Implies(exists<0x42::m::S>(a), m::exec(|a: address| Lt(select m::S.f<0x42::m::S>({ - let (a: address): (address) = Tuple(a); - BorrowGlobal(Immutable)<0x42::m::S>(a) - }), 10), a)); - } - - struct S { - f: u64, - } - spec { - invariant m::exec(|x: num| Gt(x, 0), select m::S.f()); - } - - private fun exec(f: |T|R,x: T): R { - { - let r: R = (f)(x); - spec { - assert Eq<#1>(r, (f)($t1)); - } - ; - r - } - } - private fun function_code_spec_block(x: u64): u64 { - spec { - assert m::exec(closure m::function_code_spec_block$lambda$1(), $t0); - } - ; - Add(x, 1) - } - private fun function_spec_block(x: u64): u64 { - Add(x, 1) - } - spec { - ensures Eq(result0(), m::exec(|x: num| Add(x, 1), $t0)); - } - - private inline fun get(a: address): &R { - BorrowGlobal(Immutable)(a) - } - private fun function_code_spec_block$lambda$1(y: num): bool { - Gt(y, 0) - } -} // end 0x42::m - - -// -- Model dump after env processor specification rewriter: -module 0x42::m { - spec { - invariant forall a: address: TypeDomain
(): Implies(exists<0x42::m::S>(a), m::$exec(|a: address| Lt(select m::S.f<0x42::m::S>({ - let (a: address): (address) = Tuple(a); - global<0x42::m::S>(a) - }), 10), a)); - } - - struct S { - f: u64, - } - spec { - invariant m::$exec(|x: num| Gt(x, 0), select m::S.f()); - } - - private fun exec(f: |T|R,x: T): R { - { - let r: R = (f)(x); - spec { - assert Eq<#1>(r, (f)($t1)); - } - ; - r - } - } - private fun function_code_spec_block(x: u64): u64 { - spec { - assert m::$exec(closure m::function_code_spec_block$lambda$1(), $t0); - } - ; - Add(x, 1) - } - private fun function_spec_block(x: u64): u64 { - Add(x, 1) - } - spec { - ensures Eq(result0(), m::$exec(|x: num| Add(x, 1), $t0)); - } - - private inline fun get(a: address): &R { - BorrowGlobal(Immutable)(a) - } - private fun function_code_spec_block$lambda$1(y: num): bool { - Gt(y, 0) - } - spec fun $exec(f: |#0|#1,x: #0): #1 { - { - let r: #1 = (f)(x); - r - } - } -} // end 0x42::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/inline_fun_in_spec.move:4:17 - │ -4 │ let r = f(x); - │ ^ +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/inline_fun_in_spec.move:19:28 + │ +19 │ spec { assert exec(|y| y > 0, x); }; + │ ^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inlining1.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inlining1.lambda.exp index ccd5c61991485..c94277a84e19c 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inlining1.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/inlining1.lambda.exp @@ -207,90 +207,9 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |u64|u64,x: u64): u64 { - (f)(x) - } - public fun main() { - if Eq(Test::test(), 3) { - Tuple() - } else { - Abort(5) - }; - Tuple() - } - public fun test(): u64 { - Test::foo(closure Test::test$lambda$1(), 10) - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |u64|u64,x: u64): u64 { - (f)(x) - } - public fun main() { - if Eq(Test::test(), 3) { - Tuple() - } else { - Abort(5) - }; - Tuple() - } - public fun test(): u64 { - Test::foo(closure Test::test$lambda$1(), 10) - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |u64|u64,x: u64): u64 { - (f)(x) - } - public fun main() { - if Eq(Test::test(), 3) { - Tuple() - } else { - Abort(5) - }; - Tuple() - } - public fun test(): u64 { - Test::foo(closure Test::test$lambda$1(), 10) - } - private fun test$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 3 - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/inlining1.move:4:9 - │ -4 │ f(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/inlining1.move:8:13 │ 8 │ foo(|_| 3, 10) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda.lambda.exp index 0edf647447ceb..affdfc91b8e16 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda.lambda.exp @@ -745,8 +745,53 @@ module 0x42::LambdaTest { Diagnostics: -error: captured variable `product` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/lambda.move:30:18 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:30:14 │ 30 │ foreach(&v, |e| product = LambdaTest1::inline_mul(product, *e)); - │ ^^^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:34:29 + │ +34 │ LambdaTest1::inline_apply1(|z|z, g(LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x|x, 3)))) + 2 + │ ^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:34:90 + │ +34 │ LambdaTest1::inline_apply1(|z|z, g(LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x|x, 3)))) + 2 + │ ^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:40:29 + │ +40 │ LambdaTest1::inline_apply(|y|y, x) + │ ^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:39:59 + │ +39 │ LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x| { + │ ╭──────────────────────────────────────────────────────────────^ +40 │ │ LambdaTest1::inline_apply(|y|y, x) +41 │ │ }, + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:54:29 + │ +54 │ LambdaTest2::inline_apply2(|x| x + 1, 3) + + │ ^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:55:29 + │ +55 │ LambdaTest2::inline_apply2(|x| x * x, inline_apply(|y|y, 3)) + │ ^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda.move:55:53 + │ +55 │ LambdaTest2::inline_apply2(|x| x * x, inline_apply(|y|y, 3)) + │ ^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast.lambda.exp index cc4db35759051..277584ca7ef3f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast.lambda.exp @@ -434,8 +434,20 @@ module 0x12391283::M { Diagnostics: -error: captured variable `accu` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/lambda_cast.move:18:35 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda_cast.move:18:28 │ 18 │ vector_for_each(v, |elem| accu = f(accu, elem)); - │ ^^^^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda_cast.move:26:61 + │ +26 │ vector_fold(gas_schedule_blob, (0 as u64), |sum, addend| sum + (addend as u64)) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda_cast.move:33:52 + │ +33 │ vector_fold(gas_schedule_blob, (0 as u64), |sum, addend| sum + (addend as u64)) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.exp index d9cd9d072137b..95c37d67c6f26 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|(u64, integer)|u64` to a function which expects argument of type `|(u64, vector)|u64` +error: cannot pass `|(u64, integer)|u64 with copy+store` to a function which expects argument of type `|(u64, vector)|u64` ┌─ tests/lambda/inline-parity/lambda_cast_err.move:26:52 │ 26 │ vector_fold(gas_schedule_blob, (0 as u64), |sum, addend| sum + (addend as u64)) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.lambda.exp index d9cd9d072137b..95c37d67c6f26 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_cast_err.lambda.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|(u64, integer)|u64` to a function which expects argument of type `|(u64, vector)|u64` +error: cannot pass `|(u64, integer)|u64 with copy+store` to a function which expects argument of type `|(u64, vector)|u64` ┌─ tests/lambda/inline-parity/lambda_cast_err.move:26:52 │ 26 │ vector_fold(gas_schedule_blob, (0 as u64), |sum, addend| sum + (addend as u64)) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_no_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_no_param.lambda.exp index eb23c97b263b2..dd01bdee97745 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_no_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_no_param.lambda.exp @@ -207,102 +207,15 @@ module 0xdecafbad::m { } // end 0xdecafbad::m -// -- Model dump after env processor lambda-lifting: -module 0xdecafbad::m { - private fun bar(f: |()|u64): u64 { - (f)() - } - private fun foo(f: |()|) { - (f)(); - Tuple() - } - public fun one() { - m::foo(closure m::one$lambda$1()); - Tuple() - } - public fun two(x: u64): u64 { - m::bar(closure m::two$lambda$1(x)) - } - private fun one$lambda$1() { - Tuple() - } - private fun two$lambda$1(x: u64): u64 { - x - } -} // end 0xdecafbad::m - - -// -- Model dump after env processor specification checker: -module 0xdecafbad::m { - private fun bar(f: |()|u64): u64 { - (f)() - } - private fun foo(f: |()|) { - (f)(); - Tuple() - } - public fun one() { - m::foo(closure m::one$lambda$1()); - Tuple() - } - public fun two(x: u64): u64 { - m::bar(closure m::two$lambda$1(x)) - } - private fun one$lambda$1() { - Tuple() - } - private fun two$lambda$1(x: u64): u64 { - x - } -} // end 0xdecafbad::m - - -// -- Model dump after env processor specification rewriter: -module 0xdecafbad::m { - private fun bar(f: |()|u64): u64 { - (f)() - } - private fun foo(f: |()|) { - (f)(); - Tuple() - } - public fun one() { - m::foo(closure m::one$lambda$1()); - Tuple() - } - public fun two(x: u64): u64 { - m::bar(closure m::two$lambda$1(x)) - } - private fun one$lambda$1() { - Tuple() - } - private fun two$lambda$1(x: u64): u64 { - x - } -} // end 0xdecafbad::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/lambda_no_param.move:3:9 - │ -3 │ f(); - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_no_param.move:7:13 │ 7 │ foo(|| {}); │ ^^^^^ -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/lambda_no_param.move:11:9 - │ -11 │ f() - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_no_param.move:15:13 │ 15 │ bar(||x) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param.lambda.exp index b3587c0f077ef..5e54032b12b92 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param.lambda.exp @@ -603,234 +603,27 @@ module 0x42::LambdaParam { } // end 0x42::LambdaParam -// -- Model dump after env processor lambda-lifting: -module 0x42::LambdaParam { - public fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply(f, b) - } - public fun inline_apply3(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply4(f, b) - } - public fun inline_apply4(_f: |u64|u64,b: u64): u64 { - b - } - private fun test_lambda_symbol_param1() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param1$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param2() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param2$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply(closure LambdaParam::test_lambda_symbol_param2$lambda$2(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply3(closure LambdaParam::test_lambda_symbol_param2$lambda$3(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - } - } - private fun test_lambda_symbol_param1$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$2(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$3(x: u64): u64 { - x - } -} // end 0x42::LambdaParam - - -// -- Model dump after env processor specification checker: -module 0x42::LambdaParam { - public fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply(f, b) - } - public fun inline_apply3(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply4(f, b) - } - public fun inline_apply4(_f: |u64|u64,b: u64): u64 { - b - } - private fun test_lambda_symbol_param1() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param1$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param2() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param2$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply(closure LambdaParam::test_lambda_symbol_param2$lambda$2(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply3(closure LambdaParam::test_lambda_symbol_param2$lambda$3(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - } - } - private fun test_lambda_symbol_param1$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$2(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$3(x: u64): u64 { - x - } -} // end 0x42::LambdaParam - - -// -- Model dump after env processor specification rewriter: -module 0x42::LambdaParam { - public fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply(f, b) - } - public fun inline_apply3(f: |u64|u64,b: u64): u64 { - LambdaParam::inline_apply4(f, b) - } - public fun inline_apply4(_f: |u64|u64,b: u64): u64 { - b - } - private fun test_lambda_symbol_param1() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param1$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param2() { - { - let a: u64 = LambdaParam::inline_apply2(closure LambdaParam::test_lambda_symbol_param2$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply(closure LambdaParam::test_lambda_symbol_param2$lambda$2(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - { - let b: u64 = LambdaParam::inline_apply3(closure LambdaParam::test_lambda_symbol_param2$lambda$3(), 3); - if Eq(b, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - } - } - private fun test_lambda_symbol_param1$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$1(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$2(x: u64): u64 { - x - } - private fun test_lambda_symbol_param2$lambda$3(x: u64): u64 { - x - } -} // end 0x42::LambdaParam - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/lambda_param.move:3:2 - │ -3 │ f(b) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_param.move:19:24 │ 19 │ let a = inline_apply2(|x| x, 3); │ ^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_param.move:24:24 │ 24 │ let a = inline_apply2(|x| x, 3); │ ^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_param.move:26:23 │ 26 │ let b = inline_apply(|x| x, 3); │ ^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_param.move:28:24 │ 28 │ let b = inline_apply3(|x| x, 3); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.exp index 33468b26f118d..64614096d6592 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|u64|u64` to a function which expects argument of type `|u64|` +error: cannot pass `|u64|u64 with copy+store` to a function which expects argument of type `|u64|` ┌─ tests/lambda/inline-parity/lambda_param_mismatch.move:20:32 │ 20 │ vector_for_each(input, |item| { diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.lambda.exp index 33468b26f118d..64614096d6592 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_param_mismatch.lambda.exp @@ -1,6 +1,6 @@ Diagnostics: -error: cannot pass `|u64|u64` to a function which expects argument of type `|u64|` +error: cannot pass `|u64|u64 with copy+store` to a function which expects argument of type `|u64|` ┌─ tests/lambda/inline-parity/lambda_param_mismatch.move:20:32 │ 20 │ vector_for_each(input, |item| { diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_return.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_return.lambda.exp index 2b9ffb4ba4160..1ea24d42e88ac 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_return.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_return.lambda.exp @@ -207,81 +207,9 @@ module 0x42::LambdaReturn { } // end 0x42::LambdaReturn -// -- Model dump after env processor lambda-lifting: -module 0x42::LambdaReturn { - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - return (f)(b) - } - private fun test_lambda_symbol_param() { - { - let a: u64 = LambdaReturn::inline_apply2(closure LambdaReturn::test_lambda_symbol_param$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param$lambda$1(x: u64): u64 { - x - } -} // end 0x42::LambdaReturn - - -// -- Model dump after env processor specification checker: -module 0x42::LambdaReturn { - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - return (f)(b) - } - private fun test_lambda_symbol_param() { - { - let a: u64 = LambdaReturn::inline_apply2(closure LambdaReturn::test_lambda_symbol_param$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param$lambda$1(x: u64): u64 { - x - } -} // end 0x42::LambdaReturn - - -// -- Model dump after env processor specification rewriter: -module 0x42::LambdaReturn { - public fun inline_apply2(f: |u64|u64,b: u64): u64 { - return (f)(b) - } - private fun test_lambda_symbol_param() { - { - let a: u64 = LambdaReturn::inline_apply2(closure LambdaReturn::test_lambda_symbol_param$lambda$1(), 3); - if Eq(a, 3) { - Tuple() - } else { - Abort(0) - }; - Tuple() - } - } - private fun test_lambda_symbol_param$lambda$1(x: u64): u64 { - x - } -} // end 0x42::LambdaReturn - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/lambda_return.move:3:9 - │ -3 │ return f(b) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_return.move:7:24 │ 7 │ let a = inline_apply2(|x| { x }, 3); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_typed.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_typed.lambda.exp index 396fdaf35ada9..ffe457423462b 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_typed.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/lambda_typed.lambda.exp @@ -1285,325 +1285,19 @@ module 0x42::LambdaTest { } // end 0x42::LambdaTest -// -- Model dump after env processor lambda-lifting: -module 0x42::LambdaTest1 { - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply1(f: |u64|u64,b: u64): u64 { - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add((f)(b), 1), 12); - Mul(a, 12) - } - } - public inline fun inline_mul(a: u64,b: u64): u64 { - Mul(a, b) - } -} // end 0x42::LambdaTest1 -module 0x42::LambdaTest2 { - use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1 - use std::vector; - public inline fun foreach(v: &vector,action: |&T|) { - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - (action)(vector::borrow(v, i)); - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - } - public inline fun inline_apply2(g: |u64|u64,c: u64): u64 { - Add({ - let (b: u64): (u64) = Tuple((g)({ - let (a: u64, b: u64): (u64, u64) = Tuple(c, 3); - Mul(a, 3) - })); - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add({ - let (z: u64): (u64) = Tuple(b); - z - }, 1), 12); - Mul(a, 12) - } - }, 2) - } - public inline fun inline_apply3(g: |u64|u64,c: u64): u64 { - Add(LambdaTest1::inline_apply1(g, LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$2(), 3))), 4) - } - public fun test_inline_lambda() { - { - let product: u64 = 1; - { - let (v: &vector): (&vector) = Tuple(Borrow(Immutable)([Number(1), Number(2), Number(3)])); - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - { - let (e: &u64): (&u64) = Tuple(vector::borrow(v, i)); - product: u64 = { - let (a: u64, b: u64): (u64, u64) = Tuple(product, Deref(e)); - Mul(a, b) - } - }; - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - }; - Tuple() - } - } - private fun inline_apply3$lambda$1(y: u64): u64 { - y - } - private fun inline_apply3$lambda$2(x: u64): u64 { - LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$1(), x) - } -} // end 0x42::LambdaTest2 -module 0x42::LambdaTest { - use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2 - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply_test(): u64 { - 1120 - } - private fun test_lambda() { - if false { - Tuple() - } else { - Abort(0) - }; - Tuple() - } -} // end 0x42::LambdaTest - - -// -- Model dump after env processor specification checker: -module 0x42::LambdaTest1 { - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply1(f: |u64|u64,b: u64): u64 { - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add((f)(b), 1), 12); - Mul(a, 12) - } - } - public inline fun inline_mul(a: u64,b: u64): u64 { - Mul(a, b) - } -} // end 0x42::LambdaTest1 -module 0x42::LambdaTest2 { - use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1 - use std::vector; - public inline fun foreach(v: &vector,action: |&T|) { - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - (action)(vector::borrow(v, i)); - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - } - public inline fun inline_apply2(g: |u64|u64,c: u64): u64 { - Add({ - let (b: u64): (u64) = Tuple((g)({ - let (a: u64, b: u64): (u64, u64) = Tuple(c, 3); - Mul(a, 3) - })); - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add({ - let (z: u64): (u64) = Tuple(b); - z - }, 1), 12); - Mul(a, 12) - } - }, 2) - } - public inline fun inline_apply3(g: |u64|u64,c: u64): u64 { - Add(LambdaTest1::inline_apply1(g, LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$2(), 3))), 4) - } - public fun test_inline_lambda() { - { - let product: u64 = 1; - { - let (v: &vector): (&vector) = Tuple(Borrow(Immutable)([Number(1), Number(2), Number(3)])); - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - { - let (e: &u64): (&u64) = Tuple(vector::borrow(v, i)); - product: u64 = { - let (a: u64, b: u64): (u64, u64) = Tuple(product, Deref(e)); - Mul(a, b) - } - }; - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - }; - Tuple() - } - } - private fun inline_apply3$lambda$1(y: u64): u64 { - y - } - private fun inline_apply3$lambda$2(x: u64): u64 { - LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$1(), x) - } -} // end 0x42::LambdaTest2 -module 0x42::LambdaTest { - use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2 - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply_test(): u64 { - 1120 - } - private fun test_lambda() { - if false { - Tuple() - } else { - Abort(0) - }; - Tuple() - } -} // end 0x42::LambdaTest - - -// -- Model dump after env processor specification rewriter: -module 0x42::LambdaTest1 { - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply1(f: |u64|u64,b: u64): u64 { - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add((f)(b), 1), 12); - Mul(a, 12) - } - } - public inline fun inline_mul(a: u64,b: u64): u64 { - Mul(a, b) - } -} // end 0x42::LambdaTest1 -module 0x42::LambdaTest2 { - use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1 - use std::vector; - public inline fun foreach(v: &vector,action: |&T|) { - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - (action)(vector::borrow(v, i)); - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - } - public inline fun inline_apply2(g: |u64|u64,c: u64): u64 { - Add({ - let (b: u64): (u64) = Tuple((g)({ - let (a: u64, b: u64): (u64, u64) = Tuple(c, 3); - Mul(a, 3) - })); - { - let (a: u64, b: u64): (u64, u64) = Tuple(Add({ - let (z: u64): (u64) = Tuple(b); - z - }, 1), 12); - Mul(a, 12) - } - }, 2) - } - public inline fun inline_apply3(g: |u64|u64,c: u64): u64 { - Add(LambdaTest1::inline_apply1(g, LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$2(), 3))), 4) - } - public fun test_inline_lambda() { - { - let product: u64 = 1; - { - let (v: &vector): (&vector) = Tuple(Borrow(Immutable)([Number(1), Number(2), Number(3)])); - { - let i: u64 = 0; - loop { - if Lt(i, vector::length(v)) { - { - let (e: &u64): (&u64) = Tuple(vector::borrow(v, i)); - product: u64 = { - let (a: u64, b: u64): (u64, u64) = Tuple(product, Deref(e)); - Mul(a, b) - } - }; - i: u64 = Add(i, 1); - Tuple() - } else { - break - } - } - } - }; - Tuple() - } - } - private fun inline_apply3$lambda$1(y: u64): u64 { - y - } - private fun inline_apply3$lambda$2(x: u64): u64 { - LambdaTest1::inline_apply(closure LambdaTest2::inline_apply3$lambda$1(), x) - } -} // end 0x42::LambdaTest2 -module 0x42::LambdaTest { - use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2 - public inline fun inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - public inline fun inline_apply_test(): u64 { - 1120 - } - private fun test_lambda() { - if false { - Tuple() - } else { - Abort(0) - }; - Tuple() - } -} // end 0x42::LambdaTest - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/lambda_typed.move:11:2 - │ -11 │ f(b) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/lambda_typed.move:40:29 │ 40 │ LambdaTest1::inline_apply(|y: u64|y, x) │ ^^^^^^^^^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/lambda_typed.move:39:59 + │ +39 │ LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x:u64| { + │ ╭──────────────────────────────────────────────────────────────^ +40 │ │ LambdaTest1::inline_apply(|y: u64|y, x) +41 │ │ }, + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/masking.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/masking.lambda.exp index a89c6271195d1..4f3bf689cb56b 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/masking.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/masking.lambda.exp @@ -119,96 +119,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun main(): u64 { - Test::foo(closure Test::main$lambda$1(), closure Test::main$lambda$2(), 10, 100) - } - private fun main$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun main$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun main(): u64 { - Test::foo(closure Test::main$lambda$1(), closure Test::main$lambda$2(), 10, 100) - } - private fun main$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun main$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun foo(f: |(u64, u64)|u64,g: |(u64, u64)|u64,x: u64,_y: u64): u64 { - Add((f)(x, _y), (g)(x, _y)) - } - public fun main(): u64 { - Test::foo(closure Test::main$lambda$1(), closure Test::main$lambda$2(), 10, 100) - } - private fun main$lambda$1(x: u64,param$1: u64): u64 { - { - let _: u64 = param$1; - x - } - } - private fun main$lambda$2(param$0: u64,y: u64): u64 { - { - let _: u64 = param$0; - y - } - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/masking.move:4:9 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/masking.move:4:20 - │ -4 │ f(x, _y) + g(x, _y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/masking.move:8:13 │ 8 │ foo(|x, _| x, |_, y| y, 10, 100) │ ^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/masking.move:8:23 │ 8 │ foo(|x, _| x, |_, y| y, 10, 100) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/multi_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/multi_param.lambda.exp index 79df5cae6a545..855a868e5dcb4 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/multi_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/multi_param.lambda.exp @@ -451,8 +451,18 @@ module 0x42::Test { Diagnostics: -error: captured variable `result` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/multi_param.move:21:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/multi_param.move:19:29 │ -21 │ result = result + f(&elem.k, &mut elem.v); - │ ^^^^^^ +19 │ for_each_ref_mut(v, |elem| { + │ ╭─────────────────────────────^ +20 │ │ let elem: &mut Elem = elem; // Checks whether scoping is fine +21 │ │ result = result + f(&elem.k, &mut elem.v); +22 │ │ }); + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/multi_param.move:27:64 + │ +27 │ assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x,y| *x + *y) == 3, 0) + │ ^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda.lambda.exp index 019feaaebebc4..7793f33a9f484 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda.lambda.exp @@ -119,72 +119,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun test(): u64 { - Test::apply(closure Test::test$lambda$1(), 1, Test::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun test(): u64 { - Test::apply(closure Test::test$lambda$1(), 1, Test::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun test(): u64 { - Test::apply(closure Test::test$lambda$1(), 1, Test::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/nested_lambda.move:5:9 - │ -5 │ f(x, y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/nested_lambda.move:9:15 │ 9 │ apply(|x, y| x + y, 1, apply(|x, y| x * y, 2, 1)) │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/nested_lambda.move:9:38 │ 9 │ apply(|x, y| x + y, 1, apply(|x, y| x * y, 2, 1)) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda_module.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda_module.lambda.exp index f5ed4cea4f283..7b08cadad410f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda_module.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/nested_lambda_module.lambda.exp @@ -152,81 +152,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test1 { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } -} // end 0x42::Test1 -module 0x42::Test { - use 0x42::Test1; // resolved as: 0x42::Test1 - public fun test(): u64 { - Test1::apply(closure Test::test$lambda$1(), 1, Test1::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test1 { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } -} // end 0x42::Test1 -module 0x42::Test { - use 0x42::Test1; // resolved as: 0x42::Test1 - public fun test(): u64 { - Test1::apply(closure Test::test$lambda$1(), 1, Test1::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test1 { - public fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } -} // end 0x42::Test1 -module 0x42::Test { - use 0x42::Test1; // resolved as: 0x42::Test1 - public fun test(): u64 { - Test1::apply(closure Test::test$lambda$1(), 1, Test1::apply(closure Test::test$lambda$2(), 2, 1)) - } - private fun test$lambda$1(x: u64,y: u64): u64 { - Add(x, y) - } - private fun test$lambda$2(x: u64,y: u64): u64 { - Mul(x, y) - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/nested_lambda_module.move:4:9 - │ -4 │ f(x, y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/nested_lambda_module.move:13:22 │ 13 │ Test1::apply(|x, y| x + y, 1, Test1::apply(|x, y| x * y, 2, 1)) │ ^^^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/nested_lambda_module.move:13:52 │ 13 │ Test1::apply(|x, y| x + y, 1, Test1::apply(|x, y| x * y, 2, 1)) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp index 1095994a02a62..2f733050cb6bd 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/non_lambda_arg.lambda.exp @@ -404,13 +404,3 @@ error: local `a_less_b` of type `|(T, T)|bool` does not have the `copy` ability │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ copy needed here because value is still in use 13 │ incorrect_sort_recursive(arr, pi + 1, high, a_less_b); │ ----------------------------------------------------- used here - -error: local `a_less_b` of type `|(T, T)|bool` does not have the `drop` ability - ┌─ tests/lambda/inline-parity/non_lambda_arg.move:10:9 - │ -10 │ ╭ if (low < high) { -11 │ │ let pi = low + high / 2; -12 │ │ incorrect_sort_recursive(arr, low, pi - 1, a_less_b); -13 │ │ incorrect_sort_recursive(arr, pi + 1, high, a_less_b); -14 │ │ }; - │ ╰─────────^ implicitly dropped here since it is no longer used diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/op_with_side_effect_49.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/op_with_side_effect_49.lambda.exp index a9a1dc063d69f..21ea4435d9a91 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/op_with_side_effect_49.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/op_with_side_effect_49.lambda.exp @@ -176,14 +176,14 @@ module 0xc0ffee::m { Diagnostics: -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/op_with_side_effect_49.move:9:22 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/op_with_side_effect_49.move:9:18 │ 9 │ x + call(|| {x = x + 1; x}) + call(|| {x = x + 7; x}) - │ ^ + │ ^^^^^^^^^^^^^^^^^ -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/op_with_side_effect_49.move:9:48 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/op_with_side_effect_49.move:9:44 │ 9 │ x + call(|| {x = x + 1; x}) + call(|| {x = x + 7; x}) - │ ^ + │ ^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/options.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/options.lambda.exp index 01a7a59635ddc..a0a20d5e7701d 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/options.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/options.lambda.exp @@ -284,102 +284,9 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::map_opt { - use std::option; - public fun map(t: 0x1::option::Option,f: |Element|OtherElement): 0x1::option::Option { - if option::is_some(Borrow(Immutable)(t)) { - option::some((f)(option::extract(Borrow(Mutable)(t)))) - } else { - option::none() - } - } -} // end 0x42::map_opt -module 0x42::Test { - use std::option; - use 0x42::map_opt; // resolved as: 0x42::map_opt - public fun test(): u64 { - { - let t: 0x1::option::Option = option::some(1); - { - let x: 0x1::option::Option = map_opt::map(t, closure Test::test$lambda$1()); - option::extract(Borrow(Mutable)(x)) - } - } - } - private fun test$lambda$1(e: u64): u64 { - Add(e, 1) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::map_opt { - use std::option; - public fun map(t: 0x1::option::Option,f: |Element|OtherElement): 0x1::option::Option { - if option::is_some(Borrow(Immutable)(t)) { - option::some((f)(option::extract(Borrow(Mutable)(t)))) - } else { - option::none() - } - } -} // end 0x42::map_opt -module 0x42::Test { - use std::option; - use 0x42::map_opt; // resolved as: 0x42::map_opt - public fun test(): u64 { - { - let t: 0x1::option::Option = option::some(1); - { - let x: 0x1::option::Option = map_opt::map(t, closure Test::test$lambda$1()); - option::extract(Borrow(Mutable)(x)) - } - } - } - private fun test$lambda$1(e: u64): u64 { - Add(e, 1) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::map_opt { - use std::option; - public fun map(t: 0x1::option::Option,f: |Element|OtherElement): 0x1::option::Option { - if option::is_some(Borrow(Immutable)(t)) { - option::some((f)(option::extract(Borrow(Mutable)(t)))) - } else { - option::none() - } - } -} // end 0x42::map_opt -module 0x42::Test { - use std::option; - use 0x42::map_opt; // resolved as: 0x42::map_opt - public fun test(): u64 { - { - let t: 0x1::option::Option = option::some(1); - { - let x: 0x1::option::Option = map_opt::map(t, closure Test::test$lambda$1()); - option::extract(Borrow(Mutable)(x)) - } - } - } - private fun test$lambda$1(e: u64): u64 { - Add(e, 1) - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/options.move:7:26 - │ -7 │ option::some(f(option::extract(&mut t))) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/options.move:22:33 │ 22 │ let x = map_opt::map(t, |e| e + 1); diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/return_in_lambda.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/return_in_lambda.lambda.exp index bf94c6a9de653..15cec56dd1a58 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/return_in_lambda.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/return_in_lambda.lambda.exp @@ -152,66 +152,9 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun adder(x: u64,y: u64): u64 { - Add(x, y) - } - private fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun main(): u64 { - Test::apply(closure Test::main$lambda$1(), 10, 100) - } - private fun main$lambda$1(x: u64,y: u64): u64 { - return Test::adder(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun adder(x: u64,y: u64): u64 { - Add(x, y) - } - private fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun main(): u64 { - Test::apply(closure Test::main$lambda$1(), 10, 100) - } - private fun main$lambda$1(x: u64,y: u64): u64 { - return Test::adder(x, y) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun adder(x: u64,y: u64): u64 { - Add(x, y) - } - private fun apply(f: |(u64, u64)|u64,x: u64,y: u64): u64 { - (f)(x, y) - } - public fun main(): u64 { - Test::apply(closure Test::main$lambda$1(), 10, 100) - } - private fun main$lambda$1(x: u64,y: u64): u64 { - return Test::adder(x, y) - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/return_in_lambda.move:4:9 - │ -4 │ f(x, y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/return_in_lambda.move:12:15 │ 12 │ apply(|x, y| { diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/same_names.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/same_names.lambda.exp index c473f81866042..5037745a0d988 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/same_names.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/same_names.lambda.exp @@ -361,123 +361,9 @@ module 0x42::c { } // end 0x42::c -// -- Model dump after env processor lambda-lifting: -module 0x42::b { - struct MyOtherList { - len: u64, - } - public fun len(self: &MyOtherList): u64 { - select b::MyOtherList.len<&MyOtherList>(self) - } -} // end 0x42::b -module 0x42::a { - struct MyList { - len: u64, - } - public fun len(self: &MyList): u64 { - select a::MyList.len<&MyList>(self) - } -} // end 0x42::a -module 0x42::c { - use 0x42::a; // resolved as: 0x42::a - use 0x42::b; // resolved as: 0x42::b - private fun foo(f: |(a::MyList, b::MyOtherList)|,x: a::MyList,y: b::MyOtherList) { - (f)(x, y) - } - private fun test(x: a::MyList,y: b::MyOtherList) { - c::foo(closure c::test$lambda$1(), x, y) - } - private fun test$lambda$1(x: a::MyList,y: b::MyOtherList) { - if Eq(Add(a::len(Borrow(Immutable)(x)), b::len(Borrow(Immutable)(y))), 1) { - Tuple() - } else { - Abort(1) - } - } -} // end 0x42::c - - -// -- Model dump after env processor specification checker: -module 0x42::b { - struct MyOtherList { - len: u64, - } - public fun len(self: &MyOtherList): u64 { - select b::MyOtherList.len<&MyOtherList>(self) - } -} // end 0x42::b -module 0x42::a { - struct MyList { - len: u64, - } - public fun len(self: &MyList): u64 { - select a::MyList.len<&MyList>(self) - } -} // end 0x42::a -module 0x42::c { - use 0x42::a; // resolved as: 0x42::a - use 0x42::b; // resolved as: 0x42::b - private fun foo(f: |(a::MyList, b::MyOtherList)|,x: a::MyList,y: b::MyOtherList) { - (f)(x, y) - } - private fun test(x: a::MyList,y: b::MyOtherList) { - c::foo(closure c::test$lambda$1(), x, y) - } - private fun test$lambda$1(x: a::MyList,y: b::MyOtherList) { - if Eq(Add(a::len(Borrow(Immutable)(x)), b::len(Borrow(Immutable)(y))), 1) { - Tuple() - } else { - Abort(1) - } - } -} // end 0x42::c - - -// -- Model dump after env processor specification rewriter: -module 0x42::b { - struct MyOtherList { - len: u64, - } - public fun len(self: &MyOtherList): u64 { - select b::MyOtherList.len<&MyOtherList>(self) - } -} // end 0x42::b -module 0x42::a { - struct MyList { - len: u64, - } - public fun len(self: &MyList): u64 { - select a::MyList.len<&MyList>(self) - } -} // end 0x42::a -module 0x42::c { - use 0x42::a; // resolved as: 0x42::a - use 0x42::b; // resolved as: 0x42::b - private fun foo(f: |(a::MyList, b::MyOtherList)|,x: a::MyList,y: b::MyOtherList) { - (f)(x, y) - } - private fun test(x: a::MyList,y: b::MyOtherList) { - c::foo(closure c::test$lambda$1(), x, y) - } - private fun test$lambda$1(x: a::MyList,y: b::MyOtherList) { - if Eq(Add(a::len(Borrow(Immutable)(x)), b::len(Borrow(Immutable)(y))), 1) { - Tuple() - } else { - Abort(1) - } - } -} // end 0x42::c - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/same_names.move:24:9 - │ -24 │ f(x, y) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/same_names.move:30:13 │ 30 │ foo(|x, y| { assert!(x.len() + y.len() == 1, 1) }, x, y) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing.lambda.exp index 813306a5f3a94..6220c5ae1c85e 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing.lambda.exp @@ -250,8 +250,12 @@ module 0x42::Test { Diagnostics: -error: captured variable `_x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing.move:12:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing.move:11:13 │ -12 │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^^ +11 │ foo(|y| { + │ ╭─────────────^ +12 │ │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +13 │ │ // have the value 1. +14 │ │ }); + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed.lambda.exp index 57fbdb400d002..80dc09bd1544b 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed.lambda.exp @@ -250,8 +250,12 @@ module 0x42::Test { Diagnostics: -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_renamed.move:12:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_renamed.move:11:13 │ -12 │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^ +11 │ foo(|y| { + │ ╭─────────────^ +12 │ │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +13 │ │ // have the value 1. +14 │ │ }); + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed_param.lambda.exp index bf8fa10008821..3b95647c560af 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_renamed_param.lambda.exp @@ -561,26 +561,42 @@ module 0x42::Test { Diagnostics: -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:15:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:14:13 │ -15 │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^ +14 │ foo(|y| { + │ ╭─────────────^ +15 │ │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +16 │ │ // have the value 1. +17 │ │ }, 3); + │ ╰─────────^ -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:21:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:20:14 │ -21 │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^ +20 │ foo2(|y| { + │ ╭──────────────^ +21 │ │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +22 │ │ // have the value 1. +23 │ │ }, 5); + │ ╰─────────^ -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:30:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:29:13 │ -30 │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^ +29 │ foo(|y| { + │ ╭─────────────^ +30 │ │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +31 │ │ // have the value 1. +32 │ │ }, 3); + │ ╰─────────^ -error: captured variable `x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:36:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_renamed_param.move:35:14 │ -36 │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^ +35 │ foo2(|y| { + │ ╭──────────────^ +36 │ │ x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +37 │ │ // have the value 1. +38 │ │ }, 5); + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused.lambda.exp index 7c4b85b3b4291..227fec78406e9 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused.lambda.exp @@ -505,14 +505,28 @@ module 0x42::Test { Diagnostics: -error: captured variable `_x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_unused.move:18:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused.move:11:14 │ -18 │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^^ +11 │ quux(|a, b| f(a, b), z); + │ ^^^^^^^^^^^^^^ -error: captured variable `_x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_unused.move:28:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused.move:17:13 │ -28 │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^^ +17 │ foo(|y, _q| { + │ ╭─────────────^ +18 │ │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +19 │ │ // have the value 1. +20 │ │ }, z); + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused.move:27:14 + │ +27 │ quux(|y, _q| { + │ ╭──────────────^ +28 │ │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +29 │ │ // have the value 1. +30 │ │ }, z); + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused_nodecl.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused_nodecl.lambda.exp index ccbae64fbd2f7..e2abb7639d5de 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused_nodecl.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/shadowing_unused_nodecl.lambda.exp @@ -511,14 +511,28 @@ warning: Unused parameter `z`. Consider removing or prefixing with an underscore 6 │ public fun quux(f:|u64, u64|, z: u64) { │ ^ -error: captured variable `_x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_unused_nodecl.move:20:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused_nodecl.move:13:14 │ -20 │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^^ +13 │ quux(|a, b| f(a, b), z); + │ ^^^^^^^^^^^^^^ -error: captured variable `_x` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/shadowing_unused_nodecl.move:30:13 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused_nodecl.move:19:13 │ -30 │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would - │ ^^ +19 │ foo(|y, _q| { + │ ╭─────────────^ +20 │ │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +21 │ │ // have the value 1. +22 │ │ }, z); + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/shadowing_unused_nodecl.move:29:14 + │ +29 │ quux(|y, _q| { + │ ╭──────────────^ +30 │ │ _x = y // We expect this to assign 3 via foo if renaming works correctly. If not it would +31 │ │ // have the value 1. +32 │ │ }, z); + │ ╰─────────^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/simple_map_keys.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/simple_map_keys.lambda.exp index 90288bcbca57e..3085fc6816985 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/simple_map_keys.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/simple_map_keys.lambda.exp @@ -682,8 +682,18 @@ module 0x42::simple_map { Diagnostics: -error: captured variable `result` cannot be modified inside of a lambda - ┌─ tests/lambda/inline-parity/simple_map_keys.move:28:55 +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/simple_map_keys.move:17:28 + │ +17 │ map_ref(&map.data, |e| { + │ ╭────────────────────────────^ +18 │ │ let e: &Element = e; +19 │ │ e.key +20 │ │ }) + │ ╰─────────^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/inline-parity/simple_map_keys.move:28:25 │ 28 │ for_each_ref(v, |elem| vector::push_back(&mut result, f(elem))); - │ ^^^^^^ + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/spec_inlining.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/spec_inlining.lambda.exp index 82da96e292c71..53b72c72daafa 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/spec_inlining.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/spec_inlining.lambda.exp @@ -427,156 +427,15 @@ module 0x42::Test { } // end 0x42::Test -// -- Model dump after env processor lambda-lifting: -module 0x42::Test { - private fun apply(v: u64,predicate: |u64|bool): bool { - spec { - assert Ge($t0, 0); - } - ; - (predicate)(v) - } - public fun test_apply(x: u64) { - { - let r1: bool = Test::apply(x, closure Test::test_apply$lambda$1()); - spec { - assert r1; - } - ; - if r1 { - Tuple() - } else { - Abort(1) - }; - { - let r2: bool = Test::apply(x, closure Test::test_apply$lambda$2()); - spec { - assert r2; - } - ; - if r2 { - Tuple() - } else { - Abort(2) - }; - Tuple() - } - } - } - private fun test_apply$lambda$1(v: u64): bool { - Ge(v, 0) - } - private fun test_apply$lambda$2(v: u64): bool { - Neq(v, 0) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification checker: -module 0x42::Test { - private fun apply(v: u64,predicate: |u64|bool): bool { - spec { - assert Ge($t0, 0); - } - ; - (predicate)(v) - } - public fun test_apply(x: u64) { - { - let r1: bool = Test::apply(x, closure Test::test_apply$lambda$1()); - spec { - assert r1; - } - ; - if r1 { - Tuple() - } else { - Abort(1) - }; - { - let r2: bool = Test::apply(x, closure Test::test_apply$lambda$2()); - spec { - assert r2; - } - ; - if r2 { - Tuple() - } else { - Abort(2) - }; - Tuple() - } - } - } - private fun test_apply$lambda$1(v: u64): bool { - Ge(v, 0) - } - private fun test_apply$lambda$2(v: u64): bool { - Neq(v, 0) - } -} // end 0x42::Test - - -// -- Model dump after env processor specification rewriter: -module 0x42::Test { - private fun apply(v: u64,predicate: |u64|bool): bool { - spec { - assert Ge($t0, 0); - } - ; - (predicate)(v) - } - public fun test_apply(x: u64) { - { - let r1: bool = Test::apply(x, closure Test::test_apply$lambda$1()); - spec { - assert r1; - } - ; - if r1 { - Tuple() - } else { - Abort(1) - }; - { - let r2: bool = Test::apply(x, closure Test::test_apply$lambda$2()); - spec { - assert r2; - } - ; - if r2 { - Tuple() - } else { - Abort(2) - }; - Tuple() - } - } - } - private fun test_apply$lambda$1(v: u64): bool { - Ge(v, 0) - } - private fun test_apply$lambda$2(v: u64): bool { - Neq(v, 0) - } -} // end 0x42::Test - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/spec_inlining.move:6:9 - │ -6 │ predicate(v) - │ ^^^^^^^^^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/spec_inlining.move:10:27 │ 10 │ let r1 = apply(x, |v| v >= 0); │ ^^^^^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/spec_inlining.move:16:27 │ 16 │ let r2 = apply(x, |v| v != 0); 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 51316f7cd9c17..13fdcad48d3be 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 @@ -536,10 +536,10 @@ error: Calls to function values other than inline function parameters not yet su ┌─ 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 ┌─ 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/inline-parity/unnecessary_numerical_extreme_comparisons_warn.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unnecessary_numerical_extreme_comparisons_warn.lambda.exp index 2506246844937..57b8fafd070d9 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unnecessary_numerical_extreme_comparisons_warn.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unnecessary_numerical_extreme_comparisons_warn.lambda.exp @@ -1395,405 +1395,9 @@ module 0xc0ffee::no_warn { } // end 0xc0ffee::no_warn -// -- Model dump after env processor lambda-lifting: -module 0xc0ffee::m { - private fun apply(f: |u8|bool,x: u8): bool { - (f)(x) - } - private fun bar() { - Tuple() - } - private fun foo(x: T): T { - x - } - public fun test1(x: u8) { - if Gt(Add(x, 1), 255) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test2(x: &u8,y: &u8) { - if Eq(Gt(Add(Deref(x), Deref(y)), 255), true) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test3(x: u8) { - if Or(Lt(x, 0), Gt(0, x)) { - m::bar() - } else { - Tuple() - }; - if Le(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Ge(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Gt(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Lt(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Ge(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Le(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test4(a: u8,b: u16,c: u32,d: u64,e: u128,f: u256) { - if Or(Gt(a, 255), Gt(f, 255)) { - m::bar() - } else { - Tuple() - }; - if Ge(b, 65535) { - m::bar() - } else { - Tuple() - }; - if Lt(4294967295, c) { - m::bar() - } else { - Tuple() - }; - if Le(18446744073709551615, d) { - m::bar() - } else { - Tuple() - }; - if Lt(e, 340282366920938463463374607431768211455) { - m::bar() - } else { - Tuple() - }; - if Le(f, 115792089237316195423570985008687907853269984665640564039457584007913129639935) { - m::bar() - } else { - Tuple() - }; - if Ge(115792089237316195423570985008687907853269984665640564039457584007913129639935, f) { - m::bar() - } else { - Tuple() - }; - if Gt(340282366920938463463374607431768211455, e) { - m::bar() - } else { - Tuple() - }; - spec { - assert Le($t0, 255); - } - - } - public fun test5(x: u8): bool { - m::apply(closure m::test5$lambda$1(), x) - } - private fun test5$lambda$1(x: u8): bool { - Gt(x, 255) - } -} // end 0xc0ffee::m -module 0xc0ffee::no_warn { - public fun test(x: u8) { - if Lt(x, 0) { - Abort(1) - } else { - Tuple() - }; - Tuple() - } -} // end 0xc0ffee::no_warn - - -// -- Model dump after env processor specification checker: -module 0xc0ffee::m { - private fun apply(f: |u8|bool,x: u8): bool { - (f)(x) - } - private fun bar() { - Tuple() - } - private fun foo(x: T): T { - x - } - public fun test1(x: u8) { - if Gt(Add(x, 1), 255) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test2(x: &u8,y: &u8) { - if Eq(Gt(Add(Deref(x), Deref(y)), 255), true) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test3(x: u8) { - if Or(Lt(x, 0), Gt(0, x)) { - m::bar() - } else { - Tuple() - }; - if Le(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Ge(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Gt(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Lt(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Ge(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Le(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test4(a: u8,b: u16,c: u32,d: u64,e: u128,f: u256) { - if Or(Gt(a, 255), Gt(f, 255)) { - m::bar() - } else { - Tuple() - }; - if Ge(b, 65535) { - m::bar() - } else { - Tuple() - }; - if Lt(4294967295, c) { - m::bar() - } else { - Tuple() - }; - if Le(18446744073709551615, d) { - m::bar() - } else { - Tuple() - }; - if Lt(e, 340282366920938463463374607431768211455) { - m::bar() - } else { - Tuple() - }; - if Le(f, 115792089237316195423570985008687907853269984665640564039457584007913129639935) { - m::bar() - } else { - Tuple() - }; - if Ge(115792089237316195423570985008687907853269984665640564039457584007913129639935, f) { - m::bar() - } else { - Tuple() - }; - if Gt(340282366920938463463374607431768211455, e) { - m::bar() - } else { - Tuple() - }; - spec { - assert Le($t0, 255); - } - - } - public fun test5(x: u8): bool { - m::apply(closure m::test5$lambda$1(), x) - } - private fun test5$lambda$1(x: u8): bool { - Gt(x, 255) - } -} // end 0xc0ffee::m -module 0xc0ffee::no_warn { - public fun test(x: u8) { - if Lt(x, 0) { - Abort(1) - } else { - Tuple() - }; - Tuple() - } -} // end 0xc0ffee::no_warn - - -// -- Model dump after env processor specification rewriter: -module 0xc0ffee::m { - private fun apply(f: |u8|bool,x: u8): bool { - (f)(x) - } - private fun bar() { - Tuple() - } - private fun foo(x: T): T { - x - } - public fun test1(x: u8) { - if Gt(Add(x, 1), 255) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test2(x: &u8,y: &u8) { - if Eq(Gt(Add(Deref(x), Deref(y)), 255), true) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test3(x: u8) { - if Or(Lt(x, 0), Gt(0, x)) { - m::bar() - } else { - Tuple() - }; - if Le(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Ge(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Gt(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Lt(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - if Ge(m::foo(x), 0) { - m::bar() - } else { - Tuple() - }; - if Le(0, m::foo(x)) { - m::bar() - } else { - Tuple() - }; - Tuple() - } - public fun test4(a: u8,b: u16,c: u32,d: u64,e: u128,f: u256) { - if Or(Gt(a, 255), Gt(f, 255)) { - m::bar() - } else { - Tuple() - }; - if Ge(b, 65535) { - m::bar() - } else { - Tuple() - }; - if Lt(4294967295, c) { - m::bar() - } else { - Tuple() - }; - if Le(18446744073709551615, d) { - m::bar() - } else { - Tuple() - }; - if Lt(e, 340282366920938463463374607431768211455) { - m::bar() - } else { - Tuple() - }; - if Le(f, 115792089237316195423570985008687907853269984665640564039457584007913129639935) { - m::bar() - } else { - Tuple() - }; - if Ge(115792089237316195423570985008687907853269984665640564039457584007913129639935, f) { - m::bar() - } else { - Tuple() - }; - if Gt(340282366920938463463374607431768211455, e) { - m::bar() - } else { - Tuple() - }; - spec { - assert Le($t0, 255); - } - - } - public fun test5(x: u8): bool { - m::apply(closure m::test5$lambda$1(), x) - } - private fun test5$lambda$1(x: u8): bool { - Gt(x, 255) - } -} // end 0xc0ffee::m -module 0xc0ffee::no_warn { - public fun test(x: u8) { - if Lt(x, 0) { - Abort(1) - } else { - Tuple() - }; - Tuple() - } -} // end 0xc0ffee::no_warn - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/unnecessary_numerical_extreme_comparisons_warn.move:50:9 - │ -50 │ f(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unnecessary_numerical_extreme_comparisons_warn.move:54:15 │ 54 │ apply(|x| x > U8_MAX, x) diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unpack_generic_struct.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unpack_generic_struct.lambda.exp index 2bdecc21d6698..ccb4d76ab98ae 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unpack_generic_struct.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unpack_generic_struct.lambda.exp @@ -504,177 +504,9 @@ module 0x42::m { } // end 0x42::m -// -- Model dump after env processor lambda-lifting: -module 0x42::m { - use std::vector; - struct E { - key: Key, - } - struct Option { - vec: vector, - } - public fun destroy_none(t: Option) { - if m::is_none(Borrow(Immutable)(t)) { - Tuple() - } else { - Abort(262144) - }; - { - let m::Option{ vec } = t; - vector::destroy_empty(vec) - } - } - public fun foo(data: E,v: &mut Key) { - { - let f: E = m::h(data, closure m::foo$lambda$1()); - m::g(f, closure m::foo$lambda$2(v)); - Tuple() - } - } - public fun g(x: E,v: |E|) { - (v)(x) - } - public fun h(x: E,v: |Key|E): E { - { - let m::E{ key } = x; - (v)(key) - } - } - public fun is_none(t: &Option): bool { - vector::is_empty(Borrow(Immutable)(select m::Option.vec<&Option>(t))) - } - private fun foo$lambda$1(e: Key): E { - pack m::E(e) - } - private fun foo$lambda$2(v: &mut Key,e: E) { - { - let (m::E{ key }, _x: u64): (E, u64) = Tuple(e, 3); - v = key; - Tuple() - } - } -} // end 0x42::m - - -// -- Model dump after env processor specification checker: -module 0x42::m { - use std::vector; - struct E { - key: Key, - } - struct Option { - vec: vector, - } - public fun destroy_none(t: Option) { - if m::is_none(Borrow(Immutable)(t)) { - Tuple() - } else { - Abort(262144) - }; - { - let m::Option{ vec } = t; - vector::destroy_empty(vec) - } - } - public fun foo(data: E,v: &mut Key) { - { - let f: E = m::h(data, closure m::foo$lambda$1()); - m::g(f, closure m::foo$lambda$2(v)); - Tuple() - } - } - public fun g(x: E,v: |E|) { - (v)(x) - } - public fun h(x: E,v: |Key|E): E { - { - let m::E{ key } = x; - (v)(key) - } - } - public fun is_none(t: &Option): bool { - vector::is_empty(Borrow(Immutable)(select m::Option.vec<&Option>(t))) - } - private fun foo$lambda$1(e: Key): E { - pack m::E(e) - } - private fun foo$lambda$2(v: &mut Key,e: E) { - { - let (m::E{ key }, _x: u64): (E, u64) = Tuple(e, 3); - v = key; - Tuple() - } - } -} // end 0x42::m - - -// -- Model dump after env processor specification rewriter: -module 0x42::m { - use std::vector; - struct E { - key: Key, - } - struct Option { - vec: vector, - } - public fun destroy_none(t: Option) { - if m::is_none(Borrow(Immutable)(t)) { - Tuple() - } else { - Abort(262144) - }; - { - let m::Option{ vec } = t; - vector::destroy_empty(vec) - } - } - public fun foo(data: E,v: &mut Key) { - { - let f: E = m::h(data, closure m::foo$lambda$1()); - m::g(f, closure m::foo$lambda$2(v)); - Tuple() - } - } - public fun g(x: E,v: |E|) { - (v)(x) - } - public fun h(x: E,v: |Key|E): E { - { - let m::E{ key } = x; - (v)(key) - } - } - public fun is_none(t: &Option): bool { - vector::is_empty(Borrow(Immutable)(select m::Option.vec<&Option>(t))) - } - private fun foo$lambda$1(e: Key): E { - pack m::E(e) - } - private fun foo$lambda$2(v: &mut Key,e: E) { - { - let (m::E{ key }, _x: u64): (E, u64) = Tuple(e, 3); - v = key; - Tuple() - } - } -} // end 0x42::m - - Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/unpack_generic_struct.move:24:9 - │ -24 │ v(key) - │ ^ - -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/unpack_generic_struct.move:28:9 - │ -28 │ v(x) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unpack_generic_struct.move:33:25 │ 33 │ let f = h(data, |e| { @@ -683,7 +515,7 @@ error: Function-typed values not yet supported except as parameters to calls to 35 │ │ }); │ ╰─────────^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unpack_generic_struct.move:36:14 │ 36 │ g(f, |e| { diff --git a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unused_lambda_param.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unused_lambda_param.lambda.exp index a720df7124c63..5843e39307da4 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unused_lambda_param.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/inline-parity/unused_lambda_param.lambda.exp @@ -218,102 +218,6 @@ module 0xc0ffee::m { } // end 0xc0ffee::m -// -- Model dump after env processor lambda-lifting: -module 0xc0ffee::m { - private fun test(p: u64,f: |u64|u64): u64 { - (f)(p) - } - private fun unused_lambda() { - m::test(0, closure m::unused_lambda$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed1() { - m::test(0, closure m::unused_lambda_suppressed1$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed2() { - m::test(0, closure m::unused_lambda_suppressed2$lambda$1()); - Tuple() - } - private fun unused_lambda$lambda$1(x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed1$lambda$1(_x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed2$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 1 - } - } -} // end 0xc0ffee::m - - -// -- Model dump after env processor specification checker: -module 0xc0ffee::m { - private fun test(p: u64,f: |u64|u64): u64 { - (f)(p) - } - private fun unused_lambda() { - m::test(0, closure m::unused_lambda$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed1() { - m::test(0, closure m::unused_lambda_suppressed1$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed2() { - m::test(0, closure m::unused_lambda_suppressed2$lambda$1()); - Tuple() - } - private fun unused_lambda$lambda$1(x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed1$lambda$1(_x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed2$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 1 - } - } -} // end 0xc0ffee::m - - -// -- Model dump after env processor specification rewriter: -module 0xc0ffee::m { - private fun test(p: u64,f: |u64|u64): u64 { - (f)(p) - } - private fun unused_lambda() { - m::test(0, closure m::unused_lambda$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed1() { - m::test(0, closure m::unused_lambda_suppressed1$lambda$1()); - Tuple() - } - private fun unused_lambda_suppressed2() { - m::test(0, closure m::unused_lambda_suppressed2$lambda$1()); - Tuple() - } - private fun unused_lambda$lambda$1(x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed1$lambda$1(_x: u64): u64 { - 1 - } - private fun unused_lambda_suppressed2$lambda$1(param$0: u64): u64 { - { - let _: u64 = param$0; - 1 - } - } -} // end 0xc0ffee::m - - Diagnostics: warning: Unused anonymous function parameter `x`. Consider removing or prefixing with an underscore: `_x` @@ -322,27 +226,19 @@ warning: Unused anonymous function parameter `x`. Consider removing or prefixing 7 │ test(0, |x| 1); │ ^ - -Diagnostics: -error: Calls to function values other than inline function parameters not yet supported - ┌─ tests/lambda/inline-parity/unused_lambda_param.move:3:9 - │ -3 │ f(p) - │ ^ - -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unused_lambda_param.move:7:17 │ 7 │ test(0, |x| 1); │ ^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unused_lambda_param.move:11:17 │ 11 │ test(0, |_x| 1); │ ^^^^^^ -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/inline-parity/unused_lambda_param.move:15:17 │ 15 │ test(0, |_| 1); 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 4f17028adb675..7328ae7924537 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda.exp @@ -24,7 +24,7 @@ error: cannot use `()` with an operator which expects a value of type `u64` 56 │ i = i + action(XVector::borrow(v, i)); // expected to have wrong result type │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot return `u64` from a function with result type `|integer|` +error: cannot return `u64` from a function with result type `|integer| with copy+store` ┌─ tests/lambda/lambda.move:61:9 │ 61 │ x(1) // expected to be not a function 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 4f17028adb675..7328ae7924537 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 @@ -24,7 +24,7 @@ error: cannot use `()` with an operator which expects a value of type `u64` 56 │ i = i + action(XVector::borrow(v, i)); // expected to have wrong result type │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot return `u64` from a function with result type `|integer|` +error: cannot return `u64` from a function with result type `|integer| with copy+store` ┌─ tests/lambda/lambda.move:61:9 │ 61 │ x(1) // expected to be not a function diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda3.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda3.exp index b7104b3811ed1..9eb746fa166b1 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda3.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda3.exp @@ -2,7 +2,7 @@ module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } diff --git a/third_party/move/move-compiler-v2/tests/lambda/lambda3.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/lambda3.lambda.exp index db9ce1b64dc58..cca732666e1ef 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/lambda3.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/lambda3.lambda.exp @@ -2,7 +2,7 @@ module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -13,7 +13,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -24,7 +24,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -35,7 +35,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -46,7 +46,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -57,7 +57,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -68,7 +68,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -79,7 +79,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -90,7 +90,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -101,7 +101,7 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } @@ -112,58 +112,16 @@ module 0x8675309::M { module 0x8675309::M { public fun lambda_not_allowed() { { - let _x: |u64|u64 = |i: u64| Add(i, 1); + let _x: |u64|u64 with copy+store = |i: u64| Add(i, 1); Tuple() } } } // end 0x8675309::M -// -- Model dump after env processor lambda-lifting: -module 0x8675309::M { - public fun lambda_not_allowed() { - { - let _x: |u64|u64 = closure M::lambda_not_allowed$lambda$1(); - Tuple() - } - } - private fun lambda_not_allowed$lambda$1(i: u64): u64 { - Add(i, 1) - } -} // end 0x8675309::M - - -// -- Model dump after env processor specification checker: -module 0x8675309::M { - public fun lambda_not_allowed() { - { - let _x: |u64|u64 = closure M::lambda_not_allowed$lambda$1(); - Tuple() - } - } - private fun lambda_not_allowed$lambda$1(i: u64): u64 { - Add(i, 1) - } -} // end 0x8675309::M - - -// -- Model dump after env processor specification rewriter: -module 0x8675309::M { - public fun lambda_not_allowed() { - { - let _x: |u64|u64 = closure M::lambda_not_allowed$lambda$1(); - Tuple() - } - } - private fun lambda_not_allowed$lambda$1(i: u64): u64 { - Add(i, 1) - } -} // end 0x8675309::M - - Diagnostics: -error: Function-typed values not yet supported except as parameters to calls to inline functions +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. ┌─ tests/lambda/lambda3.move:77:18 │ 77 │ let _x = |i| i + 1; // expected lambda not allowed diff --git a/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp index 0a35235798063..8949035e6a9d3 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp +++ b/third_party/move/move-compiler-v2/tests/lambda/non_lambda_arg.lambda.exp @@ -404,13 +404,3 @@ error: local `a_less_b` of type `|(T, T)|bool` does not have the `copy` ability │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ copy needed here because value is still in use 13 │ incorrect_sort_recursive(arr, pi + 1, high, a_less_b); │ ----------------------------------------------------- used here - -error: local `a_less_b` of type `|(T, T)|bool` does not have the `drop` ability - ┌─ tests/lambda/non_lambda_arg.move:10:9 - │ -10 │ ╭ if (low < high) { -11 │ │ let pi = low + high / 2; -12 │ │ incorrect_sort_recursive(arr, low, pi - 1, a_less_b); -13 │ │ incorrect_sort_recursive(arr, pi + 1, high, a_less_b); -14 │ │ }; - │ ╰─────────^ implicitly dropped here since it is no longer used 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 new file mode 100644 index 0000000000000..bee6d7e4e76c2 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.exp @@ -0,0 +1,127 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:43:17 + │ +43 │ move |x| mod3::multiply(4, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:46:17 + │ +46 │ move |y| alt_multiply(x, y) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:49:17 + │ +49 │ move |y| mod3::multiply(y, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:51:17 + │ +51 │ move |x| multiply3(x, 3, 2) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:53:17 + │ +53 │ move |x| mod3::multiply(x, 7) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:55:17 + │ +55 │ move |x| multiply3(4, x, 2) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:57:17 + │ +57 │ move |x| multiply3(3, 3, x) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:61:17 + │ +61 │ move |z| multiply3(x, y, z) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:64:17 + │ +64 │ move |x| alt_multiply(x, z) with copy + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:64:45 + │ +64 │ move |x| alt_multiply(x, z) with copy + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:66:25 + │ +66 │ let g = move |x, y| mod3::multiply(x, y) with copy+drop; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:66:58 + │ +66 │ let g = move |x, y| mod3::multiply(x, y) with copy+drop; + │ ^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:67:17 + │ +67 │ move |x| g(x, 11) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:69:25 + │ +69 │ let h = move |x| mod3::multiply(x, 12) with copy; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:69:56 + │ +69 │ let h = move |x| mod3::multiply(x, 12) with copy; + │ ^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:70:17 + │ +70 │ move |x| { h(x) } with copy + drop + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:70:35 + │ +70 │ move |x| { h(x) } with copy + drop + │ ^^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:72:25 + │ +72 │ let i = move |x| multiply3(2, x, 2); + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:73:17 + │ +73 │ move |z| i(z) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:75:25 + │ +75 │ let i = move |x, y| { let q = y - 1; 0x42::mod3::multiply(x, q + 1) }; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/doable_func.move:76:17 + │ +76 │ move |x| i(x, 15) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression 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 new file mode 100644 index 0000000000000..e39fd4deaeb18 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.lambda.exp @@ -0,0 +1,2465 @@ +// -- Model dump before env processor pipeline: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor unused checks: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor type parameter check: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor unused struct params check: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor inlining: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor acquires check: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + { + let x: u64 = 5; + move|y: u64| mod4::alt_multiply(x, y) + } + } else { + if Eq(key, 4) { + { + let x: u64 = 6; + move|y: u64| mod3::multiply(y, x) + } + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } else { + if Eq(key, 8) { + move|x: u64| test::multiply3(3, 3, x) + } else { + if Eq(key, 9) { + { + let x: u64 = 2; + { + let y: u64 = 5; + move|z: u64| test::multiply3(x, y, z) + } + } + } else { + if Eq(key, 10) { + { + let z: u64 = 11; + move|x: u64| mod4::alt_multiply(x, z) with copy, drop + } + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let x: u64 = 3; + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + { + let __upper_bound_value: u64 = 15; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, __upper_bound_value) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), x)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor simplifier: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + move|x: u64| mod3::multiply(4, x) + } else { + if Eq(key, 3) { + move|y: u64| mod4::alt_multiply(5, y) + } else { + if Eq(key, 4) { + move|y: u64| mod3::multiply(y, 6) + } else { + if Eq(key, 5) { + move|x: u64| test::multiply3(x, 3, 2) + } else { + if Eq(key, 6) { + move|x: u64| mod3::multiply(x, 7) + } else { + if Eq(key, 7) { + move|x: u64| test::multiply3(4, x, 2) + } 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) + } else { + if Eq(key, 10) { + move|x: u64| mod4::alt_multiply(x, 11) with copy, drop + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| mod3::multiply(x, y) with copy, drop; + move|x: u64| (g)(x, 11) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = move|x: u64| mod3::multiply(x, 12) with copy, drop; + move|x: u64| (h)(x) with copy, drop + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = move|x: u64| test::multiply3(2, x, 2); + move|z: u64| (i)(z) + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = move|(x: u64, y: u64): (u64, u64)| { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + }; + move|x: u64| (i)(x, 15) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, 15) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), 3)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } +} // end 0x42::test + + +// -- Model dump after env processor lambda-lifting: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + earlybind(mod3::multiply, 4) + } else { + if Eq(key, 3) { + earlybind(mod4::alt_multiply, 5) + } else { + if Eq(key, 4) { + test::choose_function1$lambda$1 + } else { + if Eq(key, 5) { + test::choose_function1$lambda$2 + } else { + if Eq(key, 6) { + test::choose_function1$lambda$3 + } else { + if Eq(key, 7) { + test::choose_function1$lambda$4 + } else { + if Eq(key, 8) { + earlybind(test::multiply3, 3, 3) + } else { + if Eq(key, 9) { + earlybind(test::multiply3, 2, 5) + } else { + if Eq(key, 10) { + test::choose_function1$lambda$5 + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = mod3::multiply; + earlybind(test::choose_function1$lambda$6, g) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + h + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + i + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; + earlybind(test::choose_function1$lambda$10, i) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, 15) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), 3)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + 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+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 { + { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + } + } + private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+store,x: u64): u64 { + (i)(x, 15) + } +} // end 0x42::test + + +// -- Model dump after env processor specification checker: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + earlybind(mod3::multiply, 4) + } else { + if Eq(key, 3) { + earlybind(mod4::alt_multiply, 5) + } else { + if Eq(key, 4) { + test::choose_function1$lambda$1 + } else { + if Eq(key, 5) { + test::choose_function1$lambda$2 + } else { + if Eq(key, 6) { + test::choose_function1$lambda$3 + } else { + if Eq(key, 7) { + test::choose_function1$lambda$4 + } else { + if Eq(key, 8) { + earlybind(test::multiply3, 3, 3) + } else { + if Eq(key, 9) { + earlybind(test::multiply3, 2, 5) + } else { + if Eq(key, 10) { + test::choose_function1$lambda$5 + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = mod3::multiply; + earlybind(test::choose_function1$lambda$6, g) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + h + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + i + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; + earlybind(test::choose_function1$lambda$10, i) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, 15) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), 3)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + 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+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 { + { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + } + } + private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+store,x: u64): u64 { + (i)(x, 15) + } +} // end 0x42::test + + +// -- Model dump after env processor specification rewriter: +module 0x42::mod4 { + public fun alt_multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod4 +module 0x42::mod3 { + public fun multiply(x: u64,y: u64): u64 { + Mul(x, y) + } +} // end 0x42::mod3 +module 0x42::mod2 { + friend fun double(x: u64): u64 { + Mul(x, 2) + } +} // end 0x42::mod2 +module 0x42::mod1 { + friend fun triple(x: u64): u64 { + Mul(x, 3) + } +} // end 0x42::mod1 +module 0x42::test { + use 0x42::mod1; // resolved as: 0x42::mod1 + use 0x42::mod2; // resolved as: 0x42::mod2 + use 0x42::mod3; // resolved as: 0x42::mod3 + use 0x42::mod4::{alt_multiply}; // resolved as: 0x42::mod4 + private fun add_mul(x: u64,y: u64,z: u64): u64 { + Mul(z, Add(x, y)) + } + private fun choose_function1(key: u64,x: u64): u64 { + { + let f: |u64|u64 with copy = if Eq(key, 0) { + mod2::double + } else { + if Eq(key, 1) { + mod1::triple + } else { + if Eq(key, 2) { + earlybind(mod3::multiply, 4) + } else { + if Eq(key, 3) { + earlybind(mod4::alt_multiply, 5) + } else { + if Eq(key, 4) { + test::choose_function1$lambda$1 + } else { + if Eq(key, 5) { + test::choose_function1$lambda$2 + } else { + if Eq(key, 6) { + test::choose_function1$lambda$3 + } else { + if Eq(key, 7) { + test::choose_function1$lambda$4 + } else { + if Eq(key, 8) { + earlybind(test::multiply3, 3, 3) + } else { + if Eq(key, 9) { + earlybind(test::multiply3, 2, 5) + } else { + if Eq(key, 10) { + test::choose_function1$lambda$5 + } else { + if Eq(key, 11) { + { + let g: |(u64, u64)|u64 with copy+store = mod3::multiply; + earlybind(test::choose_function1$lambda$6, g) + } + } else { + if Eq(key, 12) { + { + let h: |u64|u64 with copy+store = test::choose_function1$lambda$7; + h + } + } else { + if Eq(key, 14) { + { + let i: |u64|u64 with copy+store = test::choose_function1$lambda$8; + i + } + } else { + { + let i: |(u64, u64)|u64 with copy+store = test::choose_function1$lambda$9; + earlybind(test::choose_function1$lambda$10, i) + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }; + (f)(x) + } + } + private fun multiply3(x: u64,y: u64,z: u64): u64 { + Mul(Mul(x, y), z) + } + public fun test_functions() { + { + let i: u64 = 0; + { + let __update_iter_flag: bool = false; + loop { + if true { + if __update_iter_flag { + i: u64 = Add(i, 1) + } else { + __update_iter_flag: bool = true + }; + if Lt(i, 15) { + { + let y: u64 = test::choose_function1(i, 3); + if Eq(y, Mul(Add(i, 2), 3)) { + Tuple() + } else { + Abort(i) + }; + Tuple() + } + } else { + break + }; + Tuple() + } else { + break + } + }; + Tuple() + } + } + } + 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+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 { + { + let q: u64 = Sub(y, 1); + mod3::multiply(x, Add(q, 1)) + } + } + private fun choose_function1$lambda$10(i: |(u64, u64)|u64 with copy+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 + ┌─ 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 + ┌─ 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 + ┌─ 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 + ┌─ 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 + ┌─ tests/lambda/storable/doable_func.move:49:17 + │ +49 │ move |y| mod3::multiply(y, x) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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) + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet supported 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 + ┌─ tests/lambda/storable/doable_func.move:61:17 + │ +61 │ move |z| multiply3(x, 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 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet supported 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 + ┌─ tests/lambda/storable/doable_func.move:67:17 + │ +67 │ move |x| g(x, 11) + │ ^^^^^^^^^^^^^^^^^ + +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; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Function-typed values not yet supported 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 + ┌─ tests/lambda/storable/doable_func.move:76:17 + │ +76 │ move |x| i(x, 15) + │ ^^^^^^^^^^^^^^^^^ + +error: Calls to function values other than inline function parameters not yet supported + ┌─ 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 new file mode 100644 index 0000000000000..e53e9c9d3dc45 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/doable_func.move @@ -0,0 +1,93 @@ +module 0x42::mod1 { + package fun triple(x: u64) : u64 { + x * 3 + } +} + +module 0x42::mod2 { + friend 0x42::test; + friend fun double(x: u64): u64 { + x * 2 + } +} + +module 0x42::mod3 { + public fun multiply(x: u64, y: u64): u64 { + x * y + } +} + +module 0x42::mod4 { + public fun alt_multiply(x: u64, y: u64): u64 { + x * y + } +} + +module 0x42::test { + use 0x42::mod1; + use 0x42::mod2; + use 0x42::mod3; + use 0x42::mod4::alt_multiply; + fun multiply3(x: u64, y: u64, z: u64): u64 { + x * y * z + } + + // compute ((key + 2) * x) in different ways + 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) { + let x = 5; + move |y| alt_multiply(x, y) + } else if (key == 4) { + let x = 6; + move |y| mod3::multiply(y, x) + } 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) { + let x = 2; + let y = 5; + move |z| multiply3(x, y, z) + } else if (key == 10) { + let z = 11; + move |x| alt_multiply(x, z) with copy + } else if (key == 11) { + let g = move |x, y| mod3::multiply(x, y) with copy+drop; + move |x| g(x, 11) + } else if (key == 12) { + let h = move |x| mod3::multiply(x, 12) with copy; + move |x| { h(x) } with copy + drop + } else if (key == 14) { + let i = move |x| multiply3(2, x, 2); + 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) + }; + f(x) + } + + fun add_mul(x: u64, y: u64, z: u64): u64 { + z * (x + y) + } + + public fun test_functions() { + let x = 3; + + for (i in 0..15) { + let y = choose_function1(i, 3); + assert!(y == (i + 2) * x, i); + } + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.exp new file mode 100644 index 0000000000000..a10657000e3ac --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.exp @@ -0,0 +1,10 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/lambda/storable/parse_errors.move:10:15 + │ +10 │ x.y[3](27) + │ ^ + │ │ + │ Unexpected '(' + │ Expected ';' diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.lambda.exp new file mode 100644 index 0000000000000..a10657000e3ac --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.lambda.exp @@ -0,0 +1,10 @@ + +Diagnostics: +error: unexpected token + ┌─ tests/lambda/storable/parse_errors.move:10:15 + │ +10 │ x.y[3](27) + │ ^ + │ │ + │ Unexpected '(' + │ Expected ';' diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.move b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.move new file mode 100644 index 0000000000000..2c39942fb7a24 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/parse_errors.move @@ -0,0 +1,107 @@ +module 0x42::mod1 { + package fun triple(x: u64) : u64 { + x * 3 + } +} + +module 0x42::mod2 { + friend 0x42::test; + friend fun double(x: u64): u64 { + x.y[3](27) + } +} + +module 0x42::mod3 { + public fun multiply(x: u64, y: u64): u64 { + x * y + } +} + +module 0x42::mod4 { + public fun alt_multiply(x: u64, y: u64): u64 { + x * y + } +} + +module 0x42::mod5 { + struct S { + f: u64, + y: |u64|u64 with copy, + } + fun f(s: S): S { + let x = s.y(3); + let z = S { f: 4, y: s.y }; + z + } +} + + +module 0x42::test { + use 0x42::mod1; + use 0x42::mod2; + use 0x42::mod3; + use 0x42::mod4::alt_multiply; + fun multiply3(x: u64, y: u64, z: u64): u64 { + x * y * z + } + + // compute ((key + 2) * x) in different ways + 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) { + let x = 5; + move |y| alt_multiply(x, y) + } else if (key == 4) { + let x = 6; + move |y| mod3::multiply(y, x) + } 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) { + let x = 2; + let y = 5; + move |z| multiply3(x, y, z) + } else if (key == 10) { + let z = 11; + move |x| alt_multiply(x, z) with copy + } else if (key == 11) { + let g = move |x, y| mod3::multiply(x, y) has copy+drop; + move |x| g(x, 11) + } else if (key == 12) { + let h = move |x| mod3::multiply(x, 12) with copy; + move |x| { h(x) } with copy + drop + } else if (key == 14) { + let i = move |x| multiply3(2, x, 2); + 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) + }; + f(x) + } + + fun add_mul(x: u64, y: u64, z: u64): u64 { + z * (x + y) + } + + public fun test_functions() { + // let sum = vector[]; + let x = 3; + + for (i in 0..15) { + let y = choose_function1(i, 3); + assert!(y == (i + 2) * x, i); + } + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry.exp deleted file mode 100644 index a196cfcde9c4c..0000000000000 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.exp +++ /dev/null @@ -1,9 +0,0 @@ - -Diagnostics: -error: unexpected token - ┌─ tests/lambda/storable/registry.move:7:22 - │ -6 │ struct Function { - │ - To match this '{' -7 │ f: |u64| u64 has store, - │ ^ Expected '}' diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry.lambda.exp deleted file mode 100644 index a196cfcde9c4c..0000000000000 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.lambda.exp +++ /dev/null @@ -1,9 +0,0 @@ - -Diagnostics: -error: unexpected token - ┌─ tests/lambda/storable/registry.move:7:22 - │ -6 │ struct Function { - │ - To match this '{' -7 │ f: |u64| u64 has store, - │ ^ Expected '}' diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry.move deleted file mode 100644 index a6fd8bfab655c..0000000000000 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/registry.move +++ /dev/null @@ -1,109 +0,0 @@ -module 0x42::test { - struct Registry { - functions: vector - } - - struct Function { - f: |u64| u64 has store, - key: u64 - } - - enum Option { - None(), - Some(T) - }; - - fun get_function(v: &vector, k: u64): Option { - mut x = Option::None; - for_each_ref(v, |f: &Function| { - if f.key == k { - x = f.f - } - }); - x - } - - fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 has store): Option { - mut done = false; - for_each_mut(v, |f: &mut Function| { - if f.key == k { - f.f = f; - done = true; - } - }); - if !done { - let new_record = Function { f: f, key: k }; - v.append(new_record); - } - } - - fun register(owner: &signer, f: |u64| u64 has store, k: u64) acquires Registry { - let addr = owner.address; - if !exists(addr) { - let new_registry = Registry { - functions: vector[] - }; - move_to(owner, 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(registry.functions, k) { - Some(func) => { - let Function { f: f, key: key } = &func; - 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 has store { - curry(&multiply, x) - } - - - #[test(a = @0x42)] - 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); - - 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); - } - } -} 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 new file mode 100644 index 0000000000000..7c9e57dffddbf --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.exp @@ -0,0 +1,37 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:9:22 + │ +9 │ f: |u64| u64 with store, + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:28:80 + │ +28 │ fun replace_or_add_function(v: &mut vector, k: u64, f: |u64| u64 with store): Option { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:42:47 + │ +42 │ fun register(owner: &signer, f: |u64| u64 with store, k: u64) acquires Registry { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:91:41 + │ +91 │ fun multiply_by_x(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:95:42 + │ +95 │ fun multiply_by_x2(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_errors.move:96:9 + │ +96 │ move |y| multiply(x, y) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression 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 new file mode 100644 index 0000000000000..0cc07aff247e8 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.lambda.exp @@ -0,0 +1,83 @@ + +Diagnostics: +error: function type `|u64|u64 with 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 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) + │ ^^^^^^^^^^^^ + │ + = required by instantiating type parameter `T` of struct `Option` + +error: expected `&mut Function` but found a value of type `|u64|u64 with store` + ┌─ tests/lambda/storable/registry_errors.move:32:17 + │ +32 │ f.f = f; + │ ^^^ + +error: undeclared receiver function `append` for type `vector` + ┌─ tests/lambda/storable/registry_errors.move:38:13 + │ +38 │ v.append(new_record); + │ ^^^^^^^^^^^^^^^^^^^^ + +error: cannot return nothing from a function with result type `Option` + ┌─ tests/lambda/storable/registry_errors.move:38:33 + │ +38 │ v.append(new_record); + │ ^ + +error: cannot return nothing from a function with result type `Option` + ┌─ tests/lambda/storable/registry_errors.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_errors.move:43:20 + │ +43 │ let addr = owner.address; + │ ^^^^^ + +error: undeclared `registry` + ┌─ tests/lambda/storable/registry_errors.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_errors.move:68:29 + │ +68 │ match (get_function(registry.functions, k)) { + │ ^^^^^^^^^^^^^^^^^^ + +error: undeclared struct `test::Some` + ┌─ tests/lambda/storable/registry_errors.move:69:13 + │ +69 │ Some(func) => { + │ ^^^^ + +error: undeclared `func` + ┌─ tests/lambda/storable/registry_errors.move:70:52 + │ +70 │ let Function { f: f, key: key } = &func; + │ ^^^^ + +error: expected `|u64|u64 with copy+store` but found a value of type `&|u64|u64 with store` + ┌─ tests/lambda/storable/registry_errors.move:71:22 + │ +71 │ Some(f(x)) + │ ^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.move b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.move new file mode 100644 index 0000000000000..e79347c2f55ed --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_errors.move @@ -0,0 +1,128 @@ +module 0x42::test { + use std::vector; + + struct Registry has key { + functions: vector + } + + struct Function has store { + f: |u64| u64 with store, + key: u64 + } + + enum Option { + None(), + Some(T) + } + + fun get_function(v: &vector, k: u64): Option { + let x = Option::None(); + vector::for_each_ref(v, |f: &Function| { + 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): Option { + let done = false; + vector::for_each_mut(v, |f: &mut Function| { + if (f.key == k) { + f.f = f; + done = true; + } + }); + if (!done) { + let new_record = Function { f: f, key: k }; + v.append(new_record); + } + } + + fun register(owner: &signer, f: |u64| u64 with store, k: u64) acquires Registry { + let addr = owner.address; + if (!exists(addr)) { + let new_registry = Registry { + functions: vector[] + }; + move_to(owner, 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); + if (x == 1) { + return Option::None; + }; + if (x == 2) { + return Option::None(); + }; + if (x == 6) { + return Option::None() + }; + match (get_function(registry.functions, k)) { + Some(func) => { + let Function { f: f, key: key } = &func; + 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 { + |y| multiply(x, y) + } + + fun multiply_by_x2(x: u64): |u64|u64 with store { + 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/registry_ok.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp new file mode 100644 index 0000000000000..9292304f56251 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.exp @@ -0,0 +1,43 @@ + +Diagnostics: +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:10:22 + │ +10 │ f: |u64| u64 with store+copy, + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:29:84 + │ +29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:29:119 + │ +29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:53:47 + │ +53 │ fun register(owner: &signer, f: |u64| u64 with store+copy, k: u64) acquires Registry { + │ ^^^^^^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:106:41 + │ +106 │ fun multiply_by_x(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:110:42 + │ +110 │ fun multiply_by_x2(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/registry_ok.move:111:9 + │ +111 │ move |y| multiply(x, y) + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression 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 new file mode 100644 index 0000000000000..cfe0567301c9b --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.lambda.exp @@ -0,0 +1,42 @@ + +Diagnostics: +error: function type `|u64|u64 with copy+store` is not allowed as a field type + ┌─ tests/lambda/storable/registry_ok.move:10:12 + │ +10 │ f: |u64| u64 with store+copy, + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + │ + = required by declaration of field `f` + +error: function type `|u64|u64 with copy+store` is not allowed as a type argument (type was inferred) + ┌─ tests/lambda/storable/registry_ok.move:23:21 + │ +14 │ enum Option { + │ - declaration of type parameter `T` + · +23 │ x = Option::Some(f.f) + │ ^^^^^^^^^^^^ + │ + = required by instantiating type parameter `T` of struct `Option` + +error: function type `|u64|u64 with copy+store` is not allowed as a type argument + ┌─ tests/lambda/storable/registry_ok.move:29:109 + │ +14 │ enum Option { + │ - declaration of type parameter `T` + · +29 │ fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + │ ^^^^^^^^^^^^^^^^^^^^^^^^^ + │ + = required by instantiating type parameter `T` of struct `Option` + +error: function type `|u64|u64 with copy+store` is not allowed as a type argument (type was inferred) + ┌─ tests/lambda/storable/registry_ok.move:33:26 + │ +14 │ enum Option { + │ - declaration of type parameter `T` + · +33 │ result = Option::Some(f.f); + │ ^^^^^^^^^^^^ + │ + = required by instantiating type parameter `T` of struct `Option` 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 new file mode 100644 index 0000000000000..047415e26d4ef --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/registry_ok.move @@ -0,0 +1,182 @@ +module 0x42::test { + use std::vector; + use std::signer; + + struct Registry has key { + functions: vector + } + + struct Function has store { + f: |u64| u64 with store+copy, + key: u64 + } + + enum Option { + None(), + Some(T) + } + + fun get_function(v: &vector, k: u64): Option { + let x = Option::None; + vector::for_each_ref(v, |f: &Function| { + if (f.key == k) { + x = Option::Some(f.f) + } + }); + x + } + + fun replace_or_add_function(v: &mut vector, k: u64, new_f: |u64| u64 with store+copy): Option<|u64| u64 with store+copy> { + let result = Option::None; + vector::for_each_mut(v, |f: &mut Function| { + if (f.key == k) { + result = Option::Some(f.f); + f.f = new_f; + } + }); + if (result == Option::None) { + let new_record = Function { f: new_f, key: k }; + vector::push_back(v, new_record); + }; + result + } + + public fun alt_call_selected_function(v: &vector, k: u64, x: u64): Option { + for (i in 0..(vector::length(v))) { + if (v[i].key == k) { + return Option::Some((v[i].f)(x)) + } + }; + None + } + + 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)) { + Some(func) => { + let Function { f: f, key: key } = func; + Option::Some(f(x)) + }, + _ => { + Option::None + } + } + } + + fun invoke2(addr: address, k: u64, x: u64): Option acquires Registry { + if (!exists(addr)) { + return Option::None + }; + let registry = borrow_global(addr); + for (i in 0..(vector::length(®istry.functions))) { + if (registry.functions[i].key == k) { + return Option::Some((registry.functions[i].f)(x)) + } + }; + 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 { + |y| multiply(x, y) + } + + fun multiply_by_x2(x: u64): |u64|u64 with store { + 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)) { + Option::Some(x) => { assert!(x == 20); } + _ => assert!(false) + }; + match (invoke(a, 3, 11)) { + Option::Some(x) => { assert!(x == 33); } + _ => assert!(false) + }; + match (invoke(a, 4, 2)) { + Option::Some(x) => { assert!(x == 8); } + _ => assert!(false) + }; + match (invoke(a, 5, 3)) { + Option::Some(x) => { assert!(x == 15); } + _ => assert!(false) + }; + match (invoke(a, 6, 3)) { + Option::Some(x) => { assert!(x == 18); } + _ => assert!(false) + }; + } + + #[test(a = @0x42)] + fun test_registry2(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 (invoke2(a, 2, 10)) { + Some(x) => { assert!(x == 20); } + _ => assert!(false) + }; + match (invoke2(a, 3, 11)) { + Some(x) => { assert!(x == 33); } + _ => assert!(false) + }; + match (invoke2(a, 4, 2)) { + Some(x) => { assert!(x == 8); } + _ => assert!(false) + }; + match (invoke2(a, 5, 3)) { + Some(x) => { assert!(x == 15); } + _ => assert!(false) + }; + match (invoke2(a, 6, 3)) { + Some(x) => { assert!(x == 18); } + _ => assert!(false) + }; + } + + + #[test(a = @0x42)] + fun test_registry3(a: signer) { + register(a, double, 2); + let registry = borrow_global(a); + assert!(registry.functions[0].key == 2); + assert!((registry.functions[0].func)(3) == 6); + } +} diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.exp new file mode 100644 index 0000000000000..66d4547f944b1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: expected `bool` but found a value of type `integer` + ┌─ tests/lambda/storable/retain_funcs.move:6:23 + │ +6 │ let f = |x| { if (x) { 2 } else { false } }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.lambda.exp new file mode 100644 index 0000000000000..66d4547f944b1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.lambda.exp @@ -0,0 +1,7 @@ + +Diagnostics: +error: expected `bool` but found a value of type `integer` + ┌─ tests/lambda/storable/retain_funcs.move:6:23 + │ +6 │ let f = |x| { if (x) { 2 } else { false } }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.move b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.move new file mode 100644 index 0000000000000..81d75d4fa41ad --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/retain_funcs.move @@ -0,0 +1,20 @@ +//# publish +module 0x8675::M { + inline fun test1(r: u64): u64 { + let t = r; // t = 10 + let t2 = 0; // t2 = 0 + let f = |x| { if (x) { 2 } else { false } }; + while (r > 0) { + let x = r; // x = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 + r = r - 1; // r = 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + t2 = t2 + x; // t2= 10, 19, 27, 34, 40, 45, 49, 52, 54, 55 + }; + let t3 = r + t + t2; // 0 + 10 + 55 = 65 + t3 // 65 + } + public fun test(): u64 { + test1(10) + } +} + +//# run 0x8675::M::test 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 38e1020313014..bcd14792c5468 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 @@ -1,10 +1,187 @@ Diagnostics: -error: unexpected token - ┌─ tests/lambda/storable/return_func.move:14:41 - │ -14 │ fun multiply_by_x(x: u64): |u64|u64 has store { - │ ^^^ - │ │ - │ Unexpected 'has' - │ Expected '{' +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:20:41 + │ +20 │ fun multiply_by_x(x: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:21:9 + │ +21 │ move |y| multiply(x, y) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:21:33 + │ +21 │ move |y| multiply(x, y) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:24:46 + │ +24 │ fun choose_function(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:34:46 + │ +34 │ fun choose_function2(key: u64): |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:36:13 + │ +36 │ move |x| double(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:36:32 + │ +36 │ move |x| double(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:38:13 + │ +38 │ move |x| triple(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:38:32 + │ +38 │ move |x| triple(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:41:13 + │ +41 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:41:27 + │ +41 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:44:13 + │ +44 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:44:27 + │ +44 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:46:21 + │ +46 │ let f = move |y| multiply(6, y) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:46:45 + │ +46 │ let f = move |y| multiply(6, y) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:49:13 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:49:37 + │ +49 │ move |y| multiply(y, 7) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:51:21 + │ +51 │ let f = move |y| multiply(6, y) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:51:45 + │ +51 │ let f = move |y| multiply(6, y) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:52:13 + │ +52 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:52:27 + │ +52 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:55:13 + │ +55 │ move |x| f(x) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:55:27 + │ +55 │ move |x| f(x) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:57:13 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:57:41 + │ +57 │ move |y| multiply3(y, 3, 4) with store + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:61:47 + │ +61 │ fun choose_function3(key: u64) : |u64|u64 with store { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:63:21 + │ +63 │ let f = move |x| double(x) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:63:40 + │ +63 │ let f = move |x| double(x) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:66:21 + │ +66 │ let g = move |x| triple(x) with store; + │ ^^^^ Move 2.2 language construct is not enabled: Modifier on lambda expression + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:66:40 + │ +66 │ let g = move |x| triple(x) with store; + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Abilities on function expressions + +error: unsupported language construct + ┌─ tests/lambda/storable/return_func.move:74:63 + │ +74 │ public fun test_functions(choose_function: |u64|(|u64|u64 with store)) { + │ ^^^^^^^^^^ Move 2.2 language construct is not enabled: Ability constraints on function types 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 38e1020313014..7dd9a43a5339c 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 @@ -1,10 +1,47 @@ Diagnostics: -error: unexpected token - ┌─ tests/lambda/storable/return_func.move:14:41 - │ -14 │ fun multiply_by_x(x: u64): |u64|u64 has store { - │ ^^^ - │ │ - │ Unexpected 'has' - │ Expected '{' +error: type `|u64|u64 with copy` is missing required ability `store` + ┌─ tests/lambda/storable/return_func.move:26:13 + │ +26 │ double + │ ^^^^^^ + +error: type `|u64|u64 with copy` is missing required ability `store` + ┌─ tests/lambda/storable/return_func.move:28:13 + │ +28 │ triple + │ ^^^^^^ + +error: expected `|integer|_ with copy+store` but found a value of type `u64` + ┌─ tests/lambda/storable/return_func.move:85:37 + │ +85 │ vector::push_back(&mut sum, f(5)); + │ ^^^^ + +error: expected `|integer|_ with copy+store` but found a value of type `u64` + ┌─ tests/lambda/storable/return_func.move:86:37 + │ +86 │ vector::push_back(&mut sum, g(7)); + │ ^^^^ + +error: expected `|integer|_ with copy+store` but found a value of type `u64` + ┌─ tests/lambda/storable/return_func.move:87:37 + │ +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 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.move b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.move index 4f6e078d8a460..40c0e4966cf03 100644 --- a/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.move +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/return_func.move @@ -1,4 +1,6 @@ module 0x42::test { + use std::vector; + fun double(x: u64): u64 { x * 2 } @@ -11,36 +13,57 @@ module 0x42::test { x * y } - fun multiply_by_x(x: u64): |u64|u64 has store { - curry(&multiply, x) + 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 has store { - if key == 0 { - &double - } else if key == 1 { - &triple + 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 has store { - if key == 0 { - |x| double(x); - } else if key == 1 { - |x| triple(x); + 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 { - |x| multiply_by_x(4)(x) + move |y| multiply3(y, 3, 4) with store } } - fun choose_function3(key: u64) : |u64|u64 has store { - if key == 0 { - let f = |x| double(x); + 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 = |x| triple(x); + } else if (key == 1) { + let g = move |x| triple(x) with store; g } else { let h = multiply_by_x(4); @@ -48,32 +71,32 @@ module 0x42::test { } } - public fun test_functions(choose_function: |u64|(|u64|u64 has store)) { - let sum = vector[]; + public fun test_functions(choose_function: |u64|(|u64|u64 with store)) { + let sum = vector[]; let x = 3; - sum.push_back(choose_function(0)(x)); - sum.push_back(choose_function(1)(x)); - sum.push_back(choose_function(2)(x)); + vector::push_back(&mut sum, (choose_function(0))(x)); + vector::push_back(&mut sum, (choose_function(1))(x)); + vector::push_back(&mut sum, (choose_function(2))(x)); let g = choose_function(1)(x); let h = choose_function(2)(x); let f = choose_function(0)(x); - sum.push_back(f(5)); - sum.push_back(g(7)); - sum.push_back(h(6)); + 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)]; - sum.push_back(f[0](9)); - sum.push_back(f[1](11)); - sum.push_back(f[2](13)); + 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!(vector[6, 9, 12, 10, 21, 24, 18, 33, 52]) + 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); + test_functions(choose_function); + test_functions(choose_function2); + test_functions(choose_function3); } } diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.exp new file mode 100644 index 0000000000000..cbd7f88334ab1 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.exp @@ -0,0 +1,51 @@ + +Diagnostics: +warning: Unused local variable `f`. Consider removing or prefixing with an underscore: `_f` + ┌─ tests/lambda/storable/simplifier_func.move:7:13 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^ + +warning: Unused local variable `t`. Consider removing or prefixing with an underscore: `_t` + ┌─ tests/lambda/storable/simplifier_func.move:7:32 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^ + +// -- Model dump before bytecode pipeline +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + +// -- Sourcified model before bytecode pipeline +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + let f = |x| { + let t = S{x: 3}; + x + }; + x * 3 + } +} + + +Diagnostics: +error: Function-typed values not yet supported except as parameters to calls to inline functions + ┌─ tests/lambda/storable/simplifier_func.move:7:17 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.lambda.exp b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.lambda.exp new file mode 100644 index 0000000000000..233e8b77f24dd --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.lambda.exp @@ -0,0 +1,206 @@ +// -- Model dump before env processor pipeline: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor unused checks: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor type parameter check: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor check recursive struct definition: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor check cyclic type instantiation: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor unused struct params check: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor access and use check before inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor access and use check after inlining: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor acquires check: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + +// -- Model dump after env processor simplifier: +module 0x42::mod1 { + struct S { + x: u64, + } + public fun triple(x: u64): u64 { + { + let f: |u64|u64 with copy+store = |x: u64| { + let t: S = pack mod1::S(3); + x + }; + Mul(x, 3) + } + } +} // end 0x42::mod1 + + + +Diagnostics: +warning: Unused local variable `f`. Consider removing or prefixing with an underscore: `_f` + ┌─ tests/lambda/storable/simplifier_func.move:7:13 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^ + +warning: Unused local variable `t`. Consider removing or prefixing with an underscore: `_t` + ┌─ tests/lambda/storable/simplifier_func.move:7:32 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^ + +error: Currently, lambda expressions must explicitly declare `move` capture of free variables, except when appearing as an argument to an inline function call. + ┌─ tests/lambda/storable/simplifier_func.move:7:17 + │ +7 │ let f = |x: u64| { let t = S { x: 3 }; x }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.move b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.move new file mode 100644 index 0000000000000..a418d25cf855a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/lambda/storable/simplifier_func.move @@ -0,0 +1,10 @@ +module 0x42::mod1 { + struct S { // no drop + x: u64 + } + + public fun triple(x: u64) : u64 { + let f = |x: u64| { let t = S { x: 3 }; x }; + x * 3 + } +} diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression.exp index eb41afe8197db..83950af3cd058 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression.exp @@ -1,10 +1,19 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression.move:3:29 +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression.move:3:20 │ 3 │ (if (true) 5 else 0)(); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^ + +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression.move:3:27 + │ +3 │ (if (true) 5 else 0)(); + │ ^ + +error: expected `|(integer, integer)|_` but found a value of type `()` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression.move:4:9 + │ +4 │ (while (false) {})(0, 1); + │ ^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression2.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression2.exp index 03ed8ceb2af6f..6e260fff7fec5 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression2.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_complex_expression2.exp @@ -1,10 +1,19 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression2.move:3:29 +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression2.move:3:20 │ 3 │ (if (true) 5 else 0)(); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^ + +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression2.move:3:27 + │ +3 │ (if (true) 5 else 0)(); + │ ^ + +error: expected `|(integer, integer)|_` but found a value of type `()` + ┌─ tests/more-v1/parser/invalid_call_lhs_complex_expression2.move:4:9 + │ +4 │ (while (false) {})(0, 1); + │ ^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name.exp index 222dec853b372..8d362e905076d 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name.exp @@ -1,10 +1,7 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_parens_around_name.move:3:14 +error: Calls to function values other than inline function parameters not yet supported + ┌─ tests/more-v1/parser/invalid_call_lhs_parens_around_name.move:3:9 │ 3 │ (foo)() - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name2.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name2.exp index f47f13fe5ecb6..7429935364695 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name2.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_parens_around_name2.exp @@ -1,10 +1,7 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_parens_around_name2.move:3:14 +error: Calls to function values other than inline function parameters not yet supported + ┌─ tests/more-v1/parser/invalid_call_lhs_parens_around_name2.move:3:9 │ 3 │ (foo)() - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return.exp index 332165ecd3108..4890ecb1afef1 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return.exp @@ -1,10 +1,7 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_return.move:3:20 +error: Calls to function values other than inline function parameters not yet supported + ┌─ tests/more-v1/parser/invalid_call_lhs_return.move:3:9 │ 3 │ (return ())(0, 1); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return2.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return2.exp index b9972c50113c3..9b0ec32618792 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return2.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_return2.exp @@ -1,10 +1,7 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_return2.move:3:20 +error: Calls to function values other than inline function parameters not yet supported + ┌─ tests/more-v1/parser/invalid_call_lhs_return2.move:3:9 │ 3 │ (return ())(0, 1); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value.exp index d17d58623b224..6df708c2205eb 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value.exp @@ -1,10 +1,13 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_value.move:3:10 +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_value.move:3:9 │ 3 │ 5(); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^ + +error: expected `|(integer, integer)|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_value.move:4:9 + │ +4 │ 5(0, 1); + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value2.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value2.exp index e2f3d92b38d92..34a3e9e9a6b5b 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value2.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/invalid_call_lhs_value2.exp @@ -1,10 +1,13 @@ Diagnostics: -error: unexpected token - ┌─ tests/more-v1/parser/invalid_call_lhs_value2.move:3:10 +error: expected `|()|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_value2.move:3:9 │ 3 │ 5(); - │ ^ - │ │ - │ Unexpected '(' - │ Expected ';' + │ ^ + +error: expected `|(integer, integer)|_` but found a value of type `integer` + ┌─ tests/more-v1/parser/invalid_call_lhs_value2.move:4:9 + │ +4 │ 5(0, 1); + │ ^ diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/spec_parsing_ok.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/spec_parsing_ok.exp index 729c903a835a0..bec31b588f3e5 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/spec_parsing_ok.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/spec_parsing_ok.exp @@ -48,7 +48,7 @@ error: expression construct not supported in specifications 69 │ ensures RET = {let y = x; y + 1}; │ ^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot pass `|(num, num)|num` to a function which expects argument of type `|(num, num)|bool` +error: cannot pass `|(num, num)|num with copy+store` to a function which expects argument of type `|(num, num)|bool` ┌─ tests/more-v1/parser/spec_parsing_ok.move:77:24 │ 77 │ ensures all(x, |y, z| x + y + z); diff --git a/third_party/move/move-compiler-v2/tests/more-v1/parser/unexpected_token_after_ability_function_constraint.exp b/third_party/move/move-compiler-v2/tests/more-v1/parser/unexpected_token_after_ability_function_constraint.exp index b9eafd1f9f753..9808aa198bb4b 100644 --- a/third_party/move/move-compiler-v2/tests/more-v1/parser/unexpected_token_after_ability_function_constraint.exp +++ b/third_party/move/move-compiler-v2/tests/more-v1/parser/unexpected_token_after_ability_function_constraint.exp @@ -4,7 +4,6 @@ error: unexpected token ┌─ tests/more-v1/parser/unexpected_token_after_ability_function_constraint.move:4:21 │ 4 │ fun foo() {} - │ ^ - │ │ - │ Unexpected '&' - │ Expected one of: '+', '>', or ',' + │ - ^ Expected '>' + │ │ + │ To match this '<' diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index acbab3106d398..eff9be3737cf6 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -174,7 +174,8 @@ const TEST_CONFIGS: Lazy> = Lazy::new(|| { .set_experiment(Experiment::LAMBDA_IN_PARAMS, true) .set_experiment(Experiment::LAMBDA_IN_RETURNS, true) .set_experiment(Experiment::LAMBDA_VALUES, true) - .set_experiment(Experiment::LAMBDA_LIFTING, true), + .set_experiment(Experiment::LAMBDA_LIFTING, true) + .set_language_version(LanguageVersion::V2_LAMBDA), stop_after: StopAfter::FileFormat, dump_ast: DumpLevel::AllStages, dump_bytecode: DumpLevel::EndStage, diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp index a4bb458cc6f57..e368f5af7f888 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param_typed.exp @@ -24,7 +24,7 @@ comparison between v1 and v2 failed: = - error[E01013]: unsupported language construct - ┌─ TEMPFILE:24:73 -+ error: cannot pass `|(u64, u64)|integer` to a function which expects argument of type `|(&integer, &mut integer)|u64` ++ error: cannot pass `|(u64, u64)|integer with copy+store` to a function which expects argument of type `|(&integer, &mut integer)|u64` + ┌─ TEMPFILE:24:64 = │ = 24 │ assert!(elem_for_each_ref(&mut vector[Elem{k:1, v:2}], |x: u64, y: u64| *x + *y) == 3, 0) diff --git a/third_party/move/move-compiler/src/expansion/ast.rs b/third_party/move/move-compiler/src/expansion/ast.rs index 47db86f2654ba..8a241a6091ae3 100644 --- a/third_party/move/move-compiler/src/expansion/ast.rs +++ b/third_party/move/move-compiler/src/expansion/ast.rs @@ -6,8 +6,8 @@ use crate::{ expansion::translate::is_valid_struct_constant_or_schema_name, parser::ast::{ self as P, Ability, Ability_, BinOp, CallKind, ConstantName, Field, FunctionName, Label, - ModuleName, QuantKind, SpecApplyPattern, StructName, UnaryOp, UseDecl, Var, VariantName, - ENTRY_MODIFIER, + LambdaCaptureKind, ModuleName, QuantKind, SpecApplyPattern, StructName, UnaryOp, UseDecl, + Var, VariantName, ENTRY_MODIFIER, }, shared::{ ast_debug::*, @@ -401,7 +401,7 @@ pub enum Type_ { Multiple(Vec), Apply(ModuleAccess, Vec), Ref(bool, Box), - Fun(Vec, Box), + Fun(Vec, Box, AbilitySet), UnresolvedError, } pub type Type = Spanned; @@ -498,6 +498,7 @@ pub enum Exp_ { Name(ModuleAccess, Option>), Call(ModuleAccess, CallKind, Option>, Spanned>), + ExpCall(Box, Spanned>), Pack(ModuleAccess, Option>, Fields), Vector(Loc, Option>, Spanned>), @@ -506,7 +507,7 @@ pub enum Exp_ { While(Option