From 2141444ca406992a2d16de2b50a42ac584c49818 Mon Sep 17 00:00:00 2001 From: Wolfgang Grieskamp Date: Wed, 13 Mar 2024 13:34:06 -0700 Subject: [PATCH] [compiler-v2] Making v2 the basis of the prover (step #1) (#12462) * [compiler-v2] Making v2 the basis of the prover (step #1) This adds the missing parts to let compiler v2 fully support the specification language, and switches the prover to use v2 as the basis for verification of v1 bytecode. There is one further step needed to run the prover also on the code generated by v2 but that one is smaller than here. Notice that with this, we are dogfooding the v2 compiler frontend in production with the Move prover. There is no switching back and forth, code for the v1 prover integration has been removed. In more detail this does the following: - There are two new env processors, the spec_checker and the spec_rewriter: - `spec_checker` checks the correct use of Move functions in the specification language. Those functions must be 'pure' and not depend on state or use certain other constructs. The checker is to be run as part of the regular compiler chain. - `spec_rewriter` rewrites specification expressions by converting used Move functions into specification functions, and doing other transformations to lift a Move expression into the specification language. This is only run by the prover itself. - Inlining has been extended to deal with specification constructs. - To support the inlining refactoring and the new processors, a new module `rewrite_target` is introduced which allows to collect functions and specification elements in a program in a unified fashion, rewriting them, and writing back to the environment. This new data structure has been inspired by the current design of the inliner and naturally extends it. - A lot of ugliness has been ripped out of the model builder infrastructure (e.g. `TryImplAsSpec` mode is gone, as this is now handled by the `spec_rewriter`). More should come in step #2. - Multiple test cases have been added. - The prover driver has been adapted to use the new components. * Fixing some unit tests * Making hopefully all tests pass: - Adding tuple support to the specification language as they are created by the inliner. - Fixing an issue in memory usage calculation - Adding a flag `--aptos` to the prover command line for easier debugging, avoiding the CLI. * Disabling a condition for CI because of timeout. * Rebasing --- Cargo.lock | 3 + .../doc/reconfiguration_with_dkg.md | 4 +- .../reconfiguration_with_dkg.spec.move | 5 +- aptos-move/framework/src/prover.rs | 4 +- .../evm/move-to-yul/tests/TestABIStructs.exp | 4 +- third_party/move/move-compiler-v2/Cargo.toml | 2 +- .../move-compiler-v2/src/env_pipeline/mod.rs | 13 +- .../src/env_pipeline/rewrite_target.rs | 206 ++ .../src/env_pipeline/spec_checker.rs | 128 + .../src/env_pipeline/spec_rewriter.rs | 502 ++++ .../move/move-compiler-v2/src/inliner.rs | 382 +-- third_party/move/move-compiler-v2/src/lib.rs | 85 +- .../tests/ability-check/ability_violation.exp | 82 +- .../ability-check/ability_violation.move | 30 +- .../tests/ability-check/globals.exp | 33 - .../tests/ability-transform/by_reference.exp | 2098 ++++++++--------- .../ability-transform/dead_but_borrowed.exp | 140 +- .../foreach_mut_expanded.exp | 1000 ++++---- .../tests/bytecode-generator/assign.exp | 4 - .../bytecode-generator/assign_inline.exp | 31 +- .../tests/bytecode-generator/borrow.exp | 49 +- .../bytecode-generator/borrow_invalid.exp | 2 - .../bytecode-generator/conditional_borrow.exp | 333 ++- .../bytecode-generator/escape_autoref.exp | 15 - .../tests/bytecode-generator/fields.exp | 17 - .../bytecode-generator/fields_invalid.exp | 1 - .../tests/bytecode-generator/globals.exp | 111 +- .../tests/bytecode-generator/if_else.exp | 18 - .../tests/bytecode-generator/inline_specs.exp | 4 - .../tests/bytecode-generator/loop.exp | 3 - .../tests/bytecode-generator/loop_invalid.exp | 2 - .../tests/bytecode-generator/operators.exp | 18 - .../tests/bytecode-generator/pack_order.exp | 42 - .../tests/bytecode-generator/pack_unpack.exp | 9 - .../reference_conversion.exp | 4 - .../bytecode-generator/spec_construct.exp | 3 - .../tests/bytecode-generator/tuple.exp | 9 - .../bytecode-generator/tuple_invalid.exp | 9 - .../v1-commands/break_outside_loop.exp | 3 - .../break_outside_loop_in_else.exp | 1 - .../v1-commands/break_outside_loop_in_if.exp | 7 - .../v1-commands/continue_outside_loop.exp | 3 - .../continue_outside_loop_in_if.exp | 1 - .../v1-typing/global_invalid.exp | 1 - .../tests/bytecode-generator/vector.exp | 15 +- .../tests/checking/abilities/globals.exp | 25 + .../abilities}/globals.move | 0 .../tests/checking/abilities/missing_key.exp | 25 + .../tests/checking/abilities/missing_key.move | 24 + .../checking/access_specifiers/access_ok.exp | 42 - .../checking/control_flow/loop_after_loop.exp | 1 - .../checking/inlining/acquires_error_msg.exp | 2 - .../tests/checking/inlining/bug_11112.exp | 1 - .../tests/checking/inlining/bug_11223.exp | 15 - .../tests/checking/inlining/bug_9717.exp | 11 - .../checking/inlining/bug_9717_looponly.exp | 1 - .../tests/checking/inlining/deep_exp.exp | 18 - .../checking/inlining/double_nesting.exp | 12 - .../inlining/inline_accessing_constant.exp | 6 - .../tests/checking/inlining/lambda.exp | 29 - .../tests/checking/inlining/lambda_cast.exp | 2 - .../tests/checking/inlining/nested_mul.exp | 9 - .../checking/inlining/order_sensitive.exp | 27 - .../checking/inlining/recursive_nesting.exp | 15 - .../checking/inlining/resources_invalid.exp | 6 - .../checking/inlining/shadowing_unused.exp | 4 - .../inlining/shadowing_unused_nodecl.exp | 4 - .../tests/checking/inlining/spec_inlining.exp | 46 +- .../checking/inlining/spec_inlining.move | 6 +- .../checking/inlining/temp_shadowing.exp | 3 - .../tests/checking/inlining/unused_inline.exp | 2 - .../naming/duplicate_acquires_list_item.exp | 2 - .../checking/naming/generics_shadowing.exp | 9 - .../global_builtin_one_type_argument.exp | 1 - .../naming/struct_in_current_module.exp | 9 - .../specs/assert_skipped_for_spec.exp | 6 +- .../specs/clash_move_spec_function.exp | 10 + .../specs/clash_move_spec_function.move | 10 + .../tests/checking/specs/conditions_ok.exp | 7 - .../checking/specs/inline_fun_in_spec.exp | 67 + .../checking/specs/inline_fun_in_spec.move | 33 + .../checking/specs/inline_fun_spec_ok.exp | 3 - .../checking/specs/inline_spec_inference.exp | 1 - .../specs/inline_spec_inference_bitvector.exp | 11 +- .../inline_spec_inference_bitvector.move | 25 +- .../specs/inline_spec_inference_vector.exp | 11 +- .../specs/inline_spec_inference_vector.move | 17 +- .../tests/checking/specs/inline_spec_old.exp | 3 - .../checking/specs/intrinsic_decl_ok.exp | 14 +- .../tests/checking/specs/invariants_err.exp | 47 +- .../tests/checking/specs/invariants_err.move | 52 +- .../tests/checking/specs/lets_ok.exp | 1 - .../checking/specs/move_function_in_spec.exp | 9 - .../specs/move_function_in_spec_err.exp | 10 + ...ec.move => move_function_in_spec_err.move} | 9 +- .../specs/move_function_in_spec_ok.exp | 40 + .../specs/move_function_in_spec_ok.move | 23 + .../tests/checking/specs/schemas_ok.exp | 9 - .../checking/specs/spec_pureness_checks.exp | 76 + .../checking/specs/spec_pureness_checks.move | 54 + .../tests/checking/specs/structs_ok.exp | 3 - .../tests/checking/specs/type_variance_ok.exp | 3 - .../tests/checking/specs/update_field_ok.exp | 1 - .../tests/checking/typing/annotated_types.exp | 1 - .../tests/checking/typing/assign_tuple.exp | 9 - .../tests/checking/typing/assign_tuple_wg.exp | 14 - .../typing/assign_unpack_references.exp | 3 - .../tests/checking/typing/binary_add.exp | 17 +- .../tests/checking/typing/binary_and.exp | 11 +- .../tests/checking/typing/binary_bit_and.exp | 17 +- .../tests/checking/typing/binary_bit_or.exp | 17 +- .../tests/checking/typing/binary_div.exp | 13 +- .../tests/checking/typing/binary_geq.exp | 17 +- .../tests/checking/typing/binary_gt.exp | 17 +- .../tests/checking/typing/binary_leq.exp | 17 +- .../tests/checking/typing/binary_lt.exp | 17 +- .../tests/checking/typing/binary_mod.exp | 13 +- .../tests/checking/typing/binary_mul.exp | 17 +- .../tests/checking/typing/binary_or.exp | 11 +- .../tests/checking/typing/binary_shl.exp | 15 +- .../tests/checking/typing/binary_shr.exp | 15 +- .../tests/checking/typing/binary_sub.exp | 5 +- .../tests/checking/typing/binary_xor.exp | 17 +- .../typing/bind_unpack_references.exp | 3 - .../checking/typing/bind_with_type_annot.exp | 19 +- .../tests/checking/typing/block_empty.exp | 1 - .../checking/typing/block_single_expr.exp | 1 - .../checking/typing/block_with_statements.exp | 21 +- .../tests/checking/typing/borrow_field.exp | 3 - .../checking/typing/borrow_field_chain.exp | 1 - .../typing/borrow_field_complex_root_expr.exp | 1 - .../checking/typing/borrow_field_internal.exp | 4 - .../typing/borrow_field_non_ref_root.exp | 1 - .../tests/checking/typing/borrow_local.exp | 2 - .../checking/typing/borrow_local_temp.exp | 1 - .../typing/borrow_local_temp_resource.exp | 1 - .../tests/checking/typing/break_any_type.exp | 3 - .../checking/typing/break_outside_loop.exp | 3 - .../tests/checking/typing/cast.exp | 84 +- .../typing/conditional_global_operations.exp | 4 - .../typing/constant_all_valid_types.exp | 22 - .../checking/typing/continue_any_type.exp | 3 - .../checking/typing/continue_outside_loop.exp | 1 - .../typing/decl_unpack_references.exp | 3 - .../typing/declare_with_type_annot.exp | 22 +- .../tests/checking/typing/derefrence.exp | 1 - .../checking/typing/derefrence_reference.exp | 2 - .../checking/typing/entry_on_any_vis.exp | 9 - .../tests/checking/typing/eq.exp | 15 +- .../tests/checking/typing/eq_inline.exp | 9 +- .../tests/checking/typing/eq_ref.exp | 3 - .../tests/checking/typing/exp_list.exp | 6 - .../typing/exp_list_resource_drop.exp | 1 - .../tests/checking/typing/explicit_copy.exp | 16 +- .../tests/checking/typing/explicit_move.exp | 1 - .../tests/checking/typing/global_builtins.exp | 2 - .../typing/global_builtins_inferred.exp | 1 - .../typing/global_builtins_script.exp | 4 - .../typing/hex_and_decimal_address.exp | 7 - .../checking/typing/if_branches_subtype.exp | 48 - .../tests/checking/typing/if_condition.exp | 12 +- .../tests/checking/typing/if_default_else.exp | 8 +- .../checking/typing/if_matched_branches.exp | 3 - .../typing/implicit_deref_borrow_field.exp | 3 - .../implicit_deref_borrow_field_chain.exp | 1 - ...t_deref_borrow_field_complex_root_expr.exp | 1 - .../implicit_deref_borrow_field_internal.exp | 4 - ...ef_borrow_field_non_ref_non_local_root.exp | 7 - ...plicit_deref_borrow_field_non_ref_root.exp | 1 - .../tests/checking/typing/large_binop.exp | 3 +- .../tests/checking/typing/loop_body.exp | 50 +- .../checking/typing/loop_result_type.exp | 39 +- .../tests/checking/typing/main_arguments.exp | 3 - .../typing/main_arguments_various_caes.exp | 4 - .../tests/checking/typing/main_call_entry.exp | 6 - .../typing/main_with_type_parameters.exp | 3 - .../typing/module_call_entry_function.exp | 42 - .../module_call_explicit_type_arguments.exp | 5 - .../typing/move_from_type_argument.exp | 1 - .../checking/typing/mutable_eq_and_neq.exp | 13 - .../tests/checking/typing/mutate.exp | 11 - .../checking/typing/mutate_field_internal.exp | 4 - .../checking/typing/mutate_immutable.exp | 1 - .../tests/checking/typing/mutate_resource.exp | 3 - .../tests/checking/typing/neq.exp | 15 +- .../checking/typing/nested_post_process.exp | 2 - .../tests/checking/typing/other_builtins.exp | 10 +- .../tests/checking/typing/pack.exp | 28 +- .../tests/checking/typing/return_any_type.exp | 3 - .../typing/return_type_explicit_exp.exp | 3 - .../checking/typing/return_type_last_exp.exp | 9 - .../checking/typing/seq_ignores_value.exp | 4 - .../tests/checking/typing/shadowing.exp | 88 +- .../tests/checking/typing/spec_block_ok.exp | 3 - .../checking/typing/subtype_annotation.exp | 2 - .../tests/checking/typing/subtype_args.exp | 15 - .../tests/checking/typing/subtype_assign.exp | 2 - .../tests/checking/typing/subtype_bind.exp | 2 - .../tests/checking/typing/subtype_return.exp | 15 - .../typing/type_variable_join_single_pack.exp | 1 - .../type_variable_join_single_unpack.exp | 4 - ...ype_variable_join_single_unpack_assign.exp | 4 - .../type_variable_join_threaded_pack.exp | 10 - .../type_variable_join_threaded_unpack.exp | 14 - ...e_variable_join_threaded_unpack_assign.exp | 14 - .../tests/checking/typing/unary_not.exp | 5 +- .../tests/checking/typing/unit.exp | 8 +- .../checking/typing/unused_lambda_param.exp | 30 +- .../tests/checking/typing/unused_local.exp | 69 +- .../tests/checking/typing/use_local.exp | 16 +- .../tests/checking/typing/values.exp | 1 - .../checking/typing/vector_basic_cases.exp | 15 +- .../tests/checking/typing/while_body.exp | 8 +- .../tests/checking/typing/while_condition.exp | 12 +- .../tests/checking/unused/local_var.exp | 29 +- .../module_call_visibility_friend.exp | 42 - .../tests/file-format-generator/const.exp | 87 +- .../tests/file-format-generator/const.move | 24 +- .../file-format-generator/has_script.exp | 14 +- .../tests/file-format-generator/vector.exp | 94 +- .../tests/folding/constant_values.exp | 18 - .../tests/folding/non_constant_empty_vec.exp | 18 - .../tests/lambda-lifting/basic.exp | 30 - .../tests/lambda-lifting/modify.exp | 29 - .../tests/lambda-lifting/nested.exp | 18 - .../tests/lambda-lifting/pattern.exp | 18 - .../tests/live-var/mut_inline.exp | 547 +++-- .../moved_var_not_simplified.exp | 9 - .../moved_var_not_simplified2.exp | 12 - .../moved_var_not_simplified3.exp | 12 - .../return_borrowed_local_invalid.exp | 4 +- .../always_false_branch.exp | 1 - .../assign_unpack_references.exp | 3 - .../simplifier-elimination/binary_add.exp | 1 - .../bind_with_type_annot.exp | 1 - .../constant_all_valid_types.exp | 22 - .../simplifier-elimination/double_nesting.exp | 12 - .../else_assigns_if_doesnt.exp | 1 - .../if_assigns_else_doesnt.exp | 1 - .../if_assigns_no_else.exp | 1 - .../simplifier-elimination/if_condition.exp | 2 - .../moved_var_not_simplified.exp | 9 - .../moved_var_not_simplified2.exp | 12 - .../recursive_nesting.exp | 15 - .../use_before_assign.exp | 9 - .../use_before_assign_loop.exp | 4 - .../use_before_assign_while.exp | 4 - .../tests/simplifier/bug_11112.exp | 1 - .../tests/simplifier/conditional_borrow.exp | 4 - .../tests/simplifier/deep_exp.exp | 18 - .../simplifier/moved_var_not_simplified.exp | 9 - .../simplifier/moved_var_not_simplified2.exp | 12 - .../tests/simplifier/random.exp | 10 - .../tests/simplifier/simplifier_test1.exp | 2 - .../tests/simplifier/simplifier_test2.exp | 2 - .../tests/simplifier/simplifier_test3.exp | 2 - .../tests/simplifier/simplifier_test4.exp | 8 - .../move/move-compiler-v2/tests/testsuite.rs | 39 +- .../borrow_if_unfoldable.exp | 153 +- .../struct_use_before_assign.exp | 63 +- .../v1-borrow-tests/borrow_if.exp | 159 +- .../v1-borrows/eq_unassigned_local.exp | 41 +- .../variable-coalescing/borrowed_var.exp | 84 +- .../tests/variable-coalescing/conditional.exp | 105 +- .../variable-coalescing/overlapping_vars.exp | 63 +- .../variable-coalescing/reassigned_var.exp | 43 +- .../move-model/bytecode-test-utils/Cargo.toml | 1 + .../move-model/bytecode-test-utils/src/lib.rs | 15 +- third_party/move/move-model/src/ast.rs | 86 +- .../move/move-model/src/builder/builtins.rs | 20 +- .../move-model/src/builder/exp_builder.rs | 222 +- .../move-model/src/builder/model_builder.rs | 53 +- .../move-model/src/builder/module_builder.rs | 469 +--- .../move/move-model/src/exp_rewriter.rs | 102 +- third_party/move/move-model/src/lib.rs | 13 +- third_party/move/move-model/src/model.rs | 210 +- .../move/move-model/src/pureness_checker.rs | 179 ++ third_party/move/move-model/src/ty.rs | 54 +- third_party/move/move-model/src/well_known.rs | 10 +- .../tests/sources/invariants_err.exp | 20 +- .../tests/sources/invariants_err.move | 10 - third_party/move/move-prover/Cargo.toml | 1 + .../boogie-backend/src/spec_translator.rs | 41 +- .../bytecode-pipeline/src/number_operation.rs | 3 +- .../tests/spec_instrumentation/modifies.exp | 39 + .../move-prover/move-docgen/src/docgen.rs | 20 +- third_party/move/move-prover/src/cli.rs | 25 +- third_party/move/move-prover/src/lib.rs | 20 +- .../duplicate_function_declarations.exp | 12 +- .../duplicate_function_declarations.move | 3 +- .../sources/functional/inline-lambda.exp | 24 +- .../sources/functional/inline_fun_simple.exp | 8 +- .../tests/sources/functional/invariants.exp | 16 +- .../tests/sources/functional/invariants.move | 62 +- .../pure_function_call_incorrect.exp | 23 +- third_party/move/move-stdlib/docs/option.md | 182 -- third_party/move/move-stdlib/docs/vector.md | 187 -- third_party/move/scripts/move_pr.sh | 47 +- .../move/tools/move-cli/src/base/prove.rs | 4 +- 299 files changed, 5125 insertions(+), 6557 deletions(-) create mode 100644 third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs create mode 100644 third_party/move/move-compiler-v2/src/env_pipeline/spec_checker.rs create mode 100644 third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs delete mode 100644 third_party/move/move-compiler-v2/tests/ability-check/globals.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/abilities/globals.exp rename third_party/move/move-compiler-v2/tests/{ability-check => checking/abilities}/globals.move (100%) create mode 100644 third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.move delete mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.exp rename third_party/move/move-compiler-v2/tests/checking/specs/{move_function_in_spec.move => move_function_in_spec_err.move} (88%) create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.move create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.move create mode 100644 third_party/move/move-model/src/pureness_checker.rs diff --git a/Cargo.lock b/Cargo.lock index 9acb4cbef6941..c5e093079ba40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10870,6 +10870,7 @@ dependencies = [ "move-symbol-pool", "num 0.4.1", "once_cell", + "petgraph 0.6.4", "serde", ] @@ -11170,6 +11171,7 @@ dependencies = [ "move-binary-format", "move-command-line-common", "move-compiler", + "move-compiler-v2", "move-core-types", "move-docgen", "move-errmapgen", @@ -11318,6 +11320,7 @@ dependencies = [ "codespan-reporting", "move-command-line-common", "move-compiler", + "move-compiler-v2", "move-model", "move-prover-test-utils", "move-stackless-bytecode", diff --git a/aptos-move/framework/aptos-framework/doc/reconfiguration_with_dkg.md b/aptos-move/framework/aptos-framework/doc/reconfiguration_with_dkg.md index 231ce0b060283..f64d57763b192 100644 --- a/aptos-move/framework/aptos-framework/doc/reconfiguration_with_dkg.md +++ b/aptos-move/framework/aptos-framework/doc/reconfiguration_with_dkg.md @@ -164,8 +164,10 @@ Abort if no DKG is in progress. requires chain_status::is_operating(); include stake::ResourceRequirement; include stake::GetReconfigStartTimeRequirement; -include features::spec_periodical_reward_rate_decrease_enabled() ==> staking_config::StakingRewardsConfigEnabledRequirement; +include features::spec_periodical_reward_rate_decrease_enabled( +) ==> staking_config::StakingRewardsConfigEnabledRequirement; aborts_if false; +pragma verify_duration_estimate = 600; diff --git a/aptos-move/framework/aptos-framework/sources/reconfiguration_with_dkg.spec.move b/aptos-move/framework/aptos-framework/sources/reconfiguration_with_dkg.spec.move index fd5709dd53e28..d03da00335adc 100644 --- a/aptos-move/framework/aptos-framework/sources/reconfiguration_with_dkg.spec.move +++ b/aptos-move/framework/aptos-framework/sources/reconfiguration_with_dkg.spec.move @@ -12,8 +12,10 @@ spec aptos_framework::reconfiguration_with_dkg { requires chain_status::is_operating(); include stake::ResourceRequirement; include stake::GetReconfigStartTimeRequirement; - include features::spec_periodical_reward_rate_decrease_enabled() ==> staking_config::StakingRewardsConfigEnabledRequirement; + include features::spec_periodical_reward_rate_decrease_enabled( + ) ==> staking_config::StakingRewardsConfigEnabledRequirement; aborts_if false; + pragma verify_duration_estimate = 600; // TODO: set because of timeout (property proved). } spec finish(account: &signer) { @@ -59,5 +61,4 @@ spec aptos_framework::reconfiguration_with_dkg { requires dkg::has_incomplete_session(); aborts_if false; } - } diff --git a/aptos-move/framework/src/prover.rs b/aptos-move/framework/src/prover.rs index 58be654d76f46..5614c273b435b 100644 --- a/aptos-move/framework/src/prover.rs +++ b/aptos-move/framework/src/prover.rs @@ -123,7 +123,7 @@ impl ProverOptions { ) -> anyhow::Result<()> { let now = Instant::now(); let for_test = self.for_test; - let model = build_model( + let mut model = build_model( dev_mode, package_path, named_addresses, @@ -162,7 +162,7 @@ impl ProverOptions { )], }); let mut writer = StandardStream::stderr(ColorChoice::Auto); - move_prover::run_move_prover_with_model(&model, &mut writer, options, Some(now))?; + move_prover::run_move_prover_with_model(&mut model, &mut writer, options, Some(now))?; Ok(()) } diff --git a/third_party/move/evm/move-to-yul/tests/TestABIStructs.exp b/third_party/move/evm/move-to-yul/tests/TestABIStructs.exp index 36eeeb174da2d..49a3eb0ea4782 100644 --- a/third_party/move/evm/move-to-yul/tests/TestABIStructs.exp +++ b/third_party/move/evm/move-to-yul/tests/TestABIStructs.exp @@ -2446,7 +2446,7 @@ object "test_A2_M_test_abi_String" { case 2 { // label L5 // assert Le($t1, $t4) - // assert forall j: num: Range(0, $t1): ascii::$is_valid_char(Index($t0, j)) + // assert forall j: num: Range(0, $t1): ascii::is_valid_char(Index($t0, j)) // $t6 := <($t1, $t4) $t6 := $Lt(i, $t4) // if ($t6) goto L1 else goto L0 @@ -2474,7 +2474,7 @@ object "test_A2_M_test_abi_String" { case 5 { // label L0 // assert Eq($t1, $t4) - // assert forall j: num: Range(0, $t4): ascii::$is_valid_char(Index($t0, j)) + // assert forall j: num: Range(0, $t4): ascii::is_valid_char(Index($t0, j)) // $t14 := move($t0) $t14 := mload($locals) // $t15 := pack ascii::String($t14) diff --git a/third_party/move/move-compiler-v2/Cargo.toml b/third_party/move/move-compiler-v2/Cargo.toml index 010da0fffa448..3e4c679baddfd 100644 --- a/third_party/move/move-compiler-v2/Cargo.toml +++ b/third_party/move/move-compiler-v2/Cargo.toml @@ -37,7 +37,7 @@ log = { version = "0.4.14", features = ["serde"] } num = "0.4.0" once_cell = "1.7.2" #paste = "1.0.5" -#petgraph = "0.5.1" +petgraph = "0.6.4" serde = { version = "1.0.124", features = ["derive"] } [dev-dependencies] diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/mod.rs b/third_party/move/move-compiler-v2/src/env_pipeline/mod.rs index a8c591459f576..6fc17c75f266b 100644 --- a/third_party/move/move-compiler-v2/src/env_pipeline/mod.rs +++ b/third_party/move/move-compiler-v2/src/env_pipeline/mod.rs @@ -6,11 +6,14 @@ // TODO: move all other `&mut GlobalEnv` processors into this module. -use log::debug; +use log::trace; use move_model::model::GlobalEnv; use std::io::Write; pub mod lambda_lifter; +pub mod rewrite_target; +pub mod spec_checker; +pub mod spec_rewriter; /// Represents a pipeline of processors working on the global environment. #[derive(Default)] @@ -32,10 +35,10 @@ impl<'a> EnvProcessorPipeline<'a> { /// Runs the pipeline. Running will be ended if any of the steps produces an error. /// The function returns true if all steps succeeded without errors. pub fn run(&self, env: &mut GlobalEnv) -> bool { - debug!("before env processor pipeline: {}", env.dump_env()); + trace!("before env processor pipeline: {}", env.dump_env()); for (name, proc) in &self.processors { proc(env); - debug!("after env processor {}", name); + trace!("after env processor {}", name); if env.has_errors() { return false; } @@ -47,13 +50,13 @@ impl<'a> EnvProcessorPipeline<'a> { /// only. pub fn run_and_record(&self, env: &mut GlobalEnv, w: &mut impl Write) -> anyhow::Result { let msg = format!("before env processor pipeline:\n{}\n", env.dump_env()); - debug!("{}", msg); + trace!("{}", msg); writeln!(w, "// -- Model dump {}", msg)?; for (name, proc) in &self.processors { proc(env); if !env.has_errors() { let msg = format!("after env processor {}:\n{}\n", name, env.dump_env()); - debug!("{}", msg); + trace!("{}", msg); writeln!(w, "// -- Model dump {}", msg)?; } else { return Ok(false); 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 new file mode 100644 index 0000000000000..2851f5c2b79c3 --- /dev/null +++ b/third_party/move/move-compiler-v2/src/env_pipeline/rewrite_target.rs @@ -0,0 +1,206 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use move_model::{ + ast::{Exp, Spec, SpecBlockTarget}, + model::{FunId, GlobalEnv, NodeId, QualifiedId, SpecFunId}, +}; +use std::{ + collections::{BTreeMap, BTreeSet}, + mem, +}; + +/// Represents a target for rewriting. +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] +pub enum RewriteTarget { + /// A Move function + MoveFun(QualifiedId), + /// A specification function + SpecFun(QualifiedId), + /// A specification block, which can be attached to a Move function, struct, or module. + SpecBlock(SpecBlockTarget), +} + +/// Represents the state of a rewriting target. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum RewriteState { + /// The target has not been changed + Unchanged, + /// The definition of a Move or spec function has changed + Def(Exp), + /// A specification block has changed. + Spec(Spec), + /// The target is 'abstract', i.e. does have a definition. + Abstract, +} + +/// Scope for collecting targets. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] +pub enum RewritingScope { + /// Including only targets for which `module.is_target()` is true. + CompilationTarget, + /// Include everything. + Everything, +} + +/// Represents a set of rewriting targets in the given state. +#[derive(Clone)] +pub struct RewriteTargets { + pub targets: BTreeMap, +} + +impl RewriteTargets { + /// Create a new set of rewrite targets, collecting them as specified by `scope`. + /// Those targets are initially associated with `Unchanged` state. + pub fn create(env: &GlobalEnv, scope: RewritingScope) -> Self { + let mut targets = vec![]; + let add_spec = + |targets: &mut Vec, sb_target: SpecBlockTarget, spec: &Spec| { + if !spec.is_empty() { + targets.push(RewriteTarget::SpecBlock(sb_target)) + } + }; + for module in env.get_modules() { + if scope == RewritingScope::Everything || module.is_target() { + for func in module.get_functions() { + let id = func.get_qualified_id(); + targets.push(RewriteTarget::MoveFun(id)); + add_spec( + &mut targets, + SpecBlockTarget::Function(id.module_id, id.id), + &func.get_spec(), + ); + } + for (spec_fun_id, _) in module.get_spec_funs() { + targets.push(RewriteTarget::SpecFun( + module.get_id().qualified(*spec_fun_id), + )); + } + for struct_env in module.get_structs() { + add_spec( + &mut targets, + SpecBlockTarget::Struct(module.get_id(), struct_env.get_id()), + &struct_env.get_spec(), + ) + } + if !module.get_spec().is_empty() { + add_spec( + &mut targets, + SpecBlockTarget::Module(module.get_id()), + &module.get_spec(), + ); + } + } + } + Self { + targets: targets + .into_iter() + .map(|target| (target, RewriteState::Unchanged)) + .collect(), + } + } + + /// Filters the targets according to the predicate. + pub fn filter(&mut self, pred: impl Fn(&RewriteTarget, &RewriteState) -> bool) { + self.targets = mem::take(&mut self.targets) + .into_iter() + .filter(|(t, s)| pred(t, s)) + .collect(); + } + + /// Iterates all targets. + pub fn iter(&self) -> impl Iterator + '_ { + self.targets.iter() + } + + /// Returns an iteration of the target keys. + pub fn keys(&self) -> impl Iterator + '_ { + self.targets.keys().cloned() + } + + /// Adds a new rewrite target in state `Unchanged` if it doesn't exist yet. Returns + /// a boolean whether the entry is new and a mutable reference to the state. + pub fn entry(&mut self, target: RewriteTarget) -> (bool, &mut RewriteState) { + let mut is_new = false; + let state = self.targets.entry(target).or_insert_with(|| { + is_new = true; + RewriteState::Unchanged + }); + (is_new, state) + } + + /// Gets the current state of the target. + pub fn state(&self, target: &RewriteTarget) -> &RewriteState { + self.targets.get(target).expect("state defined") + } + + /// Gets the mutable current state of the target. + pub fn state_mut(&mut self, target: &RewriteTarget) -> &mut RewriteState { + self.targets.get_mut(target).expect("state defined") + } + + /// Updates the global env based on the current state. This consumes + /// the rewrite targets. + pub fn write_to_env(self, env: &mut GlobalEnv) { + for (target, state) in self.targets { + use RewriteState::*; + use RewriteTarget::*; + match (target, state) { + (_, Unchanged) => {}, + (MoveFun(fnid), Def(def)) => env.set_function_def(fnid, def), + (SpecFun(fnid), Def(def)) => env.get_spec_fun_mut(fnid).body = Some(def), + (SpecBlock(sb_target), Spec(spec)) => { + *env.get_spec_block_mut(&sb_target) = spec; + }, + _ => panic!("unexpected rewrite target and result combination"), + } + } + } +} + +impl RewriteTarget { + /// Gets the call sites for the target. + pub fn called_funs_with_call_sites( + &self, + env: &GlobalEnv, + ) -> BTreeMap, BTreeSet> { + use RewriteTarget::*; + match self { + MoveFun(id) => env + .get_function(*id) + .get_def() + .map(|e| e.called_funs_with_callsites()) + .unwrap_or_default(), + SpecFun(id) => env + .get_spec_fun(*id) + .body + .as_ref() + .map(|e| e.called_funs_with_callsites()) + .unwrap_or_default(), + SpecBlock(target) => { + let spec = env.get_spec_block(target); + spec.called_funs_with_callsites() + }, + } + } + + /// Get the environment state of this target in form of a RewriteState. + pub fn get_env_state(&self, env: &GlobalEnv) -> RewriteState { + use RewriteState::*; + use RewriteTarget::*; + match self { + MoveFun(fid) => env + .get_function(*fid) + .get_def() + .map(|e| Def(e.clone())) + .unwrap_or(Abstract), + SpecFun(fid) => env + .get_spec_fun(*fid) + .body + .clone() + .map(Def) + .unwrap_or(Abstract), + SpecBlock(sb_target) => Spec(env.get_spec_block(sb_target).clone()), + } + } +} diff --git a/third_party/move/move-compiler-v2/src/env_pipeline/spec_checker.rs b/third_party/move/move-compiler-v2/src/env_pipeline/spec_checker.rs new file mode 100644 index 0000000000000..e400eac2c6cde --- /dev/null +++ b/third_party/move/move-compiler-v2/src/env_pipeline/spec_checker.rs @@ -0,0 +1,128 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! The spec checker runs over the specifications of the target modules: +//! +//! - It checks whether the constructs they use are pure. If a specification +//! expression calls a Move function it checks that for pureness as well. +//! - It checks whether struct invariants do not depend on global state. + +use crate::env_pipeline::rewrite_target::{ + RewriteState, RewriteTarget, RewriteTargets, RewritingScope, +}; +use codespan_reporting::diagnostic::Severity; +use log::info; +use move_model::{ + ast::{Exp, Spec}, + model::{FunId, GlobalEnv, NodeId, QualifiedId}, + pureness_checker::{FunctionPurenessChecker, FunctionPurenessCheckerMode}, +}; + +pub fn run_spec_checker(env: &GlobalEnv) { + info!("checking specifications"); + + // Targets are all spec functions and spec blocks, as well as functions to + // process inline specs. + let mut targets = RewriteTargets::create(env, RewritingScope::CompilationTarget); + targets.filter(|target, _| { + matches!( + target, + RewriteTarget::SpecFun(_) | RewriteTarget::SpecBlock(_) | RewriteTarget::MoveFun(_) + ) + }); + + // Walk over those targets and check them for pureness. + for target in targets.keys() { + match (target.clone(), target.get_env_state(env)) { + (RewriteTarget::MoveFun(_), RewriteState::Def(exp)) => { + exp.visit_inline_specs(&mut |s| { + check_spec(env, s); + true + }) + }, + (RewriteTarget::SpecFun(_), RewriteState::Def(exp)) => check_exp(env, &exp), + (RewriteTarget::SpecBlock(_), RewriteState::Spec(spec)) => check_spec(env, &spec), + _ => {}, + } + } +} + +fn check_exp(env: &GlobalEnv, exp: &Exp) { + let mut error_reported = false; + let mut checker = FunctionPurenessChecker::new( + FunctionPurenessCheckerMode::Specification, + |node_id, msg, call_chain| report_error(env, &mut error_reported, node_id, msg, call_chain), + ); + checker.check_exp(env, exp); +} + +fn check_spec(env: &GlobalEnv, spec: &Spec) { + let mut error_reported = false; + let mut checker = FunctionPurenessChecker::new( + FunctionPurenessCheckerMode::Specification, + |node_id, msg, call_chain| report_error(env, &mut error_reported, node_id, msg, call_chain), + ); + checker.check_spec(env, spec); +} + +fn report_error( + env: &GlobalEnv, + error_reported: &mut bool, + id: NodeId, + msg: &str, + call_chain: &[(QualifiedId, NodeId)], +) { + // We report the first error only because otherwise the error messages can be + // overwhelming, if the user e.g. accidentally calls a complex system function. + if *error_reported { + return; + } + // The first call in call_chain is the one from the specification function to + // a Move function. We take this as the primary anchor for the error message + let print_fun = |f: QualifiedId| env.get_function(f).get_name_str(); + if call_chain.is_empty() { + // Direct report + env.diag_with_primary_and_labels( + Severity::Error, + &env.get_node_loc(id), + "specification expression cannot use impure construct", + msg, + vec![], + ); + } else { + let (first_fun, first_id) = call_chain[0]; + let mut call_chain_info = vec![]; + // First print the sequence of calls leading us to the issue + for i in 1..call_chain.len() { + let previous_fun = print_fun(call_chain[i - 1].0); + let this_fun = print_fun(call_chain[1].0); + let this_loc = env.get_node_loc(call_chain[1].1); + call_chain_info.push(( + this_loc, + format!( + "transitively calling `{}` from `{}` here", + this_fun, previous_fun + ), + )) + } + // Next print the particular issue detected + let last_fun = call_chain.last().unwrap().0; + call_chain_info.push(( + env.get_node_loc(id), + format!("in `{}`: {}", print_fun(last_fun), msg), + )); + + env.diag_with_primary_and_labels( + Severity::Error, + &env.get_node_loc(first_id), + &format!( + "specification expression cannot call impure \ + Move function `{}`", + env.get_function(first_fun).get_name_str() + ), + "called here", + call_chain_info, + ); + } + *error_reported = true; +} 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 new file mode 100644 index 0000000000000..269e3c83b9e2f --- /dev/null +++ b/third_party/move/move-compiler-v2/src/env_pipeline/spec_rewriter.rs @@ -0,0 +1,502 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! The spec rewriter runs on the whole model after inlining and after check for pureness +//! and does the following: +//! +//! - For every transitively used Move function in specs, it derives +//! a spec function version of it. +//! - It rewrites all specification expressions to call the derived spec +//! function instead of the Move function. +//! - It also rewrites expression to replace Move constructs with spec +//! constructs where possible. This includes replacing references +//! with values. This transformation assumes that expressions +//! are already checked for pureness. +//! - For all spec functions (including the derived ones) it computes +//! transitive memory usage and callee functions. +//! - It checks that data invariants do not depend on memory, and flags +//! errors if not. This can only be done after transitive memory +//! usage is known. +//! - It collects all global invariants and attaches them, together +//! with their memory usage, to the model. + +use crate::env_pipeline::rewrite_target::{ + RewriteState, RewriteTarget, RewriteTargets, RewritingScope, +}; +use itertools::Itertools; +use log::info; +use move_model::{ + ast::{ConditionKind, Exp, ExpData, GlobalInvariant, Operation, SpecFunDecl}, + exp_rewriter::ExpRewriterFunctions, + model::{FunId, GlobalEnv, NodeId, Parameter, QualifiedId, SpecFunId, StructEnv}, + symbol::Symbol, + ty::ReferenceKind, +}; +use petgraph::prelude::DiGraphMap; +use std::{ + cell::RefCell, + collections::{BTreeMap, BTreeSet}, +}; + +pub fn run_spec_rewriter(env: &mut GlobalEnv) { + info!("rewriting specifications"); + + // Collect all spec blocks and spec functions in the whole program, plus + // functions in compilation scope. For the later we need to process + // inline spec blocks. + // TODO: we may want to optimize this to only rewrite specs involved in + // a verification problem, but we need to have a precise definition + // what this entails. For example, pre/post conditions need to be present + // only if the function spec is marked as opaque. + let mut targets = RewriteTargets::create(env, RewritingScope::Everything); + targets.filter(|target, _| match target { + RewriteTarget::MoveFun(fid) => { + let fun = env.get_function(*fid); + fun.module_env.is_target() && !fun.is_inline() && !fun.is_native() + }, + RewriteTarget::SpecFun(fid) => { + let fun = env.get_spec_fun(*fid); + !fun.is_native + }, + RewriteTarget::SpecBlock(_) => true, + }); + + // Identify the Move functions transitively called by those targets. They need to be + // converted to spec functions. + let mut called_funs = BTreeSet::new(); + for target in targets.keys() { + let callees: BTreeSet<_> = match target { + RewriteTarget::MoveFun(_) => { + 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()); + true // keep going + }); + spec_callees + } else { + BTreeSet::new() + } + }, + RewriteTarget::SpecFun(_) | RewriteTarget::SpecBlock(_) => target + .called_funs_with_call_sites(env) + .into_keys() + .collect(), + }; + for callee in callees { + called_funs.insert(callee); + let mut transitive = env + .get_function(callee) + .get_transitive_closure_of_called_functions(); + called_funs.append(&mut transitive); + } + } + + // For compatibility reasons with the v1 way how to compile spec + // blocks of inline functions, we also need to add all 'lambda' + // lifted functions. + + // Derive spec functions for all called Move functions, + // building a mapping between function ids. Also add + // those new spec functions to `targets` for subsequent + // processing. + let mut function_mapping = BTreeMap::new(); + for fun_id in called_funs { + let spec_fun_id = derive_spec_fun(env, fun_id); + function_mapping.insert(fun_id, spec_fun_id); + // Add new spec fun to targets for later processing + targets.entry(RewriteTarget::SpecFun(spec_fun_id)); + // Mark spec fun to be used in environment + env.add_used_spec_fun(spec_fun_id) + } + + // Based on the mapping above, now visit all targets and convert them. + for target in targets.keys().collect_vec() { + use RewriteState::*; + use RewriteTarget::*; + let get_param_names = + |params: &[Parameter]| params.iter().map(|Parameter(name, ..)| *name).collect_vec(); + match (&target, target.get_env_state(env)) { + (MoveFun(_), Def(exp)) => { + let mut converter = SpecConverter::new(env, &function_mapping, false); + let new_exp = converter.rewrite_exp(exp.clone()); + if !ExpData::ptr_eq(&new_exp, &exp) { + *targets.state_mut(&target) = Def(new_exp) + } + }, + (SpecFun(id), Def(exp)) => { + let mut converter = SpecConverter::new(env, &function_mapping, true) + .symbolized_parameters(get_param_names(&env.get_spec_fun(*id).params)); + let new_exp = converter.rewrite_exp(exp.clone()); + if !ExpData::ptr_eq(&new_exp, &exp) { + *targets.state_mut(&target) = Def(new_exp) + } + }, + (SpecBlock(sb_target), Spec(spec)) => { + let mut converter = SpecConverter::new(env, &function_mapping, true); + let (changed, new_spec) = converter.rewrite_spec_descent(sb_target, &spec); + if changed { + *targets.state_mut(&target) = Spec(new_spec) + } + }, + _ => {}, + } + } + targets.write_to_env(env); + + // Now that all functions are defined, compute transitive callee and used memory. + // Since specification functions can be recursive we compute the strongly-connected + // components first and then process each in bottom-up order. + let mut graph: DiGraphMap, ()> = DiGraphMap::new(); + let spec_funs = env + .get_modules() + .flat_map(|m| { + m.get_spec_funs() + .map(|(id, _)| m.get_id().qualified(*id)) + .collect_vec() + }) + .collect_vec(); + for qid in spec_funs { + graph.add_node(qid); + let (initial_callees, initial_usage) = if let Some(def) = &env.get_spec_fun(qid).body { + let callees = def.called_spec_funs(env); + for callee in &callees { + graph.add_edge(qid, callee.to_qualified_id(), ()); + } + (callees, def.directly_used_memory(env)) + } else { + Default::default() + }; + let decl_mut = env.get_spec_fun_mut(qid); + (decl_mut.callees, decl_mut.used_memory) = (initial_callees, initial_usage); + } + for scc in petgraph::algo::kosaraju_scc(&graph) { + // Within each cycle, the transitive usage is the union of the transitive + // usage of each member. + let mut transitive_callees = BTreeSet::new(); + let mut transitive_usage = BTreeSet::new(); + for qid in &scc { + let decl = env.get_spec_fun(*qid); + // Add direct usage. + transitive_callees.extend(decl.callees.iter().cloned()); + transitive_usage.extend(decl.used_memory.iter().cloned()); + // Add indirect usage + for callee in &decl.callees { + let decl = env.get_spec_fun(callee.to_qualified_id()); + transitive_callees.extend( + decl.callees + .iter() + .map(|id| id.clone().instantiate(&callee.inst)), + ); + transitive_usage.extend( + decl.used_memory + .iter() + .map(|mem| mem.clone().instantiate(&callee.inst)), + ); + } + } + // Store result back + for qid in scc { + let decl_mut = env.get_spec_fun_mut(qid); + decl_mut.callees = transitive_callees.clone(); + decl_mut.used_memory = transitive_usage.clone(); + } + } + + // Last, process invariants + for module in env.get_modules() { + if module.is_target() { + for str in module.get_structs() { + check_data_invariants(&str) + } + } + } + collect_global_invariants_to_env(env) +} + +// ------------------------------------------------------------------------------------------- +// Deriving Specification Functions + +// Derive a specification function from a Move function. Initially the body is the +// original one, not yet converted to the specification representation. +fn derive_spec_fun(env: &mut GlobalEnv, fun_id: QualifiedId) -> QualifiedId { + let fun = env.get_function(fun_id); + let (is_native, body) = if fun.is_native() { + (true, None) + } else { + let exp = fun.get_def().expect("function body").clone(); + (false, Some(exp)) + }; + + // For historical reasons, those names are prefixed with `$` even though there + // is no name clash allowed. + let name = env + .symbol_pool() + .make(&format!("${}", fun.get_name().display(env.symbol_pool()))); + // Eliminate references in parameters and result type + let params = fun + .get_parameters() + .into_iter() + .map(|Parameter(sym, ty, loc)| Parameter(sym, ty.skip_reference().clone(), loc)) + .collect(); + let result_type = fun.get_result_type().skip_reference().clone(); + + let decl = SpecFunDecl { + loc: fun.get_loc(), + name, + type_params: fun.get_type_parameters(), + params, + context_params: None, + result_type, + used_memory: BTreeSet::new(), + uninterpreted: false, + is_move_fun: true, + is_native, + body, + callees: BTreeSet::new(), + is_recursive: RefCell::new(None), + }; + env.add_spec_function_def(fun_id.module_id, decl) +} + +// ------------------------------------------------------------------------------------------- +// Expressions Conversion + +/// The expression converter takes a Move expression and converts it to a +/// specification expression. It expects the expression to be checked to be pure. +struct SpecConverter<'a> { + env: &'a GlobalEnv, + /// Whether we are in a specification expression. Conversion applies only if. + in_spec: bool, + /// The mapping from Move function to spec function ids. + function_mapping: &'a BTreeMap, QualifiedId>, + /// If non-empty, Temporary expressions should be mapped to symbolic LocalVar + /// expressions. This is the convention for specification function parameters. + symbolized_parameters: Vec, + /// NodeIds which are exempted from stripping references. For compatibility + /// reasons nodes which fetch temporaries should not be stripped as the reference + /// info is needed for correct treatment of the `old(..)` expression. + reference_strip_exempted: BTreeSet, +} + +impl<'a> SpecConverter<'a> { + fn new( + env: &'a GlobalEnv, + function_mapping: &'a BTreeMap, QualifiedId>, + in_spec: bool, + ) -> Self { + Self { + env, + in_spec, + function_mapping, + symbolized_parameters: vec![], + reference_strip_exempted: Default::default(), + } + } + + fn symbolized_parameters(self, symbolized_parameters: Vec) -> Self { + Self { + symbolized_parameters, + ..self + } + } +} + +impl<'a> ExpRewriterFunctions for SpecConverter<'a> { + fn rewrite_exp(&mut self, exp: Exp) -> Exp { + use ExpData::*; + use Operation::*; + if !self.in_spec { + // If not in spec mode, check whether we need to switch to it, + // and descent + if matches!(exp.as_ref(), ExpData::SpecBlock(..)) { + self.in_spec = true; + let result = self.rewrite_exp_descent(exp); + self.in_spec = false; + result + } else { + self.rewrite_exp_descent(exp) + } + } else { + // Simplification which need to be done before descent + let exp = match exp.as_ref() { + IfElse(id, _, if_true, if_false) + if matches!(if_true.as_ref(), Call(_, Tuple, _)) + && matches!(if_false.as_ref(), Call(_, Abort, _)) => + { + // The code pattern produced by an `assert!`: `if (c) () else abort`. + // Reduce to unit + Call(*id, Tuple, vec![]).into_exp() + }, + Temporary(id, _) => { + self.reference_strip_exempted.insert(*id); + exp + }, + _ => exp, + }; + + let exp = self.rewrite_exp_descent(exp); + + // Simplification after descent + match exp.as_ref() { + Temporary(id, idx) => { + // For specification functions, parameters are represented as LocalVar, + // so apply mapping if present. + if let Some(sym) = self.symbolized_parameters.get(*idx) { + LocalVar(*id, *sym).into_exp() + } else { + exp.clone() + } + }, + Call(id, BorrowGlobal(ReferenceKind::Immutable), args) => { + // Map borrow_global to specification global + Call(*id, Global(None), args.clone()).into_exp() + }, + Call(_, Borrow(_), args) | Call(_, Deref, args) => { + // Skip local borrow + args[0].clone() + }, + Call(id, MoveFunction(mid, fid), args) => { + // Rewrite to associated spec function + let spec_fun_id = self + .function_mapping + .get(&mid.qualified(*fid)) + .unwrap_or_else(|| { + panic!( + "associated spec fun for {}", + self.env.get_function(mid.qualified(*fid)).get_name_str() + ) + }); + + Call( + *id, + SpecFunction(spec_fun_id.module_id, spec_fun_id.id, None), + args.clone(), + ) + .into_exp() + }, + // Deal with removing various occurrences of Abort and spec blocks + Call(id, Abort, _) | SpecBlock(id, ..) => { + // Replace direct call by unit + Call(*id, Tuple, vec![]).into_exp() + }, + IfElse(id, _, if_true, if_false) + if matches!(if_true.as_ref(), Call(_, Tuple, _)) + && matches!(if_false.as_ref(), Call(_, Abort, _)) => + { + // The code pattern produced by an `assert!`: `if (c) () else abort`. + // Reduce to unit as well + Call(*id, Tuple, vec![]).into_exp() + }, + Sequence(id, exps) => { + // Remove aborts, units, and spec blocks + let mut reduced_exps = exps + .iter() + .take(exps.len() - 1) + .flat_map(|e| { + if matches!( + e.as_ref(), + SpecBlock(..) | Call(_, Abort, _) | Call(_, Tuple, _) + ) { + None + } else { + Some(e.clone()) + } + }) + .collect_vec(); + reduced_exps.push(exps.last().unwrap().clone()); + if reduced_exps.len() != exps.len() { + if reduced_exps.len() == 1 { + reduced_exps.pop().unwrap() + } else { + Sequence(*id, reduced_exps).into_exp() + } + } else { + exp.clone() + } + }, + _ => exp.clone(), + } + } + } + + fn rewrite_node_id(&mut self, id: NodeId) -> Option { + if !self.in_spec || self.reference_strip_exempted.contains(&id) { + // Skip the processing below + return None; + } + if let Some(new_ty) = self + .env + .get_node_type_opt(id) + .map(|ty| ty.skip_reference().clone()) + { + let new_id = self.env.new_node(self.env.get_node_loc(id), new_ty); + if let Some(new_inst) = self.env.get_node_instantiation_opt(id).map(|inst| { + inst.into_iter() + .map(|ty| ty.skip_reference().clone()) + .collect_vec() + }) { + self.env.set_node_instantiation(new_id, new_inst); + } + Some(new_id) + } else { + None + } + } +} + +// ------------------------------------------------------------------------------------------- +// Processing Invariants + +fn collect_global_invariants_to_env(env: &mut GlobalEnv) { + let mut invariants = vec![]; + for module_env in env.get_modules() { + for cond in &module_env.get_spec().conditions { + if matches!( + cond.kind, + ConditionKind::GlobalInvariant(..) | ConditionKind::GlobalInvariantUpdate(..) + ) { + let id = env.new_global_id(); + invariants.push(GlobalInvariant { + id, + loc: cond.loc.clone(), + kind: cond.kind.clone(), + mem_usage: cond + .exp + .used_memory(env) + .into_iter() + .map(|(mem, _)| mem.clone()) + .collect(), + declaring_module: module_env.get_id(), + cond: cond.exp.clone(), + properties: cond.properties.clone(), + }); + } + } + } + for invariant in invariants { + env.add_global_invariant(invariant) + } +} + +fn check_data_invariants(struct_env: &StructEnv) { + let env = struct_env.module_env.env; + for cond in &struct_env.get_spec().conditions { + if matches!(cond.kind, ConditionKind::StructInvariant) { + let usage = cond.exp.used_memory(env); + if !usage.is_empty() { + env.error( + &cond.loc, + &format!( + "data invariants cannot depend on global state \ + but found dependency to `{}`", + usage + .into_iter() + .map(|(sid, _)| env.display(&sid).to_string()) + .join(",") + ), + ) + } + } + } +} diff --git a/third_party/move/move-compiler-v2/src/inliner.rs b/third_party/move/move-compiler-v2/src/inliner.rs index 9ec37cf047661..fdc62aa217928 100644 --- a/third_party/move/move-compiler-v2/src/inliner.rs +++ b/third_party/move/move-compiler-v2/src/inliner.rs @@ -1,46 +1,49 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -/// Inlining Overview: -/// - We visit function calling inline functions reachable from compilation targets in a bottom-up -/// fashion, storing rewritten functions in a map to simplify further processing. -/// - Change to the program happens at the end. -/// -/// Summary of structs/impls in this file. Note that these duplicate comments in the body of this file, -/// and ideally should be updated if those are changed significantly. -/// - function `run_inlining` is the main entry point for the inlining pass -/// -/// - struct `Inliner` -/// - holds the map recording function bodies which are rewritten due to inlining so that we don't -/// need to modify the program until the end. -/// - `do_inlining_in` function is the entry point for each function needing inlining. -/// -/// - struct `OuterInlinerRewriter` uses trait `ExpRewriterFunctions` to rewrite each call in the -/// target. -/// -/// - struct `InlinedRewriter` rewrites a call to an inlined function -/// - `inline_call` is the external entry point for rewriting a call to an inline function. -/// -/// - `construct_inlined_call_expression` is a helper to build the `Block` expression corresponding -/// to { let params=actuals; body } used for both lambda inlining and inline function inlining. -/// -/// - struct `InlinedRewriter` uses trait `ExpRewriterFunctions` to rewrite the inlined function -/// body. -/// - `rewrite_exp` is the entry point to rewrite the body of an inline function. -/// -/// - struct ShadowStack implements the free variable shadowing stack: -/// For a given set of "free" variables, the `ShadowStack` tracks which variables are -/// still directly visible, and which variables have been hidden by local variable -/// declarations with the same symbol. In the latter case, the ShadowStack provides -/// a "shadow" symbol which can be used in place of the original. -/// -/// - TODO(10858): add an anchor AST node so we can implement `Return` for inline functions and -/// `Lambda`. +//! Inlining Overview: +//! - We visit function calling inline functions reachable from compilation targets in a bottom-up +//! fashion, storing rewritten functions in a map to simplify further processing. +//! - Change to the program happens at the end. +//! +//! Summary of structs/impls in this file. Note that these duplicate comments in the body of this file, +//! and ideally should be updated if those are changed significantly. +//! - function `run_inlining` is the main entry point for the inlining pass +//! +//! - struct `Inliner` +//! - holds the map recording function bodies which are rewritten due to inlining so that we don't +//! need to modify the program until the end. +//! - `do_inlining_in` function is the entry point for each function needing inlining. +//! +//! - struct `OuterInlinerRewriter` uses trait `ExpRewriterFunctions` to rewrite each call in the +//! target. +//! +//! - struct `InlinedRewriter` rewrites a call to an inlined function +//! - `inline_call` is the external entry point for rewriting a call to an inline function. +//! +//! - `construct_inlined_call_expression` is a helper to build the `Block` expression corresponding +//! to { let params=actuals; body } used for both lambda inlining and inline function inlining. +//! +//! - struct `InlinedRewriter` uses trait `ExpRewriterFunctions` to rewrite the inlined function +//! body. +//! - `rewrite_exp` is the entry point to rewrite the body of an inline function. +//! +//! - struct ShadowStack implements the free variable shadowing stack: +//! For a given set of "free" variables, the `ShadowStack` tracks which variables are +//! still directly visible, and which variables have been hidden by local variable +//! declarations with the same symbol. In the latter case, the ShadowStack provides +//! a "shadow" symbol which can be used in place of the original. +//! +//! - TODO(10858): add an anchor AST node so we can implement `Return` for inline functions and +//! `Lambda`. + +use crate::env_pipeline::rewrite_target::{ + RewriteState, RewriteTarget, RewriteTargets, RewritingScope, +}; use codespan_reporting::diagnostic::Severity; -use itertools::chain; use log::{debug, trace}; use move_model::{ - ast::{Exp, ExpData, Operation, Pattern, TempIndex}, + ast::{Exp, ExpData, Operation, Pattern, Spec, SpecBlockTarget, TempIndex}, exp_rewriter::ExpRewriterFunctions, model::{FunId, GlobalEnv, Loc, NodeId, Parameter, QualifiedId}, symbol::Symbol, @@ -55,142 +58,150 @@ use std::{ }; type QualifiedFunId = QualifiedId; -type CallSiteLocations = BTreeMap<(QualifiedFunId, QualifiedFunId), BTreeSet>; +type CallSiteLocations = BTreeMap<(RewriteTarget, QualifiedFunId), BTreeSet>; // ====================================================================================== // Entry /// Run inlining on current program's AST. For each function which is target of the compilation, /// visit that function body and inline any calls to functions marked as "inline". -pub fn run_inlining(env: &mut GlobalEnv) { +pub fn run_inlining(env: &mut GlobalEnv, scope: RewritingScope, keep_inline_functions: bool) { debug!("Inlining"); // Get non-inline function roots for running inlining. // Also generate an error for any target inline functions lacking a body to inline. - let mut todo = get_targets(env); + let mut targets = RewriteTargets::create(env, scope); + filter_targets(env, &mut targets); + let mut todo: BTreeSet<_> = targets.keys().collect(); // Only look for inlining sites if we have targets to inline into. if !todo.is_empty() { // Recursively find callees of each target with a function body. - // The call graph reachable from targets, represented by a map from each function to the set + // The call graph reachable from targets, represented by a map from each target to the set // of functions it calls. The domain is limited to functions with function bodies. - let mut call_graph: BTreeMap> = BTreeMap::new(); + let mut call_graph: BTreeMap> = BTreeMap::new(); // For each function `caller` calling an inline function `callee`, we record the set of all // call sites where `caller` calls `callee` (for error messages). let mut inline_function_call_site_locations: CallSiteLocations = CallSiteLocations::new(); // Update call_graph and inline_function_call_site_locations for all reachable calls. - let mut visited_functions = BTreeSet::new(); - while let Some(id) = todo.pop_first() { - if visited_functions.insert(id) { - if let Some(def) = env.get_function(id).get_def() { - let callees_with_sites = def.called_funs_with_callsites(); - for (callee, sites) in callees_with_sites { - todo.insert(callee); - call_graph.entry(id).or_default().insert(callee); - if env.get_function(callee).is_inline() { - inline_function_call_site_locations.insert((id, callee), sites); - } + 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); + for (callee, sites) in callees_with_sites { + todo.insert(RewriteTarget::MoveFun(callee)); + targets.entry(RewriteTarget::MoveFun(callee)); + call_graph.entry(target.clone()).or_default().insert(callee); + if env.get_function(callee).is_inline() { + inline_function_call_site_locations.insert((target.clone(), callee), sites); } } } } - // Get a list of all reachable functions calling inline functions, in bottom-up order. + // Get a list of all reachable targets calling inline functions, in bottom-up order. // If there are any cycles, this call displays an error to the user and returns None. - if let Ok(functions_needing_inlining) = functions_needing_inlining_in_order( - env, - &call_graph, - inline_function_call_site_locations, - ) { + if let Ok(targets_needing_inlining) = + targets_needing_inlining_in_order(env, &call_graph, inline_function_call_site_locations) + { // We inline functions bottom-up, so that any inline function which itself has calls to // inline functions has already had its stuff inlined. - let mut inliner = Inliner::new(env); - for fid in functions_needing_inlining.iter() { - inliner.do_inlining_in(*fid); + let mut inliner = Inliner::new(env, targets); + for target in targets_needing_inlining.into_iter() { + inliner.do_inlining_in(target); } - // Now that all inlining finished, actually update function bodies in env. - for (fun_id, funexpr_after_inlining) in inliner.funexprs_after_inlining { - if let Some(changed_funexpr) = funexpr_after_inlining { - env.set_function_def(fun_id, changed_funexpr) - } - } + // Now that all inlining finished, actually update definitions in env. + inliner.inline_targets.write_to_env(env); } } // Delete all inline functions with bodies from the program rep, even if none were inlined, // since (1) they are no longer needed, and (2) they may have code constructs that codegen can't // deal with. - - // First construct a list of functions to remove. - let mut inline_funs = BTreeSet::new(); - for module in env.get_modules() { - for func in module.get_functions() { - let id = func.get_qualified_id(); - if func.is_inline() && func.get_def().is_some() { - // Only delete functions with a body. - inline_funs.insert(id); + // + // This can be overridden by `keep_inline_functions`, which maybe helpful in debugging + // scenarios since env dumping crashes if the functions are removed but still referenced + // from somewhere. + if !keep_inline_functions { + // First construct a list of functions to remove. + let mut inline_funs = BTreeSet::new(); + for module in env.get_modules() { + for func in module.get_functions() { + let id = func.get_qualified_id(); + if func.is_inline() && func.get_def().is_some() { + // Only delete functions with a body. + inline_funs.insert(id); + } } } + env.filter_functions(|fun_id: &QualifiedFunId| !inline_funs.contains(fun_id)); } - // Modify the model to delete of the functions and references to them. - env.filter_functions(|fun_id: &QualifiedFunId| inline_funs.contains(fun_id)); } -/// Helper functions for inlining driver - -/// Get all target functions which are not themselves inline functions. -/// While we're iterating, produce an error on every target inline function lacking a body to -/// inline. -fn get_targets(env: &mut GlobalEnv) -> BTreeSet { - let mut targets = BTreeSet::new(); - for module in env.get_modules() { - if module.is_target() { - for func in module.get_functions() { - let id = func.get_qualified_id(); - if func.is_inline() { - if func.get_def().is_none() { - let func_loc = func.get_loc(); - let func_name = func.get_name_str(); - if func.is_native() { - let msg = format!("Inline function `{}` must not be native", func_name); - env.error(&func_loc, &msg); - } else { - let msg = format!( - "No body found for non-native inline function `{}`", - func_name - ); - env.diag(Severity::Bug, &func_loc, &msg); - } +/// Filter out inline functions from targets since we only process them when they are +/// called from other functions. While we're iterating, produce an error +/// on every inline function lacking a body to inline. +fn filter_targets(env: &GlobalEnv, targets: &mut RewriteTargets) { + targets.filter(|target: &RewriteTarget, _| { + if let RewriteTarget::MoveFun(fnid) = target { + let func = env.get_function(*fnid); + if func.is_inline() { + if func.get_def().is_none() { + let func_loc = func.get_loc(); + let func_name = func.get_name_str(); + if func.is_native() { + let msg = format!("Inline function `{}` must not be native", func_name); + env.error(&func_loc, &msg); + } else { + let msg = format!( + "No body found for non-native inline function `{}`", + func_name + ); + env.diag(Severity::Bug, &func_loc, &msg); } - } else { - targets.insert(id); } + false + } else { + true } + } else { + true } - } - targets + }); } -/// Return a list of all functions calling inline functions, in bottom-up order, +/// Return a list of all inline functions calling inline functions, in bottom-up order, /// so that any inline function will be processed before any function calling it. -fn functions_needing_inlining_in_order( +fn targets_needing_inlining_in_order( env: &GlobalEnv, - call_graph: &BTreeMap>, + call_graph: &BTreeMap>, inline_function_call_site_locations: CallSiteLocations, -) -> Result, ()> { +) -> Result, ()> { + let is_inline_fun = |fnid: &QualifiedFunId| env.get_function(*fnid).is_inline(); + let inline_fun_target_opt = |target: &RewriteTarget| { + if let RewriteTarget::MoveFun(fnid) = target { + if is_inline_fun(fnid) { + Some(*fnid) + } else { + None + } + } else { + None + } + }; // Subset of the call graph limited to inline functions. let inline_function_call_graph: BTreeMap> = call_graph .iter() - .filter(|&(caller_fnid, _)| env.get_function(*caller_fnid).is_inline()) + .filter_map(|(target, callees)| inline_fun_target_opt(target).map(|fid| (fid, callees))) .map(|(caller_fnid, callees)| { ( - *caller_fnid, + caller_fnid, callees .iter() - .filter(|&callee_fnid| env.get_function(*callee_fnid).is_inline()) + .filter(|callee_fnid| is_inline_fun(callee_fnid)) .cloned() .collect(), ) @@ -220,7 +231,9 @@ fn functions_needing_inlining_in_order( .iter() .zip(cycle.iter().skip(1).chain(iter::once(start_fnid))) .flat_map(|(f, g)| { - let sites_ids = inline_function_call_site_locations.get(&(*f, *g)).unwrap(); + let sites_ids = inline_function_call_site_locations + .get(&(RewriteTarget::MoveFun(*f), *g)) + .unwrap(); let f_str = env.get_function(*f).get_full_name_str(); let g_str = env.get_function(*g).get_full_name_str(); let msg = format!("call from `{}` to `{}`", f_str, g_str); @@ -246,23 +259,22 @@ fn functions_needing_inlining_in_order( &inline_functions_calling_others, &inline_function_call_graph, ); - - // Identify subset of non-inline functions which call inline functions. Order doesn't matter - // here. - let non_inline_functions_needing_inlining: Vec = call_graph - .iter() - .filter(|(caller_fnid, callees)| { - !env.get_function(**caller_fnid).is_inline() - && callees - .iter() - .any(|callee_fnid| env.get_function(*callee_fnid).is_inline()) - }) - .map(|(caller_fnid, _)| caller_fnid) - .cloned() + let mut result: Vec = po_inline_functions + .into_iter() + .map(RewriteTarget::MoveFun) .collect(); - let result: Vec = - chain(po_inline_functions, non_inline_functions_needing_inlining).collect(); + // Add subset of non-inline function targets which call inline functions. Order + // doesn't matter here. + result.extend( + call_graph + .iter() + .filter(|(target, callees)| { + inline_fun_target_opt(target).is_none() && callees.iter().any(is_inline_fun) + }) + .map(|(target, _)| target.clone()), + ); + Ok(result) } @@ -348,47 +360,76 @@ fn check_for_cycles( struct Inliner<'env> { env: &'env GlobalEnv, - /// Functions already processed all get an entry here, with a new function body after inline - /// calls are substituted here. Functions which are unchanged (no calls to inline functions) - /// bind to None. - funexprs_after_inlining: BTreeMap>, + /// The set of rewrite targets the inliner works on. + inline_targets: RewriteTargets, } impl<'env> Inliner<'env> { - fn new(env: &'env GlobalEnv) -> Self { - let funexprs_after_inlining = BTreeMap::new(); + fn new(env: &'env GlobalEnv, inline_targets: RewriteTargets) -> Self { Self { env, - funexprs_after_inlining, + inline_targets, } } - /// If the body of function `func_id` contains calls to inline functions, then - /// - makes a copy of the body with every call to any inline function `callee` replaced by + /// If the target has expressions containing calls to inline functions, then + /// - makes a copy of the target with every call to any inline function `callee` replaced by /// either - /// - the mapping found in `self.funexprs_after_inlining` for `callee`, or + /// - the mapping found in `self.inline_results` for `callee`, or /// - the original body of `callee` (as obtained from `self.env: &GlobalEnv`) - /// - stores a mapping from `func_id` to the inlined body `self.funexprs_after_inlining` - /// Otherwise, stores a mapping from `func_id` to `None` in `self.funexprs_after_inlining` + /// - stores a mapping from `target` to inlining result in `self.inline_results` + /// Otherwise, stores a mapping from `target` to `InlineResult::Unchanged` in + /// `self.inline_results` /// - /// This should be called on `func_id` only after all inline functions it calls are processed. - /// It must not be called more than once for any given `func_id`. - fn do_inlining_in(&mut self, func_id: QualifiedFunId) { - assert!(!self.funexprs_after_inlining.contains_key(&func_id)); - let func_env = self.env.get_function(func_id); - if let Some(def) = func_env.get_def() { - let mut rewriter = OuterInlinerRewriter::new(self.env, self); - - let rewritten = rewriter.rewrite_exp(def.clone()); - let changed = !ExpData::ptr_eq(&rewritten, def); - if changed { - self.funexprs_after_inlining - .insert(func_id, Some(rewritten)); - } else { - self.funexprs_after_inlining.insert(func_id, None); - } + /// This should be called on `target` only after all inline functions it calls are processed. + /// It must not be called more than once for any given `target`. + fn do_inlining_in(&mut self, target: RewriteTarget) { + use RewriteState::*; + use RewriteTarget::*; + assert_eq!(self.inline_targets.entry(target.clone()).1, &Unchanged); + match &target { + MoveFun(func_id) => { + let func_env = self.env.get_function(*func_id); + if let Some(new_def) = func_env.get_def().and_then(|def| self.do_rewrite_exp(def)) { + *self.inline_targets.state_mut(&target) = Def(new_def) + } + }, + SpecFun(func_id) => { + let func_env = self.env.get_spec_fun(*func_id); + if let Some(new_def) = func_env + .body + .as_ref() + .and_then(|def| self.do_rewrite_exp(def)) + { + *self.inline_targets.state_mut(&target) = Def(new_def); + } + }, + SpecBlock(sb_target) => { + let spec = self.env.get_spec_block(sb_target); + if let Some(new_spec) = self.do_rewrite_spec(sb_target, &spec) { + *self.inline_targets.state_mut(&target) = Spec(new_spec) + } + }, + } + } + + fn do_rewrite_exp(&mut self, exp: &Exp) -> Option { + let mut rewriter = OuterInlinerRewriter::new(self.env, self); + let rewritten = rewriter.rewrite_exp(exp.clone()); + if !ExpData::ptr_eq(&rewritten, exp) { + Some(rewritten) + } else { + None + } + } + + fn do_rewrite_spec(&mut self, target: &SpecBlockTarget, spec: &Spec) -> Option { + let mut rewriter = OuterInlinerRewriter::new(self.env, self); + let (changed, new_spec) = rewriter.rewrite_spec_descent(target, spec); + if changed { + Some(new_spec) } else { - // Ignore missing body. Error is flagged elsewhere. + None } } } @@ -421,15 +462,18 @@ impl<'env, 'inliner> ExpRewriterFunctions for OuterInlinerRewriter<'env, 'inline let type_args = self.env.get_node_instantiation(call_id); let parameters = func_env.get_parameters(); let func_loc = func_env.get_id_loc(); - let body_expr = - if let Some(Some(expr)) = self.inliner.funexprs_after_inlining.get(&qfid) { - // `qfid` was previously inlined into, use the post-inlining copy of body. - Some(expr.clone()) - } else { - // `qfid` was not previously inlined into, look for the original body expr. - let func_env_def = func_env.get_def(); - func_env_def.cloned() - }; + let body_expr = if let RewriteState::Def(expr) = self + .inliner + .inline_targets + .state(&RewriteTarget::MoveFun(qfid)) + { + // `qfid` was previously inlined into, use the post-inlining copy of body. + Some(expr.clone()) + } else { + // `qfid` was not previously inlined into, look for the original body expr. + let func_env_def = func_env.get_def(); + func_env_def.cloned() + }; // inline here if let Some(expr) = body_expr { trace!( diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 785f2cb6e9df3..7d4fe6bd41273 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -15,7 +15,7 @@ pub mod options; pub mod pipeline; use crate::{ - env_pipeline::EnvProcessorPipeline, + env_pipeline::{rewrite_target::RewritingScope, spec_checker, EnvProcessorPipeline}, pipeline::{ ability_processor::AbilityProcessor, avail_copies_analysis::AvailCopiesAnalysisProcessor, copy_propagation::CopyPropagation, dead_store_elimination::DeadStoreElimination, @@ -51,7 +51,6 @@ use move_stackless_bytecode::function_target_pipeline::{ use move_symbol_pool::Symbol; pub use options::*; use std::{collections::BTreeSet, io::Write, path::Path}; - /// Run Move compiler and print errors to stderr. pub fn run_move_compiler_to_stderr( options: Options, @@ -70,25 +69,11 @@ where { logging::setup_logging(); info!("Move Compiler v2"); - // Run context check. - let mut env = run_checker(options.clone())?; - check_errors(&env, error_writer, "checking errors")?; - - debug!("After context check, GlobalEnv=\n{}", env.dump_env()); - let env_pipeline = create_env_processor_pipeline(&env); - if log_enabled!(Level::Debug) { - env_pipeline.run_and_record(&mut env, error_writer)?; - } else { - env_pipeline.run(&mut env); - } + // Run context check. + let mut env = run_checker_and_rewriters(options.clone(), RewritingScope::CompilationTarget)?; check_errors(&env, error_writer, "checking errors")?; - debug!( - "After flow-insensitive checks, GlobalEnv=\n{}", - env.dump_env() - ); - // Run code generator let mut targets = run_bytecode_gen(&env); check_errors(&env, error_writer, "code generation errors")?; @@ -167,6 +152,21 @@ pub fn run_checker(options: Options) -> anyhow::Result { Ok(env) } +/// Run the type checker as well as the AST rewriting pipeline and related additional +/// checks, returning the global env (with errors if encountered). The result +/// fails not on context checking errors, but possibly on i/o errors. +pub fn run_checker_and_rewriters( + options: Options, + scope: RewritingScope, +) -> anyhow::Result { + let env_pipeline = check_and_rewrite_pipeline(&options, false, scope); + let mut env = run_checker(options)?; + if !env.has_errors() { + env_pipeline.run(&mut env); + } + Ok(env) +} + // Run the (stackless) bytecode generator. For each function which is target of the // compilation, create an entry in the functions target holder which encapsulate info // like the generated bytecode. @@ -205,29 +205,46 @@ pub fn run_file_format_gen(env: &GlobalEnv, targets: &FunctionTargetsHolder) -> file_format_generator::generate_file_format(env, targets) } -/// Returns the standard env_processor_pipeline -pub fn create_env_processor_pipeline<'b>(env: &GlobalEnv) -> EnvProcessorPipeline<'b> { - let options = env.get_extension::().expect("options"); +/// Constructs the env checking and rewriting processing pipeline. `inlining_scope` can be set to +/// `Everything` for use with the Move Prover, otherwise `CompilationTarget` +/// should be used. +pub fn check_and_rewrite_pipeline<'a>( + options: &Options, + for_v1_model: bool, + inlining_scope: RewritingScope, +) -> EnvProcessorPipeline<'a> { let optimize_on = options.experiment_on(Experiment::OPTIMIZE); + // The default transformation pipeline on the GlobalEnv let mut env_pipeline = EnvProcessorPipeline::default(); env_pipeline.add( - "unused vars and params checks", + "unused checks", flow_insensitive_checkers::check_for_unused_vars_and_params, ); env_pipeline.add( - "function typed parameter check", + "type parameter check", function_checker::check_for_function_typed_parameters, ); - env_pipeline.add( - "access and use check before inlining", - |env: &mut GlobalEnv| function_checker::check_access_and_use(env, true), - ); - env_pipeline.add("inlining", inliner::run_inlining); - env_pipeline.add( - "access and use check after inlining", - |env: &mut GlobalEnv| function_checker::check_access_and_use(env, false), - ); + if !for_v1_model { + // Currently when coming via the v1 model building path friend info is + // not populated, so skip those tests. They are anyway run already by + // the v1 compiler. + env_pipeline.add( + "access and use check before inlining", + |env: &mut GlobalEnv| function_checker::check_access_and_use(env, true), + ); + } + env_pipeline.add("inlining", { + move |env| { + inliner::run_inlining(env, inlining_scope, /*keep_inline_functions*/ false) + } + }); + if !for_v1_model { + env_pipeline.add( + "access and use check after inlining", + |env: &mut GlobalEnv| function_checker::check_access_and_use(env, false), + ); + } env_pipeline.add("simplifier", { move |env: &mut GlobalEnv| { ast_simplifier::run_simplifier( @@ -236,6 +253,10 @@ pub fn create_env_processor_pipeline<'b>(env: &GlobalEnv) -> EnvProcessorPipelin ) } }); + env_pipeline.add("specification checker", |env| { + let env: &GlobalEnv = env; + spec_checker::run_spec_checker(env) + }); env_pipeline } diff --git a/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.exp b/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.exp index c73eab8577e2e..3910bd4b361dc 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.exp +++ b/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.exp @@ -1,75 +1,21 @@ Diagnostics: -error: type `ability::Impotent` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:4:3 - │ - 4 │ move_from(addr); - │ ^^^^^^^^^^^^^^^^^^ required because of storage operation here - · -14 │ move_from_no_key(addr); - │ -------------------------------- from a call inlined at this callsite - -error: value of type `ability::Impotent` does not have the `drop` ability - ┌─ tests/ability-check/ability_violation.move:4:3 - │ - 4 │ move_from(addr); - │ ^^^^^^^^^^^^^^^^^^ implicitly dropped here since it is no longer used - · -14 │ move_from_no_key(addr); - │ -------------------------------- from a call inlined at this callsite - -error: type `ability::S` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:15:3 - │ -15 │ move_from>(addr); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: value of type `ability::S` does not have the `drop` ability - ┌─ tests/ability-check/ability_violation.move:15:3 - │ -15 │ move_from>(addr); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implicitly dropped here since it is no longer used - -error: type `ability::Impotent` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:16:3 - │ -16 │ borrow_global_mut(addr); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: type `ability::Impotent` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:17:3 - │ -17 │ borrow_global(addr); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: type `ability::Impotent` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:18:3 - │ -18 │ exists(addr); - │ ^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: type `ability::Impotent` does not have the `key` ability - ┌─ tests/ability-check/ability_violation.move:22:3 - │ -22 │ move_to(signer, Impotent {}) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here - error: local `x` of type `ability::Impotent` does not have the `copy` ability - ┌─ tests/ability-check/ability_violation.move:27:4 - │ -27 │ (x, x); - │ ^ - used here - │ │ - │ copy needed here because value is still in use + ┌─ tests/ability-check/ability_violation.move:7:10 + │ +7 │ (x, x); + │ ^ - used here + │ │ + │ copy needed here because value is still in use error: value of type `ability::Impotent` does not have the `drop` ability - ┌─ tests/ability-check/ability_violation.move:27:4 - │ -27 │ (x, x); - │ ^ implicitly dropped here since it is no longer used + ┌─ tests/ability-check/ability_violation.move:7:10 + │ +7 │ (x, x); + │ ^ implicitly dropped here since it is no longer used error: value of type `ability::Impotent` does not have the `drop` ability - ┌─ tests/ability-check/ability_violation.move:27:7 - │ -27 │ (x, x); - │ ^ implicitly dropped here since it is no longer used + ┌─ tests/ability-check/ability_violation.move:7:13 + │ +7 │ (x, x); + │ ^ implicitly dropped here since it is no longer used diff --git a/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.move b/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.move index 4e0fcc75c2e42..869dcef1b16c0 100644 --- a/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.move +++ b/third_party/move/move-compiler-v2/tests/ability-check/ability_violation.move @@ -1,29 +1,9 @@ module 0x42::ability { - inline fun move_from_no_key(addr: address) { - move_from(addr); - } + struct Impotent {} - struct Impotent {} - - struct S has key { - x: T - } - - fun no_key(addr: address) { - move_from_no_key(addr); - move_from>(addr); - borrow_global_mut(addr); - borrow_global(addr); - exists(addr); - } - - fun invalid_move_to(signer: &signer) { - move_to(signer, Impotent {}) - } - - fun invalid_copy() { - let x = Impotent {}; - (x, x); - } + fun invalid_copy() { + let x = Impotent {}; + (x, x); + } } diff --git a/third_party/move/move-compiler-v2/tests/ability-check/globals.exp b/third_party/move/move-compiler-v2/tests/ability-check/globals.exp deleted file mode 100644 index bc37a081b87d4..0000000000000 --- a/third_party/move/move-compiler-v2/tests/ability-check/globals.exp +++ /dev/null @@ -1,33 +0,0 @@ - -Diagnostics: -warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` - ┌─ tests/ability-check/globals.move:18:27 - │ -18 │ fun write(a: address, x: u64): u64 { - │ ^ - - -Diagnostics: -error: type `globals::R` does not have the `key` ability - ┌─ tests/ability-check/globals.move:6:9 - │ -6 │ move_to(s, R{f: 1}); - │ ^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: type `globals::R` does not have the `key` ability - ┌─ tests/ability-check/globals.move:10:9 - │ -10 │ exists(a) - │ ^^^^^^^^^^^^ required because of storage operation here - -error: type `globals::R` does not have the `key` ability - ┌─ tests/ability-check/globals.move:14:17 - │ -14 │ let r = borrow_global(a); - │ ^^^^^^^^^^^^^^^^^^^ required because of storage operation here - -error: type `globals::R` does not have the `key` ability - ┌─ tests/ability-check/globals.move:19:17 - │ -19 │ let r = borrow_global_mut(a); - │ ^^^^^^^^^^^^^^^^^^^^^^^ required because of storage operation here diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp b/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp index ec4289d86565f..369bf46f052e3 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/by_reference.exp @@ -4,143 +4,127 @@ fun _0::check() { var $t0: bool var $t1: u64 - var $t2: u64 + var $t2: bool var $t3: u64 var $t4: bool - var $t5: vector - var $t6: vector + var $t5: u64 + var $t6: &u64 var $t7: u64 - var $t8: bool + var $t8: u64 var $t9: u64 - var $t10: &u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: bool - var $t15: vector - var $t16: &vector - var $t17: vector - var $t18: vector + var $t10: bool + var $t11: vector + var $t12: &vector + var $t13: vector + var $t14: vector + var $t15: u64 + var $t16: &mut u64 + var $t17: &mut u64 + var $t18: u64 var $t19: u64 - var $t20: &mut u64 - var $t21: &mut u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - var $t25: &mut vector - var $t26: vector - var $t27: vector + var $t20: &mut vector + var $t21: &mut vector + var $t22: vector + var $t23: vector + var $t24: bool + var $t25: u64 + var $t26: u64 + var $t27: u64 var $t28: bool - var $t29: u64 - var $t30: u64 + var $t29: vector + var $t30: vector var $t31: u64 var $t32: bool - var $t33: vector - var $t34: vector + var $t33: u64 + var $t34: bool var $t35: u64 - var $t36: bool - var $t37: u64 - var $t38: u64 - var $t39: u64 - var $t40: bool - var $t41: vector - var $t42: vector - var $t43: u64 - 0: $t1 := 0 - 1: $t2 := 0 - 2: $t0 := ==($t1, $t2) - 3: if ($t0) goto 4 else goto 6 - 4: label L0 - 5: goto 9 - 6: label L1 - 7: $t3 := 42 - 8: abort($t3) - 9: label L2 - 10: $t5 := [104, 101, 108, 108, 111] - 11: $t6 := [104, 101, 108, 108, 111] - 12: $t4 := ==($t5, $t6) - 13: if ($t4) goto 14 else goto 16 - 14: label L3 - 15: goto 19 - 16: label L4 - 17: $t7 := 42 - 18: abort($t7) - 19: label L5 - 20: $t11 := 0 - 21: $t10 := borrow_local($t11) - 22: $t9 := read_ref($t10) - 23: $t12 := 0 - 24: $t8 := ==($t9, $t12) - 25: if ($t8) goto 26 else goto 28 - 26: label L6 - 27: goto 31 - 28: label L7 - 29: $t13 := 42 - 30: abort($t13) - 31: label L8 - 32: $t17 := [104, 101, 108, 108, 111] - 33: $t16 := borrow_local($t17) - 34: $t15 := read_ref($t16) - 35: $t18 := [104, 101, 108, 108, 111] - 36: $t14 := ==($t15, $t18) - 37: if ($t14) goto 38 else goto 40 - 38: label L9 - 39: goto 43 - 40: label L10 - 41: $t19 := 42 - 42: abort($t19) - 43: label L11 - 44: $t22 := 0 - 45: $t21 := borrow_local($t22) - 46: $t20 := infer($t21) - 47: $t23 := 1 - 48: write_ref($t20, $t23) - 49: $t26 := [104, 101, 108, 108, 111] - 50: $t25 := borrow_local($t26) - 51: $t24 := infer($t25) - 52: $t27 := [98, 121, 101] - 53: write_ref($t24, $t27) - 54: $t29 := read_ref($t20) - 55: $t30 := 1 - 56: $t28 := ==($t29, $t30) - 57: if ($t28) goto 58 else goto 60 - 58: label L12 - 59: goto 63 - 60: label L13 - 61: $t31 := 42 - 62: abort($t31) - 63: label L14 - 64: $t33 := read_ref($t24) - 65: $t34 := [98, 121, 101] - 66: $t32 := ==($t33, $t34) - 67: if ($t32) goto 68 else goto 70 - 68: label L15 - 69: goto 73 - 70: label L16 - 71: $t35 := 42 - 72: abort($t35) - 73: label L17 - 74: $t37 := 0 - 75: $t38 := 0 - 76: $t36 := ==($t37, $t38) - 77: if ($t36) goto 78 else goto 80 - 78: label L18 - 79: goto 83 - 80: label L19 - 81: $t39 := 42 - 82: abort($t39) - 83: label L20 - 84: $t41 := [104, 101, 108, 108, 111] - 85: $t42 := [104, 101, 108, 108, 111] - 86: $t40 := ==($t41, $t42) - 87: if ($t40) goto 88 else goto 90 - 88: label L21 - 89: goto 93 - 90: label L22 - 91: $t43 := 42 - 92: abort($t43) - 93: label L23 - 94: return () + 0: $t0 := true + 1: if ($t0) goto 2 else goto 4 + 2: label L0 + 3: goto 7 + 4: label L1 + 5: $t1 := 42 + 6: abort($t1) + 7: label L2 + 8: $t2 := true + 9: if ($t2) goto 10 else goto 12 + 10: label L3 + 11: goto 15 + 12: label L4 + 13: $t3 := 42 + 14: abort($t3) + 15: label L5 + 16: $t7 := 0 + 17: $t6 := borrow_local($t7) + 18: $t5 := read_ref($t6) + 19: $t8 := 0 + 20: $t4 := ==($t5, $t8) + 21: if ($t4) goto 22 else goto 24 + 22: label L6 + 23: goto 27 + 24: label L7 + 25: $t9 := 42 + 26: abort($t9) + 27: label L8 + 28: $t13 := [104, 101, 108, 108, 111] + 29: $t12 := borrow_local($t13) + 30: $t11 := read_ref($t12) + 31: $t14 := [104, 101, 108, 108, 111] + 32: $t10 := ==($t11, $t14) + 33: if ($t10) goto 34 else goto 36 + 34: label L9 + 35: goto 39 + 36: label L10 + 37: $t15 := 42 + 38: abort($t15) + 39: label L11 + 40: $t18 := 0 + 41: $t17 := borrow_local($t18) + 42: $t16 := infer($t17) + 43: $t19 := 1 + 44: write_ref($t16, $t19) + 45: $t22 := [104, 101, 108, 108, 111] + 46: $t21 := borrow_local($t22) + 47: $t20 := infer($t21) + 48: $t23 := [98, 121, 101] + 49: write_ref($t20, $t23) + 50: $t25 := read_ref($t16) + 51: $t26 := 1 + 52: $t24 := ==($t25, $t26) + 53: if ($t24) goto 54 else goto 56 + 54: label L12 + 55: goto 59 + 56: label L13 + 57: $t27 := 42 + 58: abort($t27) + 59: label L14 + 60: $t29 := read_ref($t20) + 61: $t30 := [98, 121, 101] + 62: $t28 := ==($t29, $t30) + 63: if ($t28) goto 64 else goto 66 + 64: label L15 + 65: goto 69 + 66: label L16 + 67: $t31 := 42 + 68: abort($t31) + 69: label L17 + 70: $t32 := true + 71: if ($t32) goto 72 else goto 74 + 72: label L18 + 73: goto 77 + 74: label L19 + 75: $t33 := 42 + 76: abort($t33) + 77: label L20 + 78: $t34 := true + 79: if ($t34) goto 80 else goto 82 + 80: label L21 + 81: goto 85 + 82: label L22 + 83: $t35 := 42 + 84: abort($t35) + 85: label L23 + 86: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -149,238 +133,214 @@ fun _0::check() { fun _0::check() { var $t0: bool var $t1: u64 - var $t2: u64 + var $t2: bool var $t3: u64 var $t4: bool - var $t5: vector - var $t6: vector + var $t5: u64 + var $t6: &u64 var $t7: u64 - var $t8: bool + var $t8: u64 var $t9: u64 - var $t10: &u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: bool - var $t15: vector - var $t16: &vector - var $t17: vector - var $t18: vector + var $t10: bool + var $t11: vector + var $t12: &vector + var $t13: vector + var $t14: vector + var $t15: u64 + var $t16: &mut u64 + var $t17: &mut u64 + var $t18: u64 var $t19: u64 - var $t20: &mut u64 - var $t21: &mut u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - var $t25: &mut vector - var $t26: vector - var $t27: vector + var $t20: &mut vector + var $t21: &mut vector + var $t22: vector + var $t23: vector + var $t24: bool + var $t25: u64 + var $t26: u64 + var $t27: u64 var $t28: bool - var $t29: u64 - var $t30: u64 + var $t29: vector + var $t30: vector var $t31: u64 var $t32: bool - var $t33: vector - var $t34: vector + var $t33: u64 + var $t34: bool var $t35: u64 - var $t36: bool - var $t37: u64 - var $t38: u64 - var $t39: u64 - var $t40: bool - var $t41: vector - var $t42: vector - var $t43: u64 - # live vars: - 0: $t1 := 0 - # live vars: $t1 - 1: $t2 := 0 - # live vars: $t1, $t2 - 2: $t0 := ==($t1, $t2) + # live vars: + 0: $t0 := true # live vars: $t0 - 3: if ($t0) goto 4 else goto 6 + 1: if ($t0) goto 2 else goto 4 + # live vars: + 2: label L0 + # live vars: + 3: goto 7 + # live vars: + 4: label L1 + # live vars: + 5: $t1 := 42 + # live vars: $t1 + 6: abort($t1) + # live vars: + 7: label L2 + # live vars: + 8: $t2 := true + # live vars: $t2 + 9: if ($t2) goto 10 else goto 12 # live vars: - 4: label L0 + 10: label L3 # live vars: - 5: goto 9 + 11: goto 15 # live vars: - 6: label L1 + 12: label L4 # live vars: - 7: $t3 := 42 + 13: $t3 := 42 # live vars: $t3 - 8: abort($t3) + 14: abort($t3) # live vars: - 9: label L2 + 15: label L5 # live vars: - 10: $t5 := [104, 101, 108, 108, 111] + 16: $t7 := 0 + # live vars: $t7 + 17: $t6 := borrow_local($t7) + # live vars: $t6 + 18: $t5 := read_ref($t6) # live vars: $t5 - 11: $t6 := [104, 101, 108, 108, 111] - # live vars: $t5, $t6 - 12: $t4 := ==($t5, $t6) + 19: $t8 := 0 + # live vars: $t5, $t8 + 20: $t4 := ==($t5, $t8) # live vars: $t4 - 13: if ($t4) goto 14 else goto 16 + 21: if ($t4) goto 22 else goto 24 # live vars: - 14: label L3 + 22: label L6 # live vars: - 15: goto 19 + 23: goto 27 # live vars: - 16: label L4 + 24: label L7 # live vars: - 17: $t7 := 42 - # live vars: $t7 - 18: abort($t7) + 25: $t9 := 42 + # live vars: $t9 + 26: abort($t9) # live vars: - 19: label L5 + 27: label L8 # live vars: - 20: $t11 := 0 + 28: $t13 := [104, 101, 108, 108, 111] + # live vars: $t13 + 29: $t12 := borrow_local($t13) + # live vars: $t12 + 30: $t11 := read_ref($t12) # live vars: $t11 - 21: $t10 := borrow_local($t11) + 31: $t14 := [104, 101, 108, 108, 111] + # live vars: $t11, $t14 + 32: $t10 := ==($t11, $t14) # live vars: $t10 - 22: $t9 := read_ref($t10) - # live vars: $t9 - 23: $t12 := 0 - # live vars: $t9, $t12 - 24: $t8 := ==($t9, $t12) - # live vars: $t8 - 25: if ($t8) goto 26 else goto 28 + 33: if ($t10) goto 34 else goto 36 # live vars: - 26: label L6 + 34: label L9 # live vars: - 27: goto 31 + 35: goto 39 # live vars: - 28: label L7 + 36: label L10 # live vars: - 29: $t13 := 42 - # live vars: $t13 - 30: abort($t13) + 37: $t15 := 42 + # live vars: $t15 + 38: abort($t15) # live vars: - 31: label L8 + 39: label L11 # live vars: - 32: $t17 := [104, 101, 108, 108, 111] + 40: $t18 := 0 + # live vars: $t18 + 41: $t17 := borrow_local($t18) # live vars: $t17 - 33: $t16 := borrow_local($t17) + 42: $t16 := infer($t17) # live vars: $t16 - 34: $t15 := read_ref($t16) - # live vars: $t15 - 35: $t18 := [104, 101, 108, 108, 111] - # live vars: $t15, $t18 - 36: $t14 := ==($t15, $t18) - # live vars: $t14 - 37: if ($t14) goto 38 else goto 40 - # live vars: - 38: label L9 - # live vars: - 39: goto 43 - # live vars: - 40: label L10 - # live vars: - 41: $t19 := 42 - # live vars: $t19 - 42: abort($t19) - # live vars: - 43: label L11 + 43: $t19 := 1 + # live vars: $t16, $t19 + 44: write_ref($t16, $t19) + # live vars: $t16 + 45: $t22 := [104, 101, 108, 108, 111] + # live vars: $t16, $t22 + 46: $t21 := borrow_local($t22) + # live vars: $t16, $t21 + 47: $t20 := infer($t21) + # live vars: $t16, $t20 + 48: $t23 := [98, 121, 101] + # live vars: $t16, $t20, $t23 + 49: write_ref($t20, $t23) + # live vars: $t16, $t20 + 50: $t25 := read_ref($t16) + # live vars: $t20, $t25 + 51: $t26 := 1 + # live vars: $t20, $t25, $t26 + 52: $t24 := ==($t25, $t26) + # live vars: $t20, $t24 + 53: if ($t24) goto 54 else goto 56 + # live vars: $t20 + 54: label L12 + # live vars: $t20 + 55: goto 59 + # live vars: $t20 + 56: label L13 # live vars: - 44: $t22 := 0 - # live vars: $t22 - 45: $t21 := borrow_local($t22) - # live vars: $t21 - 46: $t20 := infer($t21) + 57: $t27 := 42 + # live vars: $t27 + 58: abort($t27) # live vars: $t20 - 47: $t23 := 1 - # live vars: $t20, $t23 - 48: write_ref($t20, $t23) + 59: label L14 # live vars: $t20 - 49: $t26 := [104, 101, 108, 108, 111] - # live vars: $t20, $t26 - 50: $t25 := borrow_local($t26) - # live vars: $t20, $t25 - 51: $t24 := infer($t25) - # live vars: $t20, $t24 - 52: $t27 := [98, 121, 101] - # live vars: $t20, $t24, $t27 - 53: write_ref($t24, $t27) - # live vars: $t20, $t24 - 54: $t29 := read_ref($t20) - # live vars: $t24, $t29 - 55: $t30 := 1 - # live vars: $t24, $t29, $t30 - 56: $t28 := ==($t29, $t30) - # live vars: $t24, $t28 - 57: if ($t28) goto 58 else goto 60 - # live vars: $t24 - 58: label L12 - # live vars: $t24 - 59: goto 63 - # live vars: $t24 - 60: label L13 - # live vars: - 61: $t31 := 42 - # live vars: $t31 - 62: abort($t31) - # live vars: $t24 - 63: label L14 - # live vars: $t24 - 64: $t33 := read_ref($t24) - # live vars: $t33 - 65: $t34 := [98, 121, 101] - # live vars: $t33, $t34 - 66: $t32 := ==($t33, $t34) - # live vars: $t32 - 67: if ($t32) goto 68 else goto 70 + 60: $t29 := read_ref($t20) + # live vars: $t29 + 61: $t30 := [98, 121, 101] + # live vars: $t29, $t30 + 62: $t28 := ==($t29, $t30) + # live vars: $t28 + 63: if ($t28) goto 64 else goto 66 # live vars: - 68: label L15 + 64: label L15 # live vars: - 69: goto 73 + 65: goto 69 # live vars: - 70: label L16 + 66: label L16 # live vars: - 71: $t35 := 42 - # live vars: $t35 - 72: abort($t35) + 67: $t31 := 42 + # live vars: $t31 + 68: abort($t31) # live vars: - 73: label L17 + 69: label L17 # live vars: - 74: $t37 := 0 - # live vars: $t37 - 75: $t38 := 0 - # live vars: $t37, $t38 - 76: $t36 := ==($t37, $t38) - # live vars: $t36 - 77: if ($t36) goto 78 else goto 80 + 70: $t32 := true + # live vars: $t32 + 71: if ($t32) goto 72 else goto 74 # live vars: - 78: label L18 + 72: label L18 # live vars: - 79: goto 83 + 73: goto 77 # live vars: - 80: label L19 + 74: label L19 # live vars: - 81: $t39 := 42 - # live vars: $t39 - 82: abort($t39) + 75: $t33 := 42 + # live vars: $t33 + 76: abort($t33) # live vars: - 83: label L20 + 77: label L20 # live vars: - 84: $t41 := [104, 101, 108, 108, 111] - # live vars: $t41 - 85: $t42 := [104, 101, 108, 108, 111] - # live vars: $t41, $t42 - 86: $t40 := ==($t41, $t42) - # live vars: $t40 - 87: if ($t40) goto 88 else goto 90 + 78: $t34 := true + # live vars: $t34 + 79: if ($t34) goto 80 else goto 82 # live vars: - 88: label L21 + 80: label L21 # live vars: - 89: goto 93 + 81: goto 85 # live vars: - 90: label L22 + 82: label L22 # live vars: - 91: $t43 := 42 - # live vars: $t43 - 92: abort($t43) + 83: $t35 := 42 + # live vars: $t35 + 84: abort($t35) # live vars: - 93: label L23 + 85: label L23 # live vars: - 94: return () + 86: return () } ============ after ReferenceSafetyProcessor: ================ @@ -389,618 +349,562 @@ fun _0::check() { fun _0::check() { var $t0: bool var $t1: u64 - var $t2: u64 + var $t2: bool var $t3: u64 var $t4: bool - var $t5: vector - var $t6: vector + var $t5: u64 + var $t6: &u64 var $t7: u64 - var $t8: bool + var $t8: u64 var $t9: u64 - var $t10: &u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: bool - var $t15: vector - var $t16: &vector - var $t17: vector - var $t18: vector + var $t10: bool + var $t11: vector + var $t12: &vector + var $t13: vector + var $t14: vector + var $t15: u64 + var $t16: &mut u64 + var $t17: &mut u64 + var $t18: u64 var $t19: u64 - var $t20: &mut u64 - var $t21: &mut u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - var $t25: &mut vector - var $t26: vector - var $t27: vector + var $t20: &mut vector + var $t21: &mut vector + var $t22: vector + var $t23: vector + var $t24: bool + var $t25: u64 + var $t26: u64 + var $t27: u64 var $t28: bool - var $t29: u64 - var $t30: u64 + var $t29: vector + var $t30: vector var $t31: u64 var $t32: bool - var $t33: vector - var $t34: vector + var $t33: u64 + var $t34: bool var $t35: u64 - var $t36: bool - var $t37: u64 - var $t38: u64 - var $t39: u64 - var $t40: bool - var $t41: vector - var $t42: vector - var $t43: u64 # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t1 := 0 - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t2 := 0 - # live vars: $t1, $t2 - # graph: {} - # locals: {} - # globals: {} - # - 2: $t0 := ==($t1, $t2) + 0: $t0 := true # live vars: $t0 # graph: {} # locals: {} # globals: {} # - 3: if ($t0) goto 4 else goto 6 + 1: if ($t0) goto 2 else goto 4 # live vars: # graph: {} # locals: {} # globals: {} # - 4: label L0 + 2: label L0 # live vars: # graph: {} # locals: {} # globals: {} # - 5: goto 9 + 3: goto 7 # live vars: # graph: {} # locals: {} # globals: {} # - 6: label L1 + 4: label L1 # live vars: # graph: {} # locals: {} # globals: {} # - 7: $t3 := 42 - # live vars: $t3 + 5: $t1 := 42 + # live vars: $t1 # graph: {} # locals: {} # globals: {} # - 8: abort($t3) + 6: abort($t1) # live vars: # graph: {} # locals: {} # globals: {} # - 9: label L2 + 7: label L2 # live vars: # graph: {} # locals: {} # globals: {} # - 10: $t5 := [104, 101, 108, 108, 111] - # live vars: $t5 - # graph: {} - # locals: {} - # globals: {} - # - 11: $t6 := [104, 101, 108, 108, 111] - # live vars: $t5, $t6 + 8: $t2 := true + # live vars: $t2 # graph: {} # locals: {} # globals: {} # - 12: $t4 := ==($t5, $t6) - # live vars: $t4 - # graph: {} - # locals: {} - # globals: {} - # - 13: if ($t4) goto 14 else goto 16 + 9: if ($t2) goto 10 else goto 12 # live vars: # graph: {} # locals: {} # globals: {} # - 14: label L3 + 10: label L3 # live vars: # graph: {} # locals: {} # globals: {} # - 15: goto 19 + 11: goto 15 # live vars: # graph: {} # locals: {} # globals: {} # - 16: label L4 + 12: label L4 # live vars: # graph: {} # locals: {} # globals: {} # - 17: $t7 := 42 - # live vars: $t7 + 13: $t3 := 42 + # live vars: $t3 # graph: {} # locals: {} # globals: {} # - 18: abort($t7) + 14: abort($t3) # live vars: # graph: {} # locals: {} # globals: {} # - 19: label L5 + 15: label L5 # live vars: # graph: {} # locals: {} # globals: {} # - 20: $t11 := 0 - # live vars: $t11 + 16: $t7 := 0 + # live vars: $t7 # graph: {} # locals: {} # globals: {} # - 21: $t10 := borrow_local($t11) - # live vars: $t10 - # graph: {@1500=local($t11)[borrow(false) -> @1501],@1501=derived[]} - # locals: {$t10=@1501,$t11=@1500} + 17: $t6 := borrow_local($t7) + # live vars: $t6 + # graph: {@1100=local($t7)[borrow(false) -> @1101],@1101=derived[]} + # locals: {$t6=@1101,$t7=@1100} # globals: {} # - 22: $t9 := read_ref($t10) - # live vars: $t9 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + 18: $t5 := read_ref($t6) + # live vars: $t5 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 23: $t12 := 0 - # live vars: $t9, $t12 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + 19: $t8 := 0 + # live vars: $t5, $t8 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 24: $t8 := ==($t9, $t12) - # live vars: $t8 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + 20: $t4 := ==($t5, $t8) + # live vars: $t4 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 25: if ($t8) goto 26 else goto 28 + 21: if ($t4) goto 22 else goto 24 # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 26: label L6 + 22: label L6 # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 27: goto 31 + 23: goto 27 # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 28: label L7 + 24: label L7 # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 29: $t13 := 42 - # live vars: $t13 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + 25: $t9 := 42 + # live vars: $t9 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 30: abort($t13) + 26: abort($t9) # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 31: label L8 + 27: label L8 # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 32: $t17 := [104, 101, 108, 108, 111] - # live vars: $t17 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + 28: $t13 := [104, 101, 108, 108, 111] + # live vars: $t13 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 33: $t16 := borrow_local($t17) - # live vars: $t16 - # graph: {@1500=local($t11)[],@2100=local($t17)[borrow(false) -> @2101],@2101=derived[]} - # locals: {$t11=@1500,$t16=@2101,$t17=@2100} + 29: $t12 := borrow_local($t13) + # live vars: $t12 + # graph: {@1100=local($t7)[],@1D00=local($t13)[borrow(false) -> @1D01],@1D01=derived[]} + # locals: {$t7=@1100,$t12=@1D01,$t13=@1D00} # globals: {} # - 34: $t15 := read_ref($t16) - # live vars: $t15 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + 30: $t11 := read_ref($t12) + # live vars: $t11 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 35: $t18 := [104, 101, 108, 108, 111] - # live vars: $t15, $t18 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + 31: $t14 := [104, 101, 108, 108, 111] + # live vars: $t11, $t14 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 36: $t14 := ==($t15, $t18) - # live vars: $t14 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + 32: $t10 := ==($t11, $t14) + # live vars: $t10 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 37: if ($t14) goto 38 else goto 40 + 33: if ($t10) goto 34 else goto 36 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 38: label L9 + 34: label L9 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 39: goto 43 + 35: goto 39 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 40: label L10 + 36: label L10 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 41: $t19 := 42 - # live vars: $t19 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + 37: $t15 := 42 + # live vars: $t15 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 42: abort($t19) + 38: abort($t15) # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 43: label L11 + 39: label L11 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 44: $t22 := 0 - # live vars: $t22 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + 40: $t18 := 0 + # live vars: $t18 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 45: $t21 := borrow_local($t22) - # live vars: $t21 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t21=@2D01,$t22=@2D00} + 41: $t17 := borrow_local($t18) + # live vars: $t17 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t17=@2901,$t18=@2900} # globals: {} # - 46: $t20 := infer($t21) - # live vars: $t20 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + 42: $t16 := infer($t17) + # live vars: $t16 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 47: $t23 := 1 - # live vars: $t20, $t23 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + 43: $t19 := 1 + # live vars: $t16, $t19 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 48: write_ref($t20, $t23) - # live vars: $t20 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + 44: write_ref($t16, $t19) + # live vars: $t16 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 49: $t26 := [104, 101, 108, 108, 111] - # live vars: $t20, $t26 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + 45: $t22 := [104, 101, 108, 108, 111] + # live vars: $t16, $t22 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 50: $t25 := borrow_local($t26) - # live vars: $t20, $t25 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t25=@3201,$t26=@3200} + 46: $t21 := borrow_local($t22) + # live vars: $t16, $t21 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t21=@2E01,$t22=@2E00} # globals: {} # - 51: $t24 := infer($t25) - # live vars: $t20, $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + 47: $t20 := infer($t21) + # live vars: $t16, $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 52: $t27 := [98, 121, 101] - # live vars: $t20, $t24, $t27 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + 48: $t23 := [98, 121, 101] + # live vars: $t16, $t20, $t23 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 53: write_ref($t24, $t27) - # live vars: $t20, $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + 49: write_ref($t20, $t23) + # live vars: $t16, $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 54: $t29 := read_ref($t20) - # live vars: $t24, $t29 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 50: $t25 := read_ref($t16) + # live vars: $t20, $t25 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 55: $t30 := 1 - # live vars: $t24, $t29, $t30 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 51: $t26 := 1 + # live vars: $t20, $t25, $t26 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 56: $t28 := ==($t29, $t30) - # live vars: $t24, $t28 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 52: $t24 := ==($t25, $t26) + # live vars: $t20, $t24 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 57: if ($t28) goto 58 else goto 60 - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 53: if ($t24) goto 54 else goto 56 + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 58: label L12 - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 54: label L12 + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 59: goto 63 - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 55: goto 59 + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 60: label L13 + 56: label L13 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 61: $t31 := 42 - # live vars: $t31 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 57: $t27 := 42 + # live vars: $t27 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 62: abort($t31) - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 58: abort($t27) + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 63: label L14 - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + 59: label L14 + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 64: $t33 := read_ref($t24) - # live vars: $t33 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 60: $t29 := read_ref($t20) + # live vars: $t29 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 65: $t34 := [98, 121, 101] - # live vars: $t33, $t34 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 61: $t30 := [98, 121, 101] + # live vars: $t29, $t30 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 66: $t32 := ==($t33, $t34) - # live vars: $t32 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 62: $t28 := ==($t29, $t30) + # live vars: $t28 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 67: if ($t32) goto 68 else goto 70 + 63: if ($t28) goto 64 else goto 66 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 68: label L15 + 64: label L15 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 69: goto 73 + 65: goto 69 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 70: label L16 + 66: label L16 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 71: $t35 := 42 - # live vars: $t35 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 67: $t31 := 42 + # live vars: $t31 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 72: abort($t35) + 68: abort($t31) # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 73: label L17 + 69: label L17 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 74: $t37 := 0 - # live vars: $t37 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 75: $t38 := 0 - # live vars: $t37, $t38 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 76: $t36 := ==($t37, $t38) - # live vars: $t36 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 70: $t32 := true + # live vars: $t32 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 77: if ($t36) goto 78 else goto 80 + 71: if ($t32) goto 72 else goto 74 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 78: label L18 + 72: label L18 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 79: goto 83 + 73: goto 77 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 80: label L19 + 74: label L19 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 81: $t39 := 42 - # live vars: $t39 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 75: $t33 := 42 + # live vars: $t33 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 82: abort($t39) + 76: abort($t33) # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 83: label L20 + 77: label L20 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 84: $t41 := [104, 101, 108, 108, 111] - # live vars: $t41 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 85: $t42 := [104, 101, 108, 108, 111] - # live vars: $t41, $t42 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 78: $t34 := true + # live vars: $t34 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 86: $t40 := ==($t41, $t42) - # live vars: $t40 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 87: if ($t40) goto 88 else goto 90 + 79: if ($t34) goto 80 else goto 82 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 88: label L21 + 80: label L21 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 89: goto 93 + 81: goto 85 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 90: label L22 + 82: label L22 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 91: $t43 := 42 - # live vars: $t43 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + 83: $t35 := 42 + # live vars: $t35 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 92: abort($t43) + 84: abort($t35) # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 93: label L23 + 85: label L23 # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 94: return () + 86: return () } ============ after AbortAnalysisProcessor: ================ @@ -1009,713 +913,649 @@ fun _0::check() { fun _0::check() { var $t0: bool var $t1: u64 - var $t2: u64 + var $t2: bool var $t3: u64 var $t4: bool - var $t5: vector - var $t6: vector + var $t5: u64 + var $t6: &u64 var $t7: u64 - var $t8: bool + var $t8: u64 var $t9: u64 - var $t10: &u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: bool - var $t15: vector - var $t16: &vector - var $t17: vector - var $t18: vector + var $t10: bool + var $t11: vector + var $t12: &vector + var $t13: vector + var $t14: vector + var $t15: u64 + var $t16: &mut u64 + var $t17: &mut u64 + var $t18: u64 var $t19: u64 - var $t20: &mut u64 - var $t21: &mut u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - var $t25: &mut vector - var $t26: vector - var $t27: vector + var $t20: &mut vector + var $t21: &mut vector + var $t22: vector + var $t23: vector + var $t24: bool + var $t25: u64 + var $t26: u64 + var $t27: u64 var $t28: bool - var $t29: u64 - var $t30: u64 + var $t29: vector + var $t30: vector var $t31: u64 var $t32: bool - var $t33: vector - var $t34: vector + var $t33: u64 + var $t34: bool var $t35: u64 - var $t36: bool - var $t37: u64 - var $t38: u64 - var $t39: u64 - var $t40: bool - var $t41: vector - var $t42: vector - var $t43: u64 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t1 := 0 - # abort state: {returns,aborts} - # live vars: $t1 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t2 := 0 - # abort state: {returns,aborts} - # live vars: $t1, $t2 - # graph: {} - # locals: {} - # globals: {} - # - 2: $t0 := ==($t1, $t2) + 0: $t0 := true # abort state: {returns,aborts} # live vars: $t0 # graph: {} # locals: {} # globals: {} # - 3: if ($t0) goto 4 else goto 6 + 1: if ($t0) goto 2 else goto 4 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 4: label L0 + 2: label L0 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 5: goto 9 + 3: goto 7 # abort state: {aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 6: label L1 + 4: label L1 # abort state: {aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 7: $t3 := 42 + 5: $t1 := 42 # abort state: {aborts} - # live vars: $t3 + # live vars: $t1 # graph: {} # locals: {} # globals: {} # - 8: abort($t3) + 6: abort($t1) # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 9: label L2 + 7: label L2 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 10: $t5 := [104, 101, 108, 108, 111] - # abort state: {returns,aborts} - # live vars: $t5 - # graph: {} - # locals: {} - # globals: {} - # - 11: $t6 := [104, 101, 108, 108, 111] + 8: $t2 := true # abort state: {returns,aborts} - # live vars: $t5, $t6 + # live vars: $t2 # graph: {} # locals: {} # globals: {} # - 12: $t4 := ==($t5, $t6) - # abort state: {returns,aborts} - # live vars: $t4 - # graph: {} - # locals: {} - # globals: {} - # - 13: if ($t4) goto 14 else goto 16 + 9: if ($t2) goto 10 else goto 12 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 14: label L3 + 10: label L3 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 15: goto 19 + 11: goto 15 # abort state: {aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 16: label L4 + 12: label L4 # abort state: {aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 17: $t7 := 42 + 13: $t3 := 42 # abort state: {aborts} - # live vars: $t7 + # live vars: $t3 # graph: {} # locals: {} # globals: {} # - 18: abort($t7) + 14: abort($t3) # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 19: label L5 + 15: label L5 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 20: $t11 := 0 + 16: $t7 := 0 # abort state: {returns,aborts} - # live vars: $t11 + # live vars: $t7 # graph: {} # locals: {} # globals: {} # - 21: $t10 := borrow_local($t11) + 17: $t6 := borrow_local($t7) # abort state: {returns,aborts} - # live vars: $t10 - # graph: {@1500=local($t11)[borrow(false) -> @1501],@1501=derived[]} - # locals: {$t10=@1501,$t11=@1500} + # live vars: $t6 + # graph: {@1100=local($t7)[borrow(false) -> @1101],@1101=derived[]} + # locals: {$t6=@1101,$t7=@1100} # globals: {} # - 22: $t9 := read_ref($t10) + 18: $t5 := read_ref($t6) # abort state: {returns,aborts} - # live vars: $t9 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # live vars: $t5 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 23: $t12 := 0 + 19: $t8 := 0 # abort state: {returns,aborts} - # live vars: $t9, $t12 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # live vars: $t5, $t8 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 24: $t8 := ==($t9, $t12) + 20: $t4 := ==($t5, $t8) # abort state: {returns,aborts} - # live vars: $t8 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # live vars: $t4 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 25: if ($t8) goto 26 else goto 28 + 21: if ($t4) goto 22 else goto 24 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 26: label L6 + 22: label L6 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 27: goto 31 + 23: goto 27 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 28: label L7 + 24: label L7 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 29: $t13 := 42 + 25: $t9 := 42 # abort state: {aborts} - # live vars: $t13 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # live vars: $t9 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 30: abort($t13) + 26: abort($t9) # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 31: label L8 + 27: label L8 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 32: $t17 := [104, 101, 108, 108, 111] + 28: $t13 := [104, 101, 108, 108, 111] # abort state: {returns,aborts} - # live vars: $t17 - # graph: {@1500=local($t11)[]} - # locals: {$t11=@1500} + # live vars: $t13 + # graph: {@1100=local($t7)[]} + # locals: {$t7=@1100} # globals: {} # - 33: $t16 := borrow_local($t17) + 29: $t12 := borrow_local($t13) # abort state: {returns,aborts} - # live vars: $t16 - # graph: {@1500=local($t11)[],@2100=local($t17)[borrow(false) -> @2101],@2101=derived[]} - # locals: {$t11=@1500,$t16=@2101,$t17=@2100} + # live vars: $t12 + # graph: {@1100=local($t7)[],@1D00=local($t13)[borrow(false) -> @1D01],@1D01=derived[]} + # locals: {$t7=@1100,$t12=@1D01,$t13=@1D00} # globals: {} # - 34: $t15 := read_ref($t16) + 30: $t11 := read_ref($t12) # abort state: {returns,aborts} - # live vars: $t15 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # live vars: $t11 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 35: $t18 := [104, 101, 108, 108, 111] + 31: $t14 := [104, 101, 108, 108, 111] # abort state: {returns,aborts} - # live vars: $t15, $t18 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # live vars: $t11, $t14 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 36: $t14 := ==($t15, $t18) + 32: $t10 := ==($t11, $t14) # abort state: {returns,aborts} - # live vars: $t14 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # live vars: $t10 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 37: if ($t14) goto 38 else goto 40 + 33: if ($t10) goto 34 else goto 36 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 38: label L9 + 34: label L9 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 39: goto 43 + 35: goto 39 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 40: label L10 + 36: label L10 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 41: $t19 := 42 + 37: $t15 := 42 # abort state: {aborts} - # live vars: $t19 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # live vars: $t15 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 42: abort($t19) + 38: abort($t15) # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 43: label L11 + 39: label L11 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 44: $t22 := 0 + 40: $t18 := 0 # abort state: {returns,aborts} - # live vars: $t22 - # graph: {@1500=local($t11)[],@2100=local($t17)[]} - # locals: {$t11=@1500,$t17=@2100} + # live vars: $t18 + # graph: {@1100=local($t7)[],@1D00=local($t13)[]} + # locals: {$t7=@1100,$t13=@1D00} # globals: {} # - 45: $t21 := borrow_local($t22) + 41: $t17 := borrow_local($t18) # abort state: {returns,aborts} - # live vars: $t21 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t21=@2D01,$t22=@2D00} + # live vars: $t17 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t17=@2901,$t18=@2900} # globals: {} # - 46: $t20 := infer($t21) + 42: $t16 := infer($t17) # abort state: {returns,aborts} - # live vars: $t20 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + # live vars: $t16 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 47: $t23 := 1 + 43: $t19 := 1 # abort state: {returns,aborts} - # live vars: $t20, $t23 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + # live vars: $t16, $t19 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 48: write_ref($t20, $t23) + 44: write_ref($t16, $t19) # abort state: {returns,aborts} - # live vars: $t20 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + # live vars: $t16 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 49: $t26 := [104, 101, 108, 108, 111] + 45: $t22 := [104, 101, 108, 108, 111] # abort state: {returns,aborts} - # live vars: $t20, $t26 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00} + # live vars: $t16, $t22 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900} # globals: {} # - 50: $t25 := borrow_local($t26) + 46: $t21 := borrow_local($t22) # abort state: {returns,aborts} - # live vars: $t20, $t25 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t25=@3201,$t26=@3200} + # live vars: $t16, $t21 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t21=@2E01,$t22=@2E00} # globals: {} # - 51: $t24 := infer($t25) + 47: $t20 := infer($t21) # abort state: {returns,aborts} - # live vars: $t20, $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t16, $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 52: $t27 := [98, 121, 101] + 48: $t23 := [98, 121, 101] # abort state: {returns,aborts} - # live vars: $t20, $t24, $t27 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t16, $t20, $t23 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 53: write_ref($t24, $t27) + 49: write_ref($t20, $t23) # abort state: {returns,aborts} - # live vars: $t20, $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[borrow(true) -> @2D01],@2D01=derived[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t20=@2D01,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t16, $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[borrow(true) -> @2901],@2901=derived[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t16=@2901,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 54: $t29 := read_ref($t20) + 50: $t25 := read_ref($t16) # abort state: {returns,aborts} - # live vars: $t24, $t29 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20, $t25 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 55: $t30 := 1 + 51: $t26 := 1 # abort state: {returns,aborts} - # live vars: $t24, $t29, $t30 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20, $t25, $t26 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 56: $t28 := ==($t29, $t30) + 52: $t24 := ==($t25, $t26) # abort state: {returns,aborts} - # live vars: $t24, $t28 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20, $t24 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 57: if ($t28) goto 58 else goto 60 + 53: if ($t24) goto 54 else goto 56 # abort state: {returns,aborts} - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 58: label L12 + 54: label L12 # abort state: {returns,aborts} - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 59: goto 63 + 55: goto 59 # abort state: {aborts} - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 60: label L13 + 56: label L13 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 61: $t31 := 42 + 57: $t27 := 42 # abort state: {aborts} - # live vars: $t31 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t27 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 62: abort($t31) + 58: abort($t27) # abort state: {returns,aborts} - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 63: label L14 + 59: label L14 # abort state: {returns,aborts} - # live vars: $t24 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[borrow(true) -> @3201],@3201=derived[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t24=@3201,$t26=@3200} + # live vars: $t20 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[borrow(true) -> @2E01],@2E01=derived[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t20=@2E01,$t22=@2E00} # globals: {} # - 64: $t33 := read_ref($t24) + 60: $t29 := read_ref($t20) # abort state: {returns,aborts} - # live vars: $t33 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t29 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 65: $t34 := [98, 121, 101] + 61: $t30 := [98, 121, 101] # abort state: {returns,aborts} - # live vars: $t33, $t34 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t29, $t30 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 66: $t32 := ==($t33, $t34) + 62: $t28 := ==($t29, $t30) # abort state: {returns,aborts} - # live vars: $t32 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t28 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 67: if ($t32) goto 68 else goto 70 + 63: if ($t28) goto 64 else goto 66 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 68: label L15 + 64: label L15 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 69: goto 73 + 65: goto 69 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 70: label L16 + 66: label L16 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 71: $t35 := 42 + 67: $t31 := 42 # abort state: {aborts} - # live vars: $t35 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t31 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 72: abort($t35) + 68: abort($t31) # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 73: label L17 + 69: label L17 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 74: $t37 := 0 - # abort state: {returns,aborts} - # live vars: $t37 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 75: $t38 := 0 + 70: $t32 := true # abort state: {returns,aborts} - # live vars: $t37, $t38 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 76: $t36 := ==($t37, $t38) - # abort state: {returns,aborts} - # live vars: $t36 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t32 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 77: if ($t36) goto 78 else goto 80 + 71: if ($t32) goto 72 else goto 74 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 78: label L18 + 72: label L18 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 79: goto 83 + 73: goto 77 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 80: label L19 + 74: label L19 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 81: $t39 := 42 + 75: $t33 := 42 # abort state: {aborts} - # live vars: $t39 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t33 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 82: abort($t39) + 76: abort($t33) # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 83: label L20 + 77: label L20 # abort state: {returns,aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 84: $t41 := [104, 101, 108, 108, 111] + 78: $t34 := true # abort state: {returns,aborts} - # live vars: $t41 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t34 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 85: $t42 := [104, 101, 108, 108, 111] - # abort state: {returns,aborts} - # live vars: $t41, $t42 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 86: $t40 := ==($t41, $t42) - # abort state: {returns,aborts} - # live vars: $t40 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} - # globals: {} - # - 87: if ($t40) goto 88 else goto 90 + 79: if ($t34) goto 80 else goto 82 # abort state: {returns} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 88: label L21 + 80: label L21 # abort state: {returns} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 89: goto 93 + 81: goto 85 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 90: label L22 + 82: label L22 # abort state: {aborts} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 91: $t43 := 42 + 83: $t35 := 42 # abort state: {aborts} - # live vars: $t43 - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # live vars: $t35 + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 92: abort($t43) + 84: abort($t35) # abort state: {returns} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 93: label L23 + 85: label L23 # abort state: {returns} # live vars: - # graph: {@1500=local($t11)[],@2100=local($t17)[],@2D00=local($t22)[],@3200=local($t26)[]} - # locals: {$t11=@1500,$t17=@2100,$t22=@2D00,$t26=@3200} + # graph: {@1100=local($t7)[],@1D00=local($t13)[],@2900=local($t18)[],@2E00=local($t22)[]} + # locals: {$t7=@1100,$t13=@1D00,$t18=@2900,$t22=@2E00} # globals: {} # - 94: return () + 86: return () } ============ after AbilityProcessor: ================ @@ -1724,142 +1564,126 @@ fun _0::check() { fun _0::check() { var $t0: bool var $t1: u64 - var $t2: u64 + var $t2: bool var $t3: u64 var $t4: bool - var $t5: vector - var $t6: vector + var $t5: u64 + var $t6: &u64 var $t7: u64 - var $t8: bool + var $t8: u64 var $t9: u64 - var $t10: &u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: bool - var $t15: vector - var $t16: &vector - var $t17: vector - var $t18: vector + var $t10: bool + var $t11: vector + var $t12: &vector + var $t13: vector + var $t14: vector + var $t15: u64 + var $t16: &mut u64 + var $t17: &mut u64 + var $t18: u64 var $t19: u64 - var $t20: &mut u64 - var $t21: &mut u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - var $t25: &mut vector - var $t26: vector - var $t27: vector + var $t20: &mut vector + var $t21: &mut vector + var $t22: vector + var $t23: vector + var $t24: bool + var $t25: u64 + var $t26: u64 + var $t27: u64 var $t28: bool - var $t29: u64 - var $t30: u64 + var $t29: vector + var $t30: vector var $t31: u64 var $t32: bool - var $t33: vector - var $t34: vector + var $t33: u64 + var $t34: bool var $t35: u64 - var $t36: bool - var $t37: u64 - var $t38: u64 - var $t39: u64 - var $t40: bool - var $t41: vector - var $t42: vector - var $t43: u64 - 0: $t1 := 0 - 1: $t2 := 0 - 2: $t0 := ==($t1, $t2) - 3: if ($t0) goto 4 else goto 6 - 4: label L0 - 5: goto 9 - 6: label L1 - 7: $t3 := 42 - 8: abort($t3) - 9: label L2 - 10: $t5 := [104, 101, 108, 108, 111] - 11: $t6 := [104, 101, 108, 108, 111] - 12: $t4 := ==($t5, $t6) - 13: if ($t4) goto 14 else goto 16 - 14: label L3 - 15: goto 19 - 16: label L4 - 17: $t7 := 42 - 18: abort($t7) - 19: label L5 - 20: $t11 := 0 - 21: $t10 := borrow_local($t11) - 22: $t9 := read_ref($t10) - 23: $t12 := 0 - 24: $t8 := ==($t9, $t12) - 25: if ($t8) goto 26 else goto 28 - 26: label L6 - 27: goto 31 - 28: label L7 - 29: $t13 := 42 - 30: abort($t13) - 31: label L8 - 32: $t17 := [104, 101, 108, 108, 111] - 33: $t16 := borrow_local($t17) - 34: $t15 := read_ref($t16) - 35: $t18 := [104, 101, 108, 108, 111] - 36: $t14 := ==($t15, $t18) - 37: if ($t14) goto 38 else goto 40 - 38: label L9 - 39: goto 43 - 40: label L10 - 41: $t19 := 42 - 42: abort($t19) - 43: label L11 - 44: $t22 := 0 - 45: $t21 := borrow_local($t22) - 46: $t20 := move($t21) - 47: $t23 := 1 - 48: write_ref($t20, $t23) - 49: $t26 := [104, 101, 108, 108, 111] - 50: $t25 := borrow_local($t26) - 51: $t24 := move($t25) - 52: $t27 := [98, 121, 101] - 53: write_ref($t24, $t27) - 54: $t29 := read_ref($t20) - 55: $t30 := 1 - 56: $t28 := ==($t29, $t30) - 57: if ($t28) goto 58 else goto 60 - 58: label L12 - 59: goto 64 - 60: label L13 - 61: drop($t24) - 62: $t31 := 42 - 63: abort($t31) - 64: label L14 - 65: $t33 := read_ref($t24) - 66: $t34 := [98, 121, 101] - 67: $t32 := ==($t33, $t34) - 68: if ($t32) goto 69 else goto 71 - 69: label L15 - 70: goto 74 - 71: label L16 - 72: $t35 := 42 - 73: abort($t35) - 74: label L17 - 75: $t37 := 0 - 76: $t38 := 0 - 77: $t36 := ==($t37, $t38) - 78: if ($t36) goto 79 else goto 81 - 79: label L18 - 80: goto 84 - 81: label L19 - 82: $t39 := 42 - 83: abort($t39) - 84: label L20 - 85: $t41 := [104, 101, 108, 108, 111] - 86: $t42 := [104, 101, 108, 108, 111] - 87: $t40 := ==($t41, $t42) - 88: if ($t40) goto 89 else goto 91 - 89: label L21 - 90: goto 94 - 91: label L22 - 92: $t43 := 42 - 93: abort($t43) - 94: label L23 - 95: return () + 0: $t0 := true + 1: if ($t0) goto 2 else goto 4 + 2: label L0 + 3: goto 7 + 4: label L1 + 5: $t1 := 42 + 6: abort($t1) + 7: label L2 + 8: $t2 := true + 9: if ($t2) goto 10 else goto 12 + 10: label L3 + 11: goto 15 + 12: label L4 + 13: $t3 := 42 + 14: abort($t3) + 15: label L5 + 16: $t7 := 0 + 17: $t6 := borrow_local($t7) + 18: $t5 := read_ref($t6) + 19: $t8 := 0 + 20: $t4 := ==($t5, $t8) + 21: if ($t4) goto 22 else goto 24 + 22: label L6 + 23: goto 27 + 24: label L7 + 25: $t9 := 42 + 26: abort($t9) + 27: label L8 + 28: $t13 := [104, 101, 108, 108, 111] + 29: $t12 := borrow_local($t13) + 30: $t11 := read_ref($t12) + 31: $t14 := [104, 101, 108, 108, 111] + 32: $t10 := ==($t11, $t14) + 33: if ($t10) goto 34 else goto 36 + 34: label L9 + 35: goto 39 + 36: label L10 + 37: $t15 := 42 + 38: abort($t15) + 39: label L11 + 40: $t18 := 0 + 41: $t17 := borrow_local($t18) + 42: $t16 := move($t17) + 43: $t19 := 1 + 44: write_ref($t16, $t19) + 45: $t22 := [104, 101, 108, 108, 111] + 46: $t21 := borrow_local($t22) + 47: $t20 := move($t21) + 48: $t23 := [98, 121, 101] + 49: write_ref($t20, $t23) + 50: $t25 := read_ref($t16) + 51: $t26 := 1 + 52: $t24 := ==($t25, $t26) + 53: if ($t24) goto 54 else goto 56 + 54: label L12 + 55: goto 60 + 56: label L13 + 57: drop($t20) + 58: $t27 := 42 + 59: abort($t27) + 60: label L14 + 61: $t29 := read_ref($t20) + 62: $t30 := [98, 121, 101] + 63: $t28 := ==($t29, $t30) + 64: if ($t28) goto 65 else goto 67 + 65: label L15 + 66: goto 70 + 67: label L16 + 68: $t31 := 42 + 69: abort($t31) + 70: label L17 + 71: $t32 := true + 72: if ($t32) goto 73 else goto 75 + 73: label L18 + 74: goto 78 + 75: label L19 + 76: $t33 := 42 + 77: abort($t33) + 78: label L20 + 79: $t34 := true + 80: if ($t34) goto 81 else goto 83 + 81: label L21 + 82: goto 86 + 83: label L22 + 84: $t35 := 42 + 85: abort($t35) + 86: label L23 + 87: return () } diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp b/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp index ab7df85d03331..63bbcb2991125 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/dead_but_borrowed.exp @@ -3,16 +3,14 @@ [variant baseline] fun explicate_drop::test0(): u8 { var $t0: u8 - var $t1: u8 - var $t2: u8 - var $t3: &u8 - var $t4: &u8 - 0: $t2 := 42 - 1: $t1 := infer($t2) - 2: $t4 := borrow_local($t1) - 3: $t3 := infer($t4) - 4: $t0 := read_ref($t3) - 5: return $t0 + var $t1: &u8 + var $t2: &u8 + var $t3: u8 + 0: $t3 := 42 + 1: $t2 := borrow_local($t3) + 2: $t1 := infer($t2) + 3: $t0 := read_ref($t1) + 4: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -20,22 +18,19 @@ fun explicate_drop::test0(): u8 { [variant baseline] fun explicate_drop::test0(): u8 { var $t0: u8 - var $t1: u8 - var $t2: u8 - var $t3: &u8 - var $t4: &u8 + var $t1: &u8 + var $t2: &u8 + var $t3: u8 # live vars: - 0: $t2 := 42 + 0: $t3 := 42 + # live vars: $t3 + 1: $t2 := borrow_local($t3) # live vars: $t2 - 1: $t1 := infer($t2) + 2: $t1 := infer($t2) # live vars: $t1 - 2: $t4 := borrow_local($t1) - # live vars: $t4 - 3: $t3 := infer($t4) - # live vars: $t3 - 4: $t0 := read_ref($t3) + 3: $t0 := read_ref($t1) # live vars: $t0 - 5: return $t0 + 4: return $t0 } ============ after ReferenceSafetyProcessor: ================ @@ -43,46 +38,39 @@ fun explicate_drop::test0(): u8 { [variant baseline] fun explicate_drop::test0(): u8 { var $t0: u8 - var $t1: u8 - var $t2: u8 - var $t3: &u8 - var $t4: &u8 + var $t1: &u8 + var $t2: &u8 + var $t3: u8 # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t2 := 42 - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t1 := infer($t2) - # live vars: $t1 + 0: $t3 := 42 + # live vars: $t3 # graph: {} # locals: {} # globals: {} # - 2: $t4 := borrow_local($t1) - # live vars: $t4 - # graph: {@200=local($t1)[borrow(false) -> @201],@201=derived[]} - # locals: {$t1=@200,$t4=@201} + 1: $t2 := borrow_local($t3) + # live vars: $t2 + # graph: {@100=local($t3)[borrow(false) -> @101],@101=derived[]} + # locals: {$t2=@101,$t3=@100} # globals: {} # - 3: $t3 := infer($t4) - # live vars: $t3 - # graph: {@200=local($t1)[borrow(false) -> @201],@201=derived[]} - # locals: {$t1=@200,$t3=@201} + 2: $t1 := infer($t2) + # live vars: $t1 + # graph: {@100=local($t3)[borrow(false) -> @101],@101=derived[]} + # locals: {$t1=@101,$t3=@100} # globals: {} # - 4: $t0 := read_ref($t3) + 3: $t0 := read_ref($t1) # live vars: $t0 - # graph: {@200=local($t1)[]} - # locals: {$t1=@200} + # graph: {@100=local($t3)[]} + # locals: {$t3=@100} # globals: {} # - 5: return $t0 + 4: return $t0 } ============ after AbortAnalysisProcessor: ================ @@ -90,52 +78,44 @@ fun explicate_drop::test0(): u8 { [variant baseline] fun explicate_drop::test0(): u8 { var $t0: u8 - var $t1: u8 - var $t2: u8 - var $t3: &u8 - var $t4: &u8 + var $t1: &u8 + var $t2: &u8 + var $t3: u8 # abort state: {returns} # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t2 := 42 + 0: $t3 := 42 # abort state: {returns} - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t1 := infer($t2) - # abort state: {returns} - # live vars: $t1 + # live vars: $t3 # graph: {} # locals: {} # globals: {} # - 2: $t4 := borrow_local($t1) + 1: $t2 := borrow_local($t3) # abort state: {returns} - # live vars: $t4 - # graph: {@200=local($t1)[borrow(false) -> @201],@201=derived[]} - # locals: {$t1=@200,$t4=@201} + # live vars: $t2 + # graph: {@100=local($t3)[borrow(false) -> @101],@101=derived[]} + # locals: {$t2=@101,$t3=@100} # globals: {} # - 3: $t3 := infer($t4) + 2: $t1 := infer($t2) # abort state: {returns} - # live vars: $t3 - # graph: {@200=local($t1)[borrow(false) -> @201],@201=derived[]} - # locals: {$t1=@200,$t3=@201} + # live vars: $t1 + # graph: {@100=local($t3)[borrow(false) -> @101],@101=derived[]} + # locals: {$t1=@101,$t3=@100} # globals: {} # - 4: $t0 := read_ref($t3) + 3: $t0 := read_ref($t1) # abort state: {returns} # live vars: $t0 - # graph: {@200=local($t1)[]} - # locals: {$t1=@200} + # graph: {@100=local($t3)[]} + # locals: {$t3=@100} # globals: {} # - 5: return $t0 + 4: return $t0 } ============ after AbilityProcessor: ================ @@ -143,14 +123,12 @@ fun explicate_drop::test0(): u8 { [variant baseline] fun explicate_drop::test0(): u8 { var $t0: u8 - var $t1: u8 - var $t2: u8 - var $t3: &u8 - var $t4: &u8 - 0: $t2 := 42 - 1: $t1 := move($t2) - 2: $t4 := borrow_local($t1) - 3: $t3 := move($t4) - 4: $t0 := read_ref($t3) - 5: return $t0 + var $t1: &u8 + var $t2: &u8 + var $t3: u8 + 0: $t3 := 42 + 1: $t2 := borrow_local($t3) + 2: $t1 := move($t2) + 3: $t0 := read_ref($t1) + 4: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp b/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp index cfd0818c613f5..14f50f0dde338 100644 --- a/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp +++ b/third_party/move/move-compiler-v2/tests/ability-transform/foreach_mut_expanded.exp @@ -8,66 +8,54 @@ fun m::test_for_each_mut() { var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - var $t9: &vector - var $t10: &mut vector - var $t11: &mut vector - var $t12: bool - var $t13: &mut u64 - var $t14: &mut u64 - var $t15: u64 - var $t16: u64 + var $t6: &vector + var $t7: &mut vector + var $t8: &mut vector + var $t9: bool + var $t10: &mut u64 + var $t11: &mut u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: vector var $t17: u64 - var $t18: bool - var $t19: vector - var $t20: u64 - var $t21: u64 - var $t22: u64 - var $t23: u64 - 0: $t2 := 1 - 1: $t3 := 2 - 2: $t4 := 3 - 3: $t1 := vector($t2, $t3, $t4) - 4: $t0 := infer($t1) - 5: $t6 := 0 - 6: $t5 := infer($t6) - 7: $t9 := borrow_local($t0) - 8: $t8 := vector::length($t9) - 9: $t7 := infer($t8) - 10: $t11 := borrow_local($t0) - 11: $t10 := infer($t11) - 12: label L0 - 13: $t12 := <($t5, $t7) - 14: if ($t12) goto 15 else goto 24 - 15: label L2 - 16: $t14 := vector::borrow_mut($t10, $t5) - 17: $t13 := infer($t14) - 18: $t15 := 2 - 19: write_ref($t13, $t15) - 20: $t17 := 1 - 21: $t16 := +($t5, $t17) - 22: $t5 := infer($t16) - 23: goto 26 - 24: label L3 - 25: goto 28 - 26: label L4 - 27: goto 12 - 28: label L1 - 29: $t20 := 2 - 30: $t21 := 3 - 31: $t22 := 4 - 32: $t19 := vector($t20, $t21, $t22) - 33: $t18 := ==($t0, $t19) - 34: if ($t18) goto 35 else goto 37 - 35: label L5 - 36: goto 40 - 37: label L6 - 38: $t23 := 0 - 39: abort($t23) - 40: label L7 - 41: return () + 0: $t1 := ["1", "2", "3"] + 1: $t0 := infer($t1) + 2: $t3 := 0 + 3: $t2 := infer($t3) + 4: $t6 := borrow_local($t0) + 5: $t5 := vector::length($t6) + 6: $t4 := infer($t5) + 7: $t8 := borrow_local($t0) + 8: $t7 := infer($t8) + 9: label L0 + 10: $t9 := <($t2, $t4) + 11: if ($t9) goto 12 else goto 21 + 12: label L2 + 13: $t11 := vector::borrow_mut($t7, $t2) + 14: $t10 := infer($t11) + 15: $t12 := 2 + 16: write_ref($t10, $t12) + 17: $t14 := 1 + 18: $t13 := +($t2, $t14) + 19: $t2 := infer($t13) + 20: goto 23 + 21: label L3 + 22: goto 25 + 23: label L4 + 24: goto 9 + 25: label L1 + 26: $t16 := ["2", "3", "4"] + 27: $t15 := ==($t0, $t16) + 28: if ($t15) goto 29 else goto 31 + 29: label L5 + 30: goto 34 + 31: label L6 + 32: $t17 := 0 + 33: abort($t17) + 34: label L7 + 35: return () } ============ after LiveVarAnalysisProcessor: ================ @@ -80,108 +68,90 @@ fun m::test_for_each_mut() { var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - var $t9: &vector - var $t10: &mut vector - var $t11: &mut vector - var $t12: bool - var $t13: &mut u64 - var $t14: &mut u64 - var $t15: u64 - var $t16: u64 + var $t6: &vector + var $t7: &mut vector + var $t8: &mut vector + var $t9: bool + var $t10: &mut u64 + var $t11: &mut u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: vector var $t17: u64 - var $t18: bool - var $t19: vector - var $t20: u64 - var $t21: u64 - var $t22: u64 - var $t23: u64 # live vars: - 0: $t2 := 1 - # live vars: $t2 - 1: $t3 := 2 - # live vars: $t2, $t3 - 2: $t4 := 3 - # live vars: $t2, $t3, $t4 - 3: $t1 := vector($t2, $t3, $t4) + 0: $t1 := ["1", "2", "3"] # live vars: $t1 - 4: $t0 := infer($t1) + 1: $t0 := infer($t1) # live vars: $t0 - 5: $t6 := 0 - # live vars: $t0, $t6 - 6: $t5 := infer($t6) - # live vars: $t0, $t5 - 7: $t9 := borrow_local($t0) - # live vars: $t0, $t5, $t9 - 8: $t8 := vector::length($t9) - # live vars: $t0, $t5, $t8 - 9: $t7 := infer($t8) - # live vars: $t0, $t5, $t7 - 10: $t11 := borrow_local($t0) - # live vars: $t0, $t5, $t7, $t11 - 11: $t10 := infer($t11) - # live vars: $t0, $t5, $t7, $t10 - 12: label L0 - # live vars: $t0, $t5, $t7, $t10 - 13: $t12 := <($t5, $t7) - # live vars: $t0, $t5, $t7, $t10, $t12 - 14: if ($t12) goto 15 else goto 24 - # live vars: $t0, $t5, $t7, $t10 - 15: label L2 - # live vars: $t0, $t5, $t7, $t10 - 16: $t14 := vector::borrow_mut($t10, $t5) - # live vars: $t0, $t5, $t7, $t10, $t14 - 17: $t13 := infer($t14) - # live vars: $t0, $t5, $t7, $t10, $t13 - 18: $t15 := 2 - # live vars: $t0, $t5, $t7, $t10, $t13, $t15 - 19: write_ref($t13, $t15) - # live vars: $t0, $t5, $t7, $t10 - 20: $t17 := 1 - # live vars: $t0, $t5, $t7, $t10, $t17 - 21: $t16 := +($t5, $t17) - # live vars: $t0, $t7, $t10, $t16 - 22: $t5 := infer($t16) - # live vars: $t0, $t5, $t7, $t10 - 23: goto 26 - # live vars: $t0, $t5, $t7, $t10 - 24: label L3 + 2: $t3 := 0 + # live vars: $t0, $t3 + 3: $t2 := infer($t3) + # live vars: $t0, $t2 + 4: $t6 := borrow_local($t0) + # live vars: $t0, $t2, $t6 + 5: $t5 := vector::length($t6) + # live vars: $t0, $t2, $t5 + 6: $t4 := infer($t5) + # live vars: $t0, $t2, $t4 + 7: $t8 := borrow_local($t0) + # live vars: $t0, $t2, $t4, $t8 + 8: $t7 := infer($t8) + # live vars: $t0, $t2, $t4, $t7 + 9: label L0 + # live vars: $t0, $t2, $t4, $t7 + 10: $t9 := <($t2, $t4) + # live vars: $t0, $t2, $t4, $t7, $t9 + 11: if ($t9) goto 12 else goto 21 + # live vars: $t0, $t2, $t4, $t7 + 12: label L2 + # live vars: $t0, $t2, $t4, $t7 + 13: $t11 := vector::borrow_mut($t7, $t2) + # live vars: $t0, $t2, $t4, $t7, $t11 + 14: $t10 := infer($t11) + # live vars: $t0, $t2, $t4, $t7, $t10 + 15: $t12 := 2 + # live vars: $t0, $t2, $t4, $t7, $t10, $t12 + 16: write_ref($t10, $t12) + # live vars: $t0, $t2, $t4, $t7 + 17: $t14 := 1 + # live vars: $t0, $t2, $t4, $t7, $t14 + 18: $t13 := +($t2, $t14) + # live vars: $t0, $t4, $t7, $t13 + 19: $t2 := infer($t13) + # live vars: $t0, $t2, $t4, $t7 + 20: goto 23 + # live vars: $t0, $t2, $t4, $t7 + 21: label L3 # live vars: $t0 - 25: goto 28 - # live vars: $t0, $t5, $t7, $t10 - 26: label L4 - # live vars: $t0, $t5, $t7, $t10 - 27: goto 12 + 22: goto 25 + # live vars: $t0, $t2, $t4, $t7 + 23: label L4 + # live vars: $t0, $t2, $t4, $t7 + 24: goto 9 # live vars: $t0 - 28: label L1 + 25: label L1 # live vars: $t0 - 29: $t20 := 2 - # live vars: $t0, $t20 - 30: $t21 := 3 - # live vars: $t0, $t20, $t21 - 31: $t22 := 4 - # live vars: $t0, $t20, $t21, $t22 - 32: $t19 := vector($t20, $t21, $t22) - # live vars: $t0, $t19 - 33: $t18 := ==($t0, $t19) - # live vars: $t18 - 34: if ($t18) goto 35 else goto 37 + 26: $t16 := ["2", "3", "4"] + # live vars: $t0, $t16 + 27: $t15 := ==($t0, $t16) + # live vars: $t15 + 28: if ($t15) goto 29 else goto 31 # live vars: - 35: label L5 + 29: label L5 # live vars: - 36: goto 40 + 30: goto 34 # live vars: - 37: label L6 + 31: label L6 # live vars: - 38: $t23 := 0 - # live vars: $t23 - 39: abort($t23) + 32: $t17 := 0 + # live vars: $t17 + 33: abort($t17) # live vars: - 40: label L7 + 34: label L7 # live vars: - 41: return () + 35: return () } ============ after ReferenceSafetyProcessor: ================ @@ -194,276 +164,234 @@ fun m::test_for_each_mut() { var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - var $t9: &vector - var $t10: &mut vector - var $t11: &mut vector - var $t12: bool - var $t13: &mut u64 - var $t14: &mut u64 - var $t15: u64 - var $t16: u64 + var $t6: &vector + var $t7: &mut vector + var $t8: &mut vector + var $t9: bool + var $t10: &mut u64 + var $t11: &mut u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: vector var $t17: u64 - var $t18: bool - var $t19: vector - var $t20: u64 - var $t21: u64 - var $t22: u64 - var $t23: u64 # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t2 := 1 - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t3 := 2 - # live vars: $t2, $t3 - # graph: {} - # locals: {} - # globals: {} - # - 2: $t4 := 3 - # live vars: $t2, $t3, $t4 - # graph: {} - # locals: {} - # globals: {} - # - 3: $t1 := vector($t2, $t3, $t4) + 0: $t1 := ["1", "2", "3"] # live vars: $t1 # graph: {} # locals: {} # globals: {} # - 4: $t0 := infer($t1) + 1: $t0 := infer($t1) # live vars: $t0 # graph: {} # locals: {} # globals: {} # - 5: $t6 := 0 - # live vars: $t0, $t6 + 2: $t3 := 0 + # live vars: $t0, $t3 # graph: {} # locals: {} # globals: {} # - 6: $t5 := infer($t6) - # live vars: $t0, $t5 + 3: $t2 := infer($t3) + # live vars: $t0, $t2 # graph: {} # locals: {} # globals: {} # - 7: $t9 := borrow_local($t0) - # live vars: $t0, $t5, $t9 - # graph: {@700=local($t0)[borrow(false) -> @701],@701=derived[]} - # locals: {$t0=@700,$t9=@701} + 4: $t6 := borrow_local($t0) + # live vars: $t0, $t2, $t6 + # graph: {@400=local($t0)[borrow(false) -> @401],@401=derived[]} + # locals: {$t0=@400,$t6=@401} # globals: {} # - 8: $t8 := vector::length($t9) - # live vars: $t0, $t5, $t8 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + 5: $t5 := vector::length($t6) + # live vars: $t0, $t2, $t5 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 9: $t7 := infer($t8) - # live vars: $t0, $t5, $t7 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + 6: $t4 := infer($t5) + # live vars: $t0, $t2, $t4 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 10: $t11 := borrow_local($t0) - # live vars: $t0, $t5, $t7, $t11 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t11=@A01} + 7: $t8 := borrow_local($t0) + # live vars: $t0, $t2, $t4, $t8 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t8=@701} # globals: {} # - 11: $t10 := infer($t11) - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 8: $t7 := infer($t8) + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 12: label L0 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 9: label L0 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 13: $t12 := <($t5, $t7) - # live vars: $t0, $t5, $t7, $t10, $t12 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 10: $t9 := <($t2, $t4) + # live vars: $t0, $t2, $t4, $t7, $t9 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 14: if ($t12) goto 15 else goto 24 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 11: if ($t9) goto 12 else goto 21 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 15: label L2 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 12: label L2 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 16: $t14 := vector::borrow_mut($t10, $t5) - # live vars: $t0, $t5, $t7, $t10, $t14 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t14=@1000} + 13: $t11 := vector::borrow_mut($t7, $t2) + # live vars: $t0, $t2, $t4, $t7, $t11 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t11=@D00} # globals: {} # - 17: $t13 := infer($t14) - # live vars: $t0, $t5, $t7, $t10, $t13 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t13=@1000} + 14: $t10 := infer($t11) + # live vars: $t0, $t2, $t4, $t7, $t10 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t10=@D00} # globals: {} # - 18: $t15 := 2 - # live vars: $t0, $t5, $t7, $t10, $t13, $t15 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t13=@1000} + 15: $t12 := 2 + # live vars: $t0, $t2, $t4, $t7, $t10, $t12 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t10=@D00} # globals: {} # - 19: write_ref($t13, $t15) - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 16: write_ref($t10, $t12) + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 20: $t17 := 1 - # live vars: $t0, $t5, $t7, $t10, $t17 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 17: $t14 := 1 + # live vars: $t0, $t2, $t4, $t7, $t14 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 21: $t16 := +($t5, $t17) - # live vars: $t0, $t7, $t10, $t16 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 18: $t13 := +($t2, $t14) + # live vars: $t0, $t4, $t7, $t13 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 22: $t5 := infer($t16) - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 19: $t2 := infer($t13) + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 23: goto 26 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 20: goto 23 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 24: label L3 + 21: label L3 # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 25: goto 28 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 22: goto 25 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 26: label L4 - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + 23: label L4 + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 27: goto 12 + 24: goto 9 # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 28: label L1 + 25: label L1 # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 29: $t20 := 2 - # live vars: $t0, $t20 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 30: $t21 := 3 - # live vars: $t0, $t20, $t21 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 31: $t22 := 4 - # live vars: $t0, $t20, $t21, $t22 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + 26: $t16 := ["2", "3", "4"] + # live vars: $t0, $t16 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 32: $t19 := vector($t20, $t21, $t22) - # live vars: $t0, $t19 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + 27: $t15 := ==($t0, $t16) + # live vars: $t15 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 33: $t18 := ==($t0, $t19) - # live vars: $t18 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 34: if ($t18) goto 35 else goto 37 + 28: if ($t15) goto 29 else goto 31 # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 35: label L5 + 29: label L5 # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 36: goto 40 + 30: goto 34 # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 37: label L6 + 31: label L6 # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 38: $t23 := 0 - # live vars: $t23 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + 32: $t17 := 0 + # live vars: $t17 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 39: abort($t23) + 33: abort($t17) # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 40: label L7 + 34: label L7 # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 41: return () + 35: return () } ============ after AbortAnalysisProcessor: ================ @@ -476,318 +404,270 @@ fun m::test_for_each_mut() { var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - var $t9: &vector - var $t10: &mut vector - var $t11: &mut vector - var $t12: bool - var $t13: &mut u64 - var $t14: &mut u64 - var $t15: u64 - var $t16: u64 + var $t6: &vector + var $t7: &mut vector + var $t8: &mut vector + var $t9: bool + var $t10: &mut u64 + var $t11: &mut u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: vector var $t17: u64 - var $t18: bool - var $t19: vector - var $t20: u64 - var $t21: u64 - var $t22: u64 - var $t23: u64 # abort state: {returns,aborts} # live vars: # graph: {} # locals: {} # globals: {} # - 0: $t2 := 1 - # abort state: {returns,aborts} - # live vars: $t2 - # graph: {} - # locals: {} - # globals: {} - # - 1: $t3 := 2 - # abort state: {returns,aborts} - # live vars: $t2, $t3 - # graph: {} - # locals: {} - # globals: {} - # - 2: $t4 := 3 - # abort state: {returns,aborts} - # live vars: $t2, $t3, $t4 - # graph: {} - # locals: {} - # globals: {} - # - 3: $t1 := vector($t2, $t3, $t4) + 0: $t1 := ["1", "2", "3"] # abort state: {returns,aborts} # live vars: $t1 # graph: {} # locals: {} # globals: {} # - 4: $t0 := infer($t1) + 1: $t0 := infer($t1) # abort state: {returns,aborts} # live vars: $t0 # graph: {} # locals: {} # globals: {} # - 5: $t6 := 0 + 2: $t3 := 0 # abort state: {returns,aborts} - # live vars: $t0, $t6 + # live vars: $t0, $t3 # graph: {} # locals: {} # globals: {} # - 6: $t5 := infer($t6) + 3: $t2 := infer($t3) # abort state: {returns,aborts} - # live vars: $t0, $t5 + # live vars: $t0, $t2 # graph: {} # locals: {} # globals: {} # - 7: $t9 := borrow_local($t0) + 4: $t6 := borrow_local($t0) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t9 - # graph: {@700=local($t0)[borrow(false) -> @701],@701=derived[]} - # locals: {$t0=@700,$t9=@701} + # live vars: $t0, $t2, $t6 + # graph: {@400=local($t0)[borrow(false) -> @401],@401=derived[]} + # locals: {$t0=@400,$t6=@401} # globals: {} # - 8: $t8 := vector::length($t9) + 5: $t5 := vector::length($t6) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t8 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # live vars: $t0, $t2, $t5 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 9: $t7 := infer($t8) + 6: $t4 := infer($t5) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # live vars: $t0, $t2, $t4 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 10: $t11 := borrow_local($t0) + 7: $t8 := borrow_local($t0) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t11 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t11=@A01} + # live vars: $t0, $t2, $t4, $t8 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t8=@701} # globals: {} # - 11: $t10 := infer($t11) + 8: $t7 := infer($t8) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 12: label L0 + 9: label L0 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 13: $t12 := <($t5, $t7) + 10: $t9 := <($t2, $t4) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10, $t12 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7, $t9 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 14: if ($t12) goto 15 else goto 24 + 11: if ($t9) goto 12 else goto 21 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 15: label L2 + 12: label L2 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 16: $t14 := vector::borrow_mut($t10, $t5) + 13: $t11 := vector::borrow_mut($t7, $t2) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10, $t14 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t14=@1000} + # live vars: $t0, $t2, $t4, $t7, $t11 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t11=@D00} # globals: {} # - 17: $t13 := infer($t14) + 14: $t10 := infer($t11) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10, $t13 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t13=@1000} + # live vars: $t0, $t2, $t4, $t7, $t10 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t10=@D00} # globals: {} # - 18: $t15 := 2 + 15: $t12 := 2 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10, $t13, $t15 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[call(true) -> @1000],@1000=derived[]} - # locals: {$t0=@700,$t10=@A01,$t13=@1000} + # live vars: $t0, $t2, $t4, $t7, $t10, $t12 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[call(true) -> @D00],@D00=derived[]} + # locals: {$t0=@400,$t7=@701,$t10=@D00} # globals: {} # - 19: write_ref($t13, $t15) + 16: write_ref($t10, $t12) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 20: $t17 := 1 + 17: $t14 := 1 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10, $t17 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7, $t14 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 21: $t16 := +($t5, $t17) + 18: $t13 := +($t2, $t14) # abort state: {returns,aborts} - # live vars: $t0, $t7, $t10, $t16 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t4, $t7, $t13 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 22: $t5 := infer($t16) + 19: $t2 := infer($t13) # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 23: goto 26 + 20: goto 23 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 24: label L3 + 21: label L3 # abort state: {returns,aborts} # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 25: goto 28 + 22: goto 25 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 26: label L4 + 23: label L4 # abort state: {returns,aborts} - # live vars: $t0, $t5, $t7, $t10 - # graph: {@700=local($t0)[borrow(true) -> @A01],@A01=derived[]} - # locals: {$t0=@700,$t10=@A01} + # live vars: $t0, $t2, $t4, $t7 + # graph: {@400=local($t0)[borrow(true) -> @701],@701=derived[]} + # locals: {$t0=@400,$t7=@701} # globals: {} # - 27: goto 12 + 24: goto 9 # abort state: {returns,aborts} # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 28: label L1 + 25: label L1 # abort state: {returns,aborts} # live vars: $t0 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 29: $t20 := 2 - # abort state: {returns,aborts} - # live vars: $t0, $t20 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 30: $t21 := 3 - # abort state: {returns,aborts} - # live vars: $t0, $t20, $t21 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} - # globals: {} - # - 31: $t22 := 4 - # abort state: {returns,aborts} - # live vars: $t0, $t20, $t21, $t22 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 32: $t19 := vector($t20, $t21, $t22) + 26: $t16 := ["2", "3", "4"] # abort state: {returns,aborts} - # live vars: $t0, $t19 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # live vars: $t0, $t16 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 33: $t18 := ==($t0, $t19) + 27: $t15 := ==($t0, $t16) # abort state: {returns,aborts} - # live vars: $t18 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # live vars: $t15 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 34: if ($t18) goto 35 else goto 37 + 28: if ($t15) goto 29 else goto 31 # abort state: {returns} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 35: label L5 + 29: label L5 # abort state: {returns} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 36: goto 40 + 30: goto 34 # abort state: {aborts} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 37: label L6 + 31: label L6 # abort state: {aborts} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 38: $t23 := 0 + 32: $t17 := 0 # abort state: {aborts} - # live vars: $t23 - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # live vars: $t17 + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 39: abort($t23) + 33: abort($t17) # abort state: {returns} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 40: label L7 + 34: label L7 # abort state: {returns} # live vars: - # graph: {@700=local($t0)[]} - # locals: {$t0=@700} + # graph: {@400=local($t0)[]} + # locals: {$t0=@400} # globals: {} # - 41: return () + 35: return () } ============ after AbilityProcessor: ================ @@ -800,67 +680,55 @@ fun m::test_for_each_mut() { var $t3: u64 var $t4: u64 var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - var $t9: &vector - var $t10: &mut vector - var $t11: &mut vector - var $t12: bool - var $t13: &mut u64 - var $t14: &mut u64 - var $t15: u64 - var $t16: u64 + var $t6: &vector + var $t7: &mut vector + var $t8: &mut vector + var $t9: bool + var $t10: &mut u64 + var $t11: &mut u64 + var $t12: u64 + var $t13: u64 + var $t14: u64 + var $t15: bool + var $t16: vector var $t17: u64 - var $t18: bool - var $t19: vector - var $t20: u64 - var $t21: u64 - var $t22: u64 - var $t23: u64 - var $t24: &mut vector - 0: $t2 := 1 - 1: $t3 := 2 - 2: $t4 := 3 - 3: $t1 := vector($t2, $t3, $t4) - 4: $t0 := move($t1) - 5: $t6 := 0 - 6: $t5 := move($t6) - 7: $t9 := borrow_local($t0) - 8: $t8 := vector::length($t9) - 9: $t7 := move($t8) - 10: $t11 := borrow_local($t0) - 11: $t10 := move($t11) - 12: label L0 - 13: $t12 := <($t5, $t7) - 14: if ($t12) goto 15 else goto 25 - 15: label L2 - 16: $t24 := copy($t10) - 17: $t14 := vector::borrow_mut($t24, $t5) - 18: $t13 := move($t14) - 19: $t15 := 2 - 20: write_ref($t13, $t15) - 21: $t17 := 1 - 22: $t16 := +($t5, $t17) - 23: $t5 := move($t16) - 24: goto 28 - 25: label L3 - 26: drop($t10) - 27: goto 30 - 28: label L4 - 29: goto 12 - 30: label L1 - 31: $t20 := 2 - 32: $t21 := 3 - 33: $t22 := 4 - 34: $t19 := vector($t20, $t21, $t22) - 35: $t18 := ==($t0, $t19) - 36: if ($t18) goto 37 else goto 39 - 37: label L5 - 38: goto 42 - 39: label L6 - 40: $t23 := 0 - 41: abort($t23) - 42: label L7 - 43: return () + var $t18: &mut vector + 0: $t1 := ["1", "2", "3"] + 1: $t0 := move($t1) + 2: $t3 := 0 + 3: $t2 := move($t3) + 4: $t6 := borrow_local($t0) + 5: $t5 := vector::length($t6) + 6: $t4 := move($t5) + 7: $t8 := borrow_local($t0) + 8: $t7 := move($t8) + 9: label L0 + 10: $t9 := <($t2, $t4) + 11: if ($t9) goto 12 else goto 22 + 12: label L2 + 13: $t18 := copy($t7) + 14: $t11 := vector::borrow_mut($t18, $t2) + 15: $t10 := move($t11) + 16: $t12 := 2 + 17: write_ref($t10, $t12) + 18: $t14 := 1 + 19: $t13 := +($t2, $t14) + 20: $t2 := move($t13) + 21: goto 25 + 22: label L3 + 23: drop($t7) + 24: goto 27 + 25: label L4 + 26: goto 9 + 27: label L1 + 28: $t16 := ["2", "3", "4"] + 29: $t15 := ==($t0, $t16) + 30: if ($t15) goto 31 else goto 33 + 31: label L5 + 32: goto 36 + 33: label L6 + 34: $t17 := 0 + 35: abort($t17) + 36: label L7 + 37: return () } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp index bdd1d77f074fb..33831b169b809 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign.exp @@ -23,10 +23,6 @@ module 0x42::assign { s = pack assign::S(42, pack assign::T(42)); Tuple() } - spec fun $assign_field(s: &mut assign::S,f: u64); - spec fun $assign_int(x: &mut u64); - spec fun $assign_pattern(s: assign::S,f: u64,h: u64): u64; - spec fun $assign_struct(s: &mut assign::S); } // end 0x42::assign ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp index 38976bbc84af9..e141a31f57fd9 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/assign_inline.exp @@ -1,22 +1,7 @@ // -- Model dump before bytecode pipeline module 0x42::assign { public fun main(): (u64, u64) { - { - let (a: u64, b: u64): (u64, u64) = { - let (x: u64): (u64) = Tuple(3); - Tuple(1, x) - }; - Tuple(a, b) - } - } - spec fun $expose(x: u64): (u64, u64) { - Tuple(1, x) - } - spec fun $main(): (u64, u64) { - { - let (a: u64, b: u64): (u64, u64) = assign::$expose(3); - Tuple(a, b) - } + Tuple(1, 3) } } // end 0x42::assign @@ -26,15 +11,7 @@ module 0x42::assign { public fun assign::main(): (u64, u64) { var $t0: u64 var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: u64 - var $t5: u64 - 0: $t5 := 3 - 1: $t4 := infer($t5) - 2: $t2 := 1 - 3: $t3 := infer($t4) - 4: $t0 := infer($t2) - 5: $t1 := infer($t3) - 6: return ($t0, $t1) + 0: $t0 := 1 + 1: $t1 := 3 + 2: return ($t0, $t1) } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp index 9478e860f9f1e..c45361d5ae379 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow.exp @@ -25,11 +25,8 @@ module 0x42::borrow { } private fun local(param: u64): u64 { { - let local: u64 = 33; - { - let r: &u64 = Borrow(Immutable)(local); - Deref(r) - } + let r: &u64 = Borrow(Immutable)(33); + Deref(r) } } private fun param(param: u64): u64 { @@ -62,30 +59,6 @@ module 0x42::borrow { Deref(r) } } - spec fun $field(s: borrow::S): u64 { - { - let r: u64 = select borrow::S.f(s); - r - } - } - spec fun $local(param: u64): u64 { - { - let local: u64 = 33; - { - let r: u64 = local; - r - } - } - } - spec fun $mut_field(s: &mut borrow::S): u64; - spec fun $mut_local(param: u64): u64; - spec fun $mut_param(param: u64): u64; - spec fun $param(param: u64): u64 { - { - let r: u64 = param; - r - } - } } // end 0x42::borrow ============ initial bytecode ================ @@ -105,16 +78,14 @@ fun borrow::field($t0: &borrow::S): u64 { [variant baseline] fun borrow::local($t0: u64): u64 { var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: &u64 - var $t5: &u64 - 0: $t3 := 33 - 1: $t2 := infer($t3) - 2: $t5 := borrow_local($t2) - 3: $t4 := infer($t5) - 4: $t1 := read_ref($t4) - 5: return $t1 + var $t2: &u64 + var $t3: &u64 + var $t4: u64 + 0: $t4 := 33 + 1: $t3 := borrow_local($t4) + 2: $t2 := infer($t3) + 3: $t1 := read_ref($t2) + 4: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_invalid.exp index e79ca0f3018fe..49c886ecdc0ad 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/borrow_invalid.exp @@ -17,8 +17,6 @@ module 0x42::borrow { Deref(r) } } - spec fun $mut_expr(x: u64): u64; - spec fun $mut_field(s: &borrow::S): u64; } // end 0x42::borrow ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp index 3a5818eebefd6..62441e8bbf890 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/conditional_borrow.exp @@ -8,41 +8,35 @@ module 0x8675::M { } private fun test1(r: u64): u64 { { - let x: u64 = 3; + let tref: &mut u64 = Borrow(Mutable)(if Lt(r, 4) { + r + } else { + 3 + }); + tref = 10; { - let tref: &mut u64 = Borrow(Mutable)(if Lt(r, 4) { - r - } else { - x - }); - tref = 10; + let y: u64 = r; { - let y: u64 = r; + let tref2: &mut u64 = Borrow(Mutable)(y); + tref2 = Add(Deref(tref2), 1); { - let tref2: &mut u64 = Borrow(Mutable)(y); - tref2 = Add(Deref(tref2), 1); + let z: u64 = y; { - let z: u64 = y; + let tref3: &mut u64 = Borrow(Mutable)(Add(z, 0)); + tref3 = Add(Deref(tref3), 2); { - let tref3: &mut u64 = Borrow(Mutable)(Add(z, 0)); - tref3 = Add(Deref(tref3), 2); + let a: u64 = z; { - let a: u64 = z; + let tref4: &mut u64 = Borrow(Mutable)(a); + tref4 = Add(Deref(tref4), 4); { - let tref4: &mut u64 = Borrow(Mutable)({ - let _q: u64 = 1; - a - }); - tref4 = Add(Deref(tref4), 4); + let tref5: &mut u64 = Borrow(Mutable)(a); + tref5 = Add(Deref(tref5), 8); { - let tref5: &mut u64 = Borrow(Mutable)(a); - tref5 = Add(Deref(tref5), 8); - { - let tref6: &mut u64 = Borrow(Mutable)(3; - a); - tref6 = Add(Deref(tref6), 16); - a - } + let tref6: &mut u64 = Borrow(Mutable)(3; + a); + tref6 = Add(Deref(tref6), 16); + a } } } @@ -76,10 +70,7 @@ module 0x8675::M { { let a: M::S = z; { - let tref4: &mut u64 = Borrow(Mutable)({ - let _q: u64 = 1; - select M::S.f(a) - }); + let tref4: &mut u64 = Borrow(Mutable)(select M::S.f(a)); tref4 = Add(Deref(tref4), 1); { let tref5: &mut u64 = Borrow(Mutable)(select M::S.f(a)); @@ -103,10 +94,6 @@ module 0x8675::M { public fun testb(): u64 { Add(M::test1b(pack M::S(7)), M::test1b(pack M::S(2))) } - spec fun $test(): u64; - spec fun $test1(r: u64): u64; - spec fun $test1b(r: M::S): u64; - spec fun $testb(): u64; } // end 0x8675::M ============ initial bytecode ================ @@ -130,108 +117,100 @@ public fun M::test(): u64 { [variant baseline] fun M::test1($t0: u64): u64 { var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: &mut u64 - var $t5: &mut u64 + var $t2: &mut u64 + var $t3: &mut u64 + var $t4: u64 + var $t5: bool var $t6: u64 - var $t7: bool + var $t7: u64 var $t8: u64 - var $t9: u64 - var $t10: u64 - var $t11: &mut u64 - var $t12: &mut u64 + var $t9: &mut u64 + var $t10: &mut u64 + var $t11: u64 + var $t12: u64 var $t13: u64 var $t14: u64 - var $t15: u64 - var $t16: u64 - var $t17: &mut u64 - var $t18: &mut u64 + var $t15: &mut u64 + var $t16: &mut u64 + var $t17: u64 + var $t18: u64 var $t19: u64 var $t20: u64 var $t21: u64 var $t22: u64 - var $t23: u64 - var $t24: u64 - var $t25: &mut u64 - var $t26: &mut u64 + var $t23: &mut u64 + var $t24: &mut u64 + var $t25: u64 + var $t26: u64 var $t27: u64 var $t28: u64 - var $t29: u64 - var $t30: u64 + var $t29: &mut u64 + var $t30: &mut u64 var $t31: u64 var $t32: u64 - var $t33: &mut u64 - var $t34: &mut u64 - var $t35: u64 - var $t36: u64 + var $t33: u64 + var $t34: u64 + var $t35: &mut u64 + var $t36: &mut u64 var $t37: u64 var $t38: u64 - var $t39: &mut u64 - var $t40: &mut u64 + var $t39: u64 + var $t40: u64 var $t41: u64 - var $t42: u64 - var $t43: u64 - var $t44: u64 - var $t45: u64 - 0: $t3 := 3 - 1: $t2 := infer($t3) - 2: $t8 := 4 - 3: $t7 := <($t0, $t8) - 4: if ($t7) goto 5 else goto 8 - 5: label L0 - 6: $t6 := infer($t0) - 7: goto 10 - 8: label L1 - 9: $t6 := infer($t2) - 10: label L2 - 11: $t5 := borrow_local($t6) - 12: $t4 := infer($t5) - 13: $t9 := 10 - 14: write_ref($t4, $t9) - 15: $t10 := infer($t0) - 16: $t12 := borrow_local($t10) - 17: $t11 := infer($t12) - 18: $t14 := read_ref($t11) - 19: $t15 := 1 - 20: $t13 := +($t14, $t15) - 21: write_ref($t11, $t13) - 22: $t16 := infer($t10) - 23: $t20 := 0 - 24: $t19 := +($t16, $t20) - 25: $t18 := borrow_local($t19) - 26: $t17 := infer($t18) - 27: $t22 := read_ref($t17) - 28: $t23 := 2 - 29: $t21 := +($t22, $t23) - 30: write_ref($t17, $t21) - 31: $t24 := infer($t16) - 32: $t29 := 1 - 33: $t28 := infer($t29) - 34: $t27 := infer($t24) - 35: $t26 := borrow_local($t27) - 36: $t25 := infer($t26) - 37: $t31 := read_ref($t25) - 38: $t32 := 4 - 39: $t30 := +($t31, $t32) - 40: write_ref($t25, $t30) - 41: $t35 := infer($t24) - 42: $t34 := borrow_local($t35) - 43: $t33 := infer($t34) - 44: $t37 := read_ref($t33) - 45: $t38 := 8 - 46: $t36 := +($t37, $t38) - 47: write_ref($t33, $t36) - 48: $t42 := 3 - 49: $t41 := infer($t24) - 50: $t40 := borrow_local($t41) - 51: $t39 := infer($t40) - 52: $t44 := read_ref($t39) - 53: $t45 := 16 - 54: $t43 := +($t44, $t45) - 55: write_ref($t39, $t43) - 56: $t1 := infer($t24) - 57: return $t1 + 0: $t6 := 4 + 1: $t5 := <($t0, $t6) + 2: if ($t5) goto 3 else goto 6 + 3: label L0 + 4: $t4 := infer($t0) + 5: goto 8 + 6: label L1 + 7: $t4 := 3 + 8: label L2 + 9: $t3 := borrow_local($t4) + 10: $t2 := infer($t3) + 11: $t7 := 10 + 12: write_ref($t2, $t7) + 13: $t8 := infer($t0) + 14: $t10 := borrow_local($t8) + 15: $t9 := infer($t10) + 16: $t12 := read_ref($t9) + 17: $t13 := 1 + 18: $t11 := +($t12, $t13) + 19: write_ref($t9, $t11) + 20: $t14 := infer($t8) + 21: $t18 := 0 + 22: $t17 := +($t14, $t18) + 23: $t16 := borrow_local($t17) + 24: $t15 := infer($t16) + 25: $t20 := read_ref($t15) + 26: $t21 := 2 + 27: $t19 := +($t20, $t21) + 28: write_ref($t15, $t19) + 29: $t22 := infer($t14) + 30: $t25 := infer($t22) + 31: $t24 := borrow_local($t25) + 32: $t23 := infer($t24) + 33: $t27 := read_ref($t23) + 34: $t28 := 4 + 35: $t26 := +($t27, $t28) + 36: write_ref($t23, $t26) + 37: $t31 := infer($t22) + 38: $t30 := borrow_local($t31) + 39: $t29 := infer($t30) + 40: $t33 := read_ref($t29) + 41: $t34 := 8 + 42: $t32 := +($t33, $t34) + 43: write_ref($t29, $t32) + 44: $t38 := 3 + 45: $t37 := infer($t22) + 46: $t36 := borrow_local($t37) + 47: $t35 := infer($t36) + 48: $t40 := read_ref($t35) + 49: $t41 := 16 + 50: $t39 := +($t40, $t41) + 51: write_ref($t35, $t39) + 52: $t1 := infer($t22) + 53: return $t1 } @@ -276,32 +255,30 @@ fun M::test1b($t0: M::S): u64 { var $t37: &mut u64 var $t38: &mut u64 var $t39: u64 - var $t40: u64 - var $t41: u64 - var $t42: &M::S - var $t43: &u64 + var $t40: &M::S + var $t41: &u64 + var $t42: u64 + var $t43: u64 var $t44: u64 - var $t45: u64 - var $t46: u64 - var $t47: &mut u64 - var $t48: &mut u64 - var $t49: u64 - var $t50: &M::S - var $t51: &u64 + var $t45: &mut u64 + var $t46: &mut u64 + var $t47: u64 + var $t48: &M::S + var $t49: &u64 + var $t50: u64 + var $t51: u64 var $t52: u64 - var $t53: u64 - var $t54: u64 - var $t55: &mut u64 - var $t56: &mut u64 - var $t57: u64 - var $t58: u64 - var $t59: &M::S - var $t60: &u64 + var $t53: &mut u64 + var $t54: &mut u64 + var $t55: u64 + var $t56: u64 + var $t57: &M::S + var $t58: &u64 + var $t59: u64 + var $t60: u64 var $t61: u64 - var $t62: u64 - var $t63: u64 - var $t64: &M::S - var $t65: &u64 + var $t62: &M::S + var $t63: &u64 0: $t4 := 3 1: $t3 := pack M::S($t4) 2: $t2 := infer($t3) @@ -346,40 +323,38 @@ fun M::test1b($t0: M::S): u64 { 41: $t33 := +($t34, $t35) 42: write_ref($t30, $t33) 43: $t36 := infer($t29) - 44: $t41 := 1 - 45: $t40 := infer($t41) - 46: $t42 := borrow_local($t36) - 47: $t43 := borrow_field.f($t42) - 48: $t39 := read_ref($t43) - 49: $t38 := borrow_local($t39) - 50: $t37 := infer($t38) - 51: $t45 := read_ref($t37) - 52: $t46 := 1 - 53: $t44 := +($t45, $t46) - 54: write_ref($t37, $t44) - 55: $t50 := borrow_local($t36) - 56: $t51 := borrow_field.f($t50) - 57: $t49 := read_ref($t51) - 58: $t48 := borrow_local($t49) - 59: $t47 := infer($t48) - 60: $t53 := read_ref($t47) - 61: $t54 := 8 - 62: $t52 := +($t53, $t54) - 63: write_ref($t47, $t52) - 64: $t58 := 3 - 65: $t59 := borrow_local($t36) - 66: $t60 := borrow_field.f($t59) - 67: $t57 := read_ref($t60) - 68: $t56 := borrow_local($t57) - 69: $t55 := infer($t56) - 70: $t62 := read_ref($t55) - 71: $t63 := 16 - 72: $t61 := +($t62, $t63) - 73: write_ref($t55, $t61) - 74: $t64 := borrow_local($t36) - 75: $t65 := borrow_field.f($t64) - 76: $t1 := read_ref($t65) - 77: return $t1 + 44: $t40 := borrow_local($t36) + 45: $t41 := borrow_field.f($t40) + 46: $t39 := read_ref($t41) + 47: $t38 := borrow_local($t39) + 48: $t37 := infer($t38) + 49: $t43 := read_ref($t37) + 50: $t44 := 1 + 51: $t42 := +($t43, $t44) + 52: write_ref($t37, $t42) + 53: $t48 := borrow_local($t36) + 54: $t49 := borrow_field.f($t48) + 55: $t47 := read_ref($t49) + 56: $t46 := borrow_local($t47) + 57: $t45 := infer($t46) + 58: $t51 := read_ref($t45) + 59: $t52 := 8 + 60: $t50 := +($t51, $t52) + 61: write_ref($t45, $t50) + 62: $t56 := 3 + 63: $t57 := borrow_local($t36) + 64: $t58 := borrow_field.f($t57) + 65: $t55 := read_ref($t58) + 66: $t54 := borrow_local($t55) + 67: $t53 := infer($t54) + 68: $t60 := read_ref($t53) + 69: $t61 := 16 + 70: $t59 := +($t60, $t61) + 71: write_ref($t53, $t59) + 72: $t62 := borrow_local($t36) + 73: $t63 := borrow_field.f($t62) + 74: $t1 := read_ref($t63) + 75: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp index b3304cd9f784a..1e33c882718ce 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/escape_autoref.exp @@ -21,21 +21,6 @@ module 0x42::m { private fun will_autoref(): address { select m::Object.inner(m::make()) } - spec fun $make(): m::Object { - Abort(0) - } - spec fun $owner_correct(o: m::Object): address { - { - let addr: address = select m::Object.inner(o); - select m::ObjectCore.owner(global(addr)) - } - } - spec fun $owner_read_ref_missing(o: m::Object): address { - select m::ObjectCore.owner(global(select m::Object.inner(o))) - } - spec fun $will_autoref(): address { - select m::Object.inner(m::$make()) - } } // end 0x42::m ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp index f3e92a459c93e..1a9cc9ce2d1cd 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields.exp @@ -57,23 +57,6 @@ module 0x42::fields { select fields::T.h(select fields::S.g(x)) = 42; x } - spec fun $read_generic_val(x: fields::G): u64 { - select fields::G.f(x) - } - spec fun $read_ref(x: fields::S): u64 { - select fields::T.h(select fields::S.g(x)) - } - spec fun $read_val(x: fields::S): u64 { - select fields::T.h(select fields::S.g(x)) - } - spec fun $write_generic_val(x: fields::G,v: u64) { - select fields::G.f(x) = v - } - spec fun $write_local_direct(): fields::S; - spec fun $write_local_via_ref(): fields::S; - spec fun $write_local_via_ref_2(): fields::S; - spec fun $write_param(x: &mut fields::S); - spec fun $write_val(x: fields::S): fields::S; } // end 0x42::fields ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields_invalid.exp index 467a9d11b6317..00da148628c9b 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/fields_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/fields_invalid.exp @@ -11,7 +11,6 @@ module 0x42::fields { select fields::T.h(select fields::S.g(x)) = 42; Tuple() } - spec fun $write_ref(x: &fields::S); } // end 0x42::fields diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp index 3d6bfa9c2505e..5c1901fbf896c 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/globals.exp @@ -1,96 +1,25 @@ Diagnostics: -warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` - ┌─ tests/bytecode-generator/globals.move:18:27 +error: type `R` does not have expected ability `key` + ┌─ tests/bytecode-generator/globals.move:6:20 + │ +6 │ move_to(s, R{f: 1}); + │ ^^^^^^^ + +error: type `R` does not have expected ability `key` + ┌─ tests/bytecode-generator/globals.move:10:9 │ -18 │ fun write(a: address, x: u64): u64 { - │ ^ - -// -- Model dump before bytecode pipeline -module 0x42::globals { - struct R { - f: u64, - } - private fun check(a: address): bool { - exists(a) - } - private fun publish(s: &signer) { - MoveTo(s, pack globals::R(1)); - Tuple() - } - private fun read(a: address): u64 { - { - let r: &globals::R = BorrowGlobal(Immutable)(a); - select globals::R.f(r) - } - } - private fun write(a: address,x: u64): u64 { - { - let r: &mut globals::R = BorrowGlobal(Mutable)(a); - select globals::R.f(r) = 2; - 9 - } - } - spec fun $check(a: address): bool { - exists(a) - } - spec fun $publish(s: &signer); - spec fun $read(a: address): u64 { - { - let r: globals::R = global(a); - select globals::R.f(r) - } - } - spec fun $write(a: address,x: u64): u64; -} // end 0x42::globals - -============ initial bytecode ================ - -[variant baseline] -fun globals::check($t0: address): bool { - var $t1: bool - 0: $t1 := exists($t0) - 1: return $t1 -} - - -[variant baseline] -fun globals::publish($t0: &signer) { - var $t1: globals::R - var $t2: u64 - 0: $t2 := 1 - 1: $t1 := pack globals::R($t2) - 2: move_to($t0, $t1) - 3: return () -} - - -[variant baseline] -fun globals::read($t0: address): u64 { - var $t1: u64 - var $t2: &globals::R - var $t3: &globals::R - var $t4: &u64 - 0: $t3 := borrow_global($t0) - 1: $t2 := infer($t3) - 2: $t4 := borrow_field.f($t2) - 3: $t1 := read_ref($t4) - 4: return $t1 -} +10 │ exists(a) + │ ^^^^^^^^^^^^ +error: type `R` does not have expected ability `key` + ┌─ tests/bytecode-generator/globals.move:14:17 + │ +14 │ let r = borrow_global(a); + │ ^^^^^^^^^^^^^^^^^^^ -[variant baseline] -fun globals::write($t0: address, $t1: u64): u64 { - var $t2: u64 - var $t3: &mut globals::R - var $t4: &mut globals::R - var $t5: u64 - var $t6: &mut u64 - 0: $t4 := borrow_global($t0) - 1: $t3 := infer($t4) - 2: $t5 := 2 - 3: $t6 := borrow_field.f($t3) - 4: write_ref($t6, $t5) - 5: $t2 := 9 - 6: return $t2 -} +error: type `R` does not have expected ability `key` + ┌─ tests/bytecode-generator/globals.move:19:17 + │ +19 │ let r = borrow_global_mut(a); + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp index afaa77aa8ac71..fa374099954fa 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/if_else.exp @@ -18,24 +18,6 @@ module 0x42::if_else { Div(x, 2) } } - spec fun $if_else(cond: bool,x: u64): u64 { - if cond { - Add(x, 1) - } else { - Sub(x, 1) - } - } - spec fun $if_else_nested(cond: bool,x: u64): u64 { - if Gt(if cond { - Add(x, 1) - } else { - Sub(x, 1) - }, 10) { - Mul(x, 2) - } else { - Div(x, 2) - } - } } // end 0x42::if_else ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp index 29f12e19c5cf3..0b554e4d24adc 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/inline_specs.exp @@ -18,10 +18,6 @@ module 0x42::inline_specs { private fun succ(x: u64): u64 { Add(x, 1) } - spec fun $specs(): u64; - spec fun $succ(x: u64): u64 { - Add(x, 1) - } } // end 0x42::inline_specs ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp index f3165cfe03561..4882e1dea81a7 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop.exp @@ -53,9 +53,6 @@ module 0x42::loops { }; x } - spec fun $nested_loop(x: u64): u64; - spec fun $while_loop(x: u64): u64; - spec fun $while_loop_with_break_and_continue(x: u64): u64; } // end 0x42::loops ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_invalid.exp index 4d4d0a627e3f1..ba517bb313e92 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/loop_invalid.exp @@ -22,8 +22,6 @@ module 0x42::loop_invalid { }; x } - spec fun $misplaced_break(x: u64): u64; - spec fun $misplaced_continue(x: u64): u64; } // end 0x42::loop_invalid diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp index 4de7f420e77b9..92f9a57f591c0 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/operators.exp @@ -18,24 +18,6 @@ module 0x42::operators { private fun order(x: u64,y: u64): bool { And(And(And(Lt(x, y), Le(x, y)), Not(Gt(x, y))), Not(Ge(x, y))) } - spec fun $arithm(x: u64,y: u64): u64 { - Add(x, Mod(Mul(Div(y, Sub(x, y)), y), x)) - } - spec fun $bits(x: u64,y: u8): u64 { - BitAnd(Shl(x, y), x) - } - spec fun $bools(x: bool,y: bool): bool { - Or(Or(Or(And(x, y), And(x, Not(y))), And(Not(x), y)), And(Not(x), Not(y))) - } - spec fun $equality(x: #0,y: #0): bool { - Eq<#0>(x, y) - } - spec fun $inequality(x: #0,y: #0): bool { - Neq<#0>(x, y) - } - spec fun $order(x: u64,y: u64): bool { - And(And(And(Lt(x, y), Le(x, y)), Not(Gt(x, y))), Not(Ge(x, y))) - } } // end 0x42::operators ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp index d4fbf99150ce6..c47dad9d9a649 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_order.exp @@ -47,48 +47,6 @@ module 0x42::pack_unpack { } } } - spec fun $pack1(x: u8,y: u8,z: u8): pack_unpack::S { - pack pack_unpack::S(x, y, z) - } - spec fun $pack2(x: u8,y: u8,z: u8): pack_unpack::S { - { - let $f1: u8 = x; - { - let $f3: u8 = y; - pack pack_unpack::S($f1, z, $f3) - } - } - } - spec fun $pack3(x: u8,y: u8,z: u8): pack_unpack::S { - { - let $f2: u8 = x; - pack pack_unpack::S(y, $f2, z) - } - } - spec fun $pack4(x: u8,y: u8,z: u8): pack_unpack::S { - { - let $f2: u8 = x; - { - let $f3: u8 = y; - pack pack_unpack::S(z, $f2, $f3) - } - } - } - spec fun $pack5(x: u8,y: u8,z: u8): pack_unpack::S { - { - let $f3: u8 = x; - pack pack_unpack::S(y, z, $f3) - } - } - spec fun $pack6(x: u8,y: u8,z: u8): pack_unpack::S { - { - let $f3: u8 = x; - { - let $f2: u8 = y; - pack pack_unpack::S(z, $f2, $f3) - } - } - } } // end 0x42::pack_unpack ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp index 69a3c1ea2aa47..7809faaa94493 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/pack_unpack.exp @@ -16,15 +16,6 @@ module 0x42::pack_unpack { Tuple(f, h) } } - spec fun $pack(x: u64,y: u64): pack_unpack::S { - pack pack_unpack::S(x, pack pack_unpack::T(y)) - } - spec fun $unpack(s: pack_unpack::S): (u64, u64) { - { - let pack_unpack::S{ f: f: u64, g: pack_unpack::T{ h: h: u64 } }: pack_unpack::S = s; - Tuple(f, h) - } - } } // end 0x42::pack_unpack ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp index c526d5abf71d8..513c30524f499 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/reference_conversion.exp @@ -13,10 +13,6 @@ module 0x42::reference_conversion { } } } - spec fun $deref(r: u64): u64 { - r - } - spec fun $use_it(): u64; } // end 0x42::reference_conversion ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp index b614421985754..d37ff8d8d63e6 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/spec_construct.exp @@ -10,9 +10,6 @@ module 0x42::m { public fun foo(v: &m::S): u8 { select m::E.k(vector::borrow(Borrow(Immutable)(select m::S.data(v)), 0)) } - spec fun $foo(v: m::S): u8 { - select m::E.k(vector::$borrow(select m::S.data(v), 0)) - } } // end 0x42::m ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp index d92bea86ebb98..a779a467964c7 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp @@ -12,15 +12,6 @@ module 0x42::tuple { Add(x, y) } } - spec fun $tuple(x: u64): (u64, tuple::S) { - Tuple(x, pack tuple::S(Add(x, 1))) - } - spec fun $use_tuple(x: u64): u64 { - { - let (x: u64, tuple::S{ f: y: u64 }): (u64, tuple::S) = tuple::$tuple(x); - Add(x, y) - } - } } // end 0x42::tuple ============ initial bytecode ================ diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp index 2088366c95fd8..cc08d333b8e91 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp @@ -20,15 +20,6 @@ module 0x42::tuple_invalid { 1 } } - spec fun $tuple(x: u64): (u64, tuple_invalid::S) { - Tuple(x, pack tuple_invalid::S(Add(x, 1))) - } - spec fun $use_tuple1(x: u64): u64 { - { - let x: (u64, tuple_invalid::S) = tuple_invalid::$tuple(x); - 1 - } - } } // end 0x42::tuple_invalid diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop.exp index fae74eaec15d7..65d9bf167c6fb 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop.exp @@ -3,9 +3,6 @@ module _0 { private fun main() { break } - spec fun $main() { - break - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_else.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_else.exp index 4ffdc238eeec4..fd3592ca4a473 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_else.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_else.exp @@ -8,7 +8,6 @@ module _0 { }; Tuple() } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_if.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_if.exp index 8141c2a36ec4c..4ba118a1a902b 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_if.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/break_outside_loop_in_if.exp @@ -7,13 +7,6 @@ module _0 { Tuple() } } - spec fun $main() { - if true { - break - } else { - Tuple() - } - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop.exp index 9fad9550d0603..dd49daa2df427 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop.exp @@ -3,9 +3,6 @@ module _0 { private fun main() { continue } - spec fun $main() { - continue - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop_in_if.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop_in_if.exp index 58067c06a1a8f..9bca0da5da53c 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop_in_if.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-commands/continue_outside_loop_in_if.exp @@ -8,7 +8,6 @@ module _0 { }; Tuple() } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-typing/global_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-typing/global_invalid.exp index bf7318ba7503c..21c2baac2a0de 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-typing/global_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/v1-typing/global_invalid.exp @@ -12,7 +12,6 @@ module 0x42::m { Tuple() } } - spec fun $invalid(addr: address); } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp index ae7a1c95355cb..0776edc2f714c 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/vector.exp @@ -1,10 +1,7 @@ // -- Model dump before bytecode pipeline module 0x42::vector { private fun create(): vector { - Vector(1, 2, 3) - } - spec fun $create(): vector { - Vector(1, 2, 3) + [Number(1), Number(2), Number(3)] } } // end 0x42::vector @@ -13,12 +10,6 @@ module 0x42::vector { [variant baseline] fun vector::create(): vector { var $t0: vector - var $t1: u64 - var $t2: u64 - var $t3: u64 - 0: $t1 := 1 - 1: $t2 := 2 - 2: $t3 := 3 - 3: $t0 := vector($t1, $t2, $t3) - 4: return $t0 + 0: $t0 := ["1", "2", "3"] + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/checking/abilities/globals.exp b/third_party/move/move-compiler-v2/tests/checking/abilities/globals.exp new file mode 100644 index 0000000000000..e752fa131e7d9 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/abilities/globals.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: type `R` does not have expected ability `key` + ┌─ tests/checking/abilities/globals.move:6:20 + │ +6 │ move_to(s, R{f: 1}); + │ ^^^^^^^ + +error: type `R` does not have expected ability `key` + ┌─ tests/checking/abilities/globals.move:10:9 + │ +10 │ exists(a) + │ ^^^^^^^^^^^^ + +error: type `R` does not have expected ability `key` + ┌─ tests/checking/abilities/globals.move:14:17 + │ +14 │ let r = borrow_global(a); + │ ^^^^^^^^^^^^^^^^^^^ + +error: type `R` does not have expected ability `key` + ┌─ tests/checking/abilities/globals.move:19:17 + │ +19 │ let r = borrow_global_mut(a); + │ ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/ability-check/globals.move b/third_party/move/move-compiler-v2/tests/checking/abilities/globals.move similarity index 100% rename from third_party/move/move-compiler-v2/tests/ability-check/globals.move rename to third_party/move/move-compiler-v2/tests/checking/abilities/globals.move diff --git a/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.exp b/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.exp new file mode 100644 index 0000000000000..9d1164bbc4ad6 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.exp @@ -0,0 +1,25 @@ + +Diagnostics: +error: type `Impotent` does not have expected ability `key` + ┌─ tests/checking/abilities/missing_key.move:16:9 + │ +16 │ borrow_global_mut(addr); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `Impotent` does not have expected ability `key` + ┌─ tests/checking/abilities/missing_key.move:17:9 + │ +17 │ borrow_global(addr); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `Impotent` does not have expected ability `key` + ┌─ tests/checking/abilities/missing_key.move:18:9 + │ +18 │ exists(addr); + │ ^^^^^^^^^^^^^^^^^^^^^^ + +error: type `Impotent` does not have expected ability `key` + ┌─ tests/checking/abilities/missing_key.move:22:25 + │ +22 │ move_to(signer, Impotent {}) + │ ^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.move b/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.move new file mode 100644 index 0000000000000..b66a2573dad00 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/abilities/missing_key.move @@ -0,0 +1,24 @@ +module 0x42::ability { + + inline fun move_from_no_key(addr: address) { + move_from(addr); + } + + struct Impotent {} + + struct S has key { + x: T + } + + fun no_key(addr: address) { + move_from_no_key(addr); + move_from>(addr); + borrow_global_mut(addr); + borrow_global(addr); + exists(addr); + } + + fun invalid_move_to(signer: &signer) { + move_to(signer, Impotent {}) + } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/access_specifiers/access_ok.exp b/third_party/move/move-compiler-v2/tests/checking/access_specifiers/access_ok.exp index 4c34be22ac2d6..b2e3bc2231280 100644 --- a/third_party/move/move-compiler-v2/tests/checking/access_specifiers/access_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/access_specifiers/access_ok.exp @@ -104,46 +104,4 @@ module 0x42::m { private fun make_up_address(x: u64): address { 0x42 } - spec fun $f1() { - Tuple() - } - spec fun $f10(x: u64) { - Tuple() - } - spec fun $f11() { - Tuple() - } - spec fun $f12() { - Tuple() - } - spec fun $f2() { - Tuple() - } - spec fun $f3() { - Tuple() - } - spec fun $f4() { - Tuple() - } - spec fun $f5() { - Tuple() - } - spec fun $f6() { - Tuple() - } - spec fun $f7() { - Tuple() - } - spec fun $f8() { - Tuple() - } - spec fun $f9(a: address) { - Tuple() - } - spec fun $f_multiple() { - Tuple() - } - spec fun $make_up_address(x: u64): address { - 0x42 - } } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/control_flow/loop_after_loop.exp b/third_party/move/move-compiler-v2/tests/checking/control_flow/loop_after_loop.exp index 93a0ac0e86069..08bf31d7ac079 100644 --- a/third_party/move/move-compiler-v2/tests/checking/control_flow/loop_after_loop.exp +++ b/third_party/move/move-compiler-v2/tests/checking/control_flow/loop_after_loop.exp @@ -8,5 +8,4 @@ module _0 { Tuple() } } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp index d7db07798777e..786d57ffbecfa 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/acquires_error_msg.exp @@ -13,6 +13,4 @@ module 0x42::test { select test::Test.value(BorrowGlobal(Mutable)(0xcafe)) = 2; Tuple() } - spec fun $call_modify_without_acquire(); - spec fun $modify(); } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp index db1a990014d9e..7fc23f62bf2bf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11112.exp @@ -33,5 +33,4 @@ module 0xcafe::vectors { } } } - spec fun $test_for_each_mut(); } // end 0xcafe::vectors diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp index d3ba0962744a2..6de110861a7f7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_11223.exp @@ -16,19 +16,4 @@ module 0xcafe::vectors { } } } - spec fun $guess_flips_break2(flips: vector): u64 { - { - let flipsref5: vector = flips; - { - let _v: vector = Copy(flips); - { - let _v2: vector = flips; - { - let x: vector = flipsref5; - vector::$length(x) - } - } - } - } - } } // end 0xcafe::vectors diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp index c3c1d0fe1e7c8..09a4d87b6d39c 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717.exp @@ -129,15 +129,4 @@ module 0xcafe::vectors { vectors::guess_without_break_with_inline([Number(0), Number(0), Number(0), Number(0)]); Tuple() } - spec fun $guess_flips(flips: vector); - spec fun $guess_flips_directly(flips: vector); - spec fun $guess_with_break_without_inline(flips: vector); - spec fun $guess_without_break_with_inline(flips: vector); - spec fun $loops_with_break(flips: &vector); - spec fun $loops_with_break_no_inline(flips: &vector); - spec fun $loops_without_break(flips: &vector); - spec fun $test_guess_directly(); - spec fun $test_guess_with_break_no_inline(); - spec fun $test_guess_with_inline_break(); - spec fun $test_guess_without_break(); } // end 0xcafe::vectors diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp index 0c51b05556d8c..a1bab5aa98412 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/bug_9717_looponly.exp @@ -37,5 +37,4 @@ module 0xcafe::vectors { } } } - spec fun $guess_flips_break2(flips: vector): u64; } // end 0xcafe::vectors diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp index 49ef45553fe64..103457c42d5f2 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/deep_exp.exp @@ -3,22 +3,4 @@ module 0x42::Test { public fun test(): u64 { 625 } - spec fun $f1(x: u64): u64 { - Test::$f2(Test::$f2(Test::$f2(Test::$f2(Test::$f2(x))))) - } - spec fun $f2(x: u64): u64 { - Test::$f3(Test::$f3(Test::$f3(Test::$f3(Test::$f3(x))))) - } - spec fun $f3(x: u64): u64 { - Test::$f4(Test::$f4(Test::$f4(Test::$f4(Test::$f4(x))))) - } - spec fun $f4(x: u64): u64 { - Test::$f5(Test::$f5(Test::$f5(Test::$f5(Test::$f5(x))))) - } - spec fun $f5(x: u64): u64 { - Add(x, 1) - } - spec fun $test(): u64 { - Test::$f1(0) - } } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp index 7264326e6c4ab..e5132322bc003 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/double_nesting.exp @@ -1,13 +1,7 @@ // -- Model dump before bytecode pipeline module 0x42::mathtest2 { - spec fun $fun2(a: u64,b: u64,c: u64): u64 { - Cast(Add(Add(Mul(7, Cast(a)), Mul(11, Cast(b))), Mul(13, Cast(c)))) - } } // end 0x42::mathtest2 module 0x42::mathtest { - spec fun $fun1(a: u64,b: u64,c: u64): u64 { - Cast(Add(Add(Mul(2, Cast(a)), Mul(3, Cast(b))), Mul(5, Cast(c)))) - } } // end 0x42::mathtest module 0x42::test { use 0x42::mathtest; // resolved as: 0x42::mathtest @@ -20,10 +14,4 @@ module 0x42::test { }; Tuple() } - spec fun $test_nested_fun1() { - { - let a: u64 = mathtest::$fun1(2, mathtest::$fun1(3, mathtest2::$fun2(4, 5, 6), 7), mathtest2::$fun2(8, 9, mathtest::$fun1(10, mathtest2::$fun2(11, 12, 13), 14))); - Tuple() - } - } } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp index 62a451d9bdd61..41b76a2b90b91 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/inline_accessing_constant.exp @@ -1,14 +1,8 @@ // -- Model dump before bytecode pipeline module 0xc0ffee::dummy1 { - spec fun $expose(): u64 { - 1 - } } // end 0xc0ffee::dummy1 module 0xc0ffee::dummy2 { public fun main(): u64 { 1 } - spec fun $main(): u64 { - dummy1::$expose() - } } // end 0xc0ffee::dummy2 diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp index 85e0063a9442f..82f2a6ecb8041 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda.exp @@ -1,14 +1,5 @@ // -- Model dump before bytecode pipeline module 0x42::LambdaTest1 { - spec fun $inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - spec fun $inline_apply1(f: |u64|u64,b: u64): u64 { - LambdaTest1::$inline_mul(Add((f)(b), 1), LambdaTest1::$inline_mul(3, 4)) - } - spec fun $inline_mul(a: u64,b: u64): u64 { - Mul(a, b) - } } // end 0x42::LambdaTest1 module 0x42::LambdaTest2 { use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1 @@ -40,14 +31,6 @@ module 0x42::LambdaTest2 { Tuple() } } - spec fun $foreach(v: &vector<#0>,action: |�|); - spec fun $inline_apply2(g: |u64|u64,c: u64): u64 { - Add(LambdaTest1::$inline_apply1(|z: u64| z, (g)(LambdaTest1::$inline_mul(c, LambdaTest1::$inline_apply(|x: u64| x, 3)))), 2) - } - spec fun $inline_apply3(g: |u64|u64,c: u64): u64 { - Add(LambdaTest1::$inline_apply1(g, LambdaTest1::$inline_mul(c, LambdaTest1::$inline_apply(|x: u64| LambdaTest1::$inline_apply(|y: u64| y, x), 3))), 4) - } - spec fun $test_inline_lambda(); } // end 0x42::LambdaTest2 module 0x42::LambdaTest { use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2 @@ -59,16 +42,4 @@ module 0x42::LambdaTest { }; Tuple() } - spec fun $inline_apply(f: |u64|u64,b: u64): u64 { - (f)(b) - } - spec fun $inline_apply_test(): u64 { - Add(LambdaTest2::$inline_apply2(|x: num| Add(x, 1), 3), LambdaTest2::$inline_apply2(|x: num| Mul(x, x), LambdaTest::$inline_apply(|y: u64| y, 3))) - } - spec fun $test_lambda() { - { - let a: u64 = LambdaTest::$inline_apply_test(); - Tuple() - } - } } // end 0x42::LambdaTest diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp index ec0ddd3501080..a67ca1e188d4e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/lambda_cast.exp @@ -57,6 +57,4 @@ module 0x12391283::M { accu } } - spec fun $test_1(): u64; - spec fun $test_2(): u64; } // end 0x12391283::M diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp index 5b05faf4d8e2c..7f6dd9c649389 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/nested_mul.exp @@ -1,8 +1,5 @@ // -- Model dump before bytecode pipeline module 0x42::mathtest { - spec fun $mul_div(a: u64,b: u64,c: u64): u64 { - Cast(Div(Mul(Cast(a), Cast(b)), Cast(c))) - } } // end 0x42::mathtest module 0x42::test { use 0x42::mathtest; // resolved as: 0x42::mathtest @@ -14,10 +11,4 @@ module 0x42::test { }; Tuple() } - spec fun $test_nested_mul_div() { - { - let a: u64 = mathtest::$mul_div(1, mathtest::$mul_div(1, 1, 1), 1); - Tuple() - } - } } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp index 50fb0dcf14869..16f2b89c1f834 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/order_sensitive.exp @@ -1,26 +1,8 @@ // -- Model dump before bytecode pipeline module 0x42::OrderSensitiveTest1 { - spec fun $inline_fun1(a: u64,b: u64): u64 { - Mul(a, b) - } - spec fun $inline_fun2(a: u64,b: u64): u64 { - Add(OrderSensitiveTest1::$inline_fun1(a, b), Mul(2, OrderSensitiveTest1::$inline_fun3(a, b))) - } - spec fun $inline_fun3(a: u64,b: u64): u64 { - Add(Mul(a, b), 2) - } } // end 0x42::OrderSensitiveTest1 module 0x42::OrderSensitiveTest2 { use 0x42::OrderSensitiveTest1; // resolved as: 0x42::OrderSensitiveTest1 - spec fun $inline_fun1(a: u64,b: u64): u64 { - Add(Mul(a, b), 3) - } - spec fun $inline_fun2(a: u64,b: u64): u64 { - Add(Add(OrderSensitiveTest1::$inline_fun2(OrderSensitiveTest2::$inline_fun1(a, b), OrderSensitiveTest2::$inline_fun3(a, b)), Mul(3, OrderSensitiveTest2::$inline_fun1(a, b))), Mul(5, OrderSensitiveTest2::$inline_fun3(a, b))) - } - spec fun $inline_fun3(a: u64,b: u64): u64 { - Add(Mul(a, b), 4) - } } // end 0x42::OrderSensitiveTest2 module 0x42::OrderSensitiveTest3 { use 0x42::OrderSensitiveTest2; // resolved as: 0x42::OrderSensitiveTest2 @@ -57,13 +39,4 @@ module 0x42::OrderSensitiveTest3 { Add(Mul(a, b), 6) })) } - spec fun $fun1(a: u64,b: u64): u64 { - Add(Mul(a, b), 5) - } - spec fun $fun2(a: u64,b: u64): u64 { - Add(OrderSensitiveTest2::$inline_fun2(Mul(7, OrderSensitiveTest3::$fun1(a, b)), b), Mul(9, OrderSensitiveTest3::$fun3(a, b))) - } - spec fun $fun3(a: u64,b: u64): u64 { - Add(Mul(a, b), 6) - } } // end 0x42::OrderSensitiveTest3 diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp index 35b5cb830c1f3..ba0a03aa56369 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/recursive_nesting.exp @@ -1,20 +1,11 @@ // -- Model dump before bytecode pipeline module 0x42::mathtest { - spec fun $mul_div(a: u64,b: u64,c: u64): u64 { - Cast(Div(Mul(Cast(a), Cast(b)), Cast(c))) - } } // end 0x42::mathtest module 0x42::mathtest2 { use 0x42::mathtest; // resolved as: 0x42::mathtest - spec fun $mul_div2(a: u64,b: u64,c: u64): u64 { - mathtest::$mul_div(b, a, c) - } } // end 0x42::mathtest2 module 0x42::mathtest3 { use 0x42::mathtest2; // resolved as: 0x42::mathtest2 - spec fun $mul_div3(a: u64,b: u64,c: u64): u64 { - mathtest2::$mul_div2(b, a, c) - } } // end 0x42::mathtest3 module 0x42::test { use 0x42::mathtest; // resolved as: 0x42::mathtest @@ -28,10 +19,4 @@ module 0x42::test { }; Tuple() } - spec fun $test_nested_mul_div() { - { - let a: u64 = mathtest::$mul_div(mathtest3::$mul_div3(1, 1, 1), mathtest::$mul_div(1, 1, 1), mathtest2::$mul_div2(1, 1, 1)); - Tuple() - } - } } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp index 4834ac3c66390..04f56c7eafca5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/resources_invalid.exp @@ -3,9 +3,6 @@ module 0x42::objects { struct ReaderRef { addr: address, } - spec fun $reader(ref: objects::ReaderRef<#0>): #0 { - global<#0>(select objects::ReaderRef.addr(ref)) - } } // end 0x42::objects module 0x42::token { use 0x42::objects as obj; // resolved as: 0x42::objects @@ -18,7 +15,4 @@ module 0x42::token { BorrowGlobal(Immutable)(select objects::ReaderRef.addr(ref)) }) } - spec fun $get_value(ref: objects::ReaderRef): u64 { - select token::Token.val(objects::$reader(ref)) - } } // end 0x42::token diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp index 5473a9c048671..23ed46173ec3d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused.exp @@ -25,8 +25,4 @@ module 0x42::Test { } } } - spec fun $foo(f: |(u64, u64)|,z: u64); - spec fun $quux(f: |(u64, u64)|,_z: u64); - spec fun $test_shadowing(); - spec fun $test_shadowing2(); } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp index 8012e0f593822..dd4450373fc1a 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/shadowing_unused_nodecl.exp @@ -33,8 +33,4 @@ module 0x42::Test { } } } - spec fun $foo(f: |(u64, u64)|,z: u64); - spec fun $quux(f: |(u64, u64)|,z: u64); - spec fun $test_shadowing(); - spec fun $test_shadowing2(); } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp index a83703bcbefc6..e80c54961868f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.exp @@ -1,12 +1,18 @@ // -- Model dump before bytecode pipeline module 0x42::Test { - public fun test_apply() { + public fun test_apply(x: u64) { { - let r1: bool = spec { - assert true; - } - ; - true; + let r1: bool = { + let (v: u64): (u64) = Tuple(x); + spec { + assert Ge(v, 0); + } + ; + { + let (v: u64): (u64) = Tuple(v); + Ge(v, 0) + } + }; spec { assert r1; } @@ -17,11 +23,17 @@ module 0x42::Test { Abort(1) }; { - let r2: bool = spec { - assert true; - } - ; - false; + let r2: bool = { + let (v: u64): (u64) = Tuple(x); + spec { + assert Ge(v, 0); + } + ; + { + let (v: u64): (u64) = Tuple(v); + Neq(v, 0) + } + }; spec { assert r2; } @@ -35,16 +47,4 @@ module 0x42::Test { } } } - spec fun $apply(v: u64,predicate: |u64|bool): bool { - (predicate)(v) - } - spec fun $test_apply() { - { - let r1: bool = Test::$apply(0, |v: num| Ge(v, 0)); - { - let r2: bool = Test::$apply(0, |v: u256| Neq(v, 0)); - Tuple() - } - } - } } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.move b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.move index 2b66d0358c654..ad38360e44352 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.move +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/spec_inlining.move @@ -6,14 +6,14 @@ module 0x42::Test { predicate(v) } - public fun test_apply() { - let r1 = apply(0, |v| v >= 0); + public fun test_apply(x: u64) { + let r1 = apply(x, |v| v >= 0); spec { assert r1; }; assert!(r1, 1); - let r2 = apply(0, |v| v != 0); + let r2 = apply(x, |v| v != 0); spec { assert r2; }; diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp index 982e0bc2ac4a4..aa06a27a64542 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/temp_shadowing.exp @@ -40,7 +40,4 @@ module 0x42::Test { } } } - spec fun $nested(a: u64,b: u64): u64; - spec fun $other(a: u64,b: u64): u64; - spec fun $test_shadowing(); } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp b/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp index 1a61202256188..1e9d0bda4be17 100644 --- a/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp +++ b/third_party/move/move-compiler-v2/tests/checking/inlining/unused_inline.exp @@ -27,6 +27,4 @@ module 0xc0ffee::m { i } } - spec fun $bar(): u64; - spec fun $foo(): u64; } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/checking/naming/duplicate_acquires_list_item.exp b/third_party/move/move-compiler-v2/tests/checking/naming/duplicate_acquires_list_item.exp index e30e0d127bb96..c1969b53e490a 100644 --- a/third_party/move/move-compiler-v2/tests/checking/naming/duplicate_acquires_list_item.exp +++ b/third_party/move/move-compiler-v2/tests/checking/naming/duplicate_acquires_list_item.exp @@ -26,6 +26,4 @@ module 0x8675309::M { BorrowGlobal(Mutable)(0x1); Tuple() } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp index e665846217343..7d025d34595a6 100644 --- a/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp +++ b/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp @@ -12,13 +12,4 @@ module 0x2::M { } } } - spec fun $foo(s: #0): #0 { - { - let s: #0 = s; - { - let s: #0 = s; - s - } - } - } } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/naming/global_builtin_one_type_argument.exp b/third_party/move/move-compiler-v2/tests/checking/naming/global_builtin_one_type_argument.exp index a1b00532be929..126eb1e9aaa6b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/naming/global_builtin_one_type_argument.exp +++ b/third_party/move/move-compiler-v2/tests/checking/naming/global_builtin_one_type_argument.exp @@ -23,5 +23,4 @@ module 0x8675309::M { } } } - spec fun $t(account: &signer); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/naming/struct_in_current_module.exp b/third_party/move/move-compiler-v2/tests/checking/naming/struct_in_current_module.exp index c25bf0e391ea3..93ba4b71e23df 100644 --- a/third_party/move/move-compiler-v2/tests/checking/naming/struct_in_current_module.exp +++ b/third_party/move/move-compiler-v2/tests/checking/naming/struct_in_current_module.exp @@ -15,13 +15,4 @@ module 0x8675309::M { } } } - spec fun $foo() { - { - let _: M::S = pack M::S(0); - { - let M::R{ f: _ }: M::R = pack M::R(0); - Tuple() - } - } - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/assert_skipped_for_spec.exp b/third_party/move/move-compiler-v2/tests/checking/specs/assert_skipped_for_spec.exp index 471517d9a3019..35729286d8c52 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/assert_skipped_for_spec.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/assert_skipped_for_spec.exp @@ -8,10 +8,10 @@ module 0x42::M { }; Sub(x, 1) } - spec fun $bar(x: u64): u64 { - Sub(x, 1) - } spec fun foo(): u64 { M::$bar(2) } + spec fun $bar(x: u64): u64 { + Sub(x, 1) + } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.exp b/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.exp new file mode 100644 index 0000000000000..8201177f83e6e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.exp @@ -0,0 +1,10 @@ + +Diagnostics: +error: duplicate declaration, item, or annotation + ┌─ tests/checking/specs/clash_move_spec_function.move:5:14 + │ +3 │ fun f(): u64 { 1 } + │ - Alias previously defined here +4 │ +5 │ spec fun f(): u64 { 1 } + │ ^ Duplicate module member or alias 'f'. Top level names in a namespace must be unique diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.move b/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.move new file mode 100644 index 0000000000000..2a9d47fcc599f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/clash_move_spec_function.move @@ -0,0 +1,10 @@ +module 0x42::m { + + fun f(): u64 { 1 } + + spec fun f(): u64 { 1 } + + spec module { + invariant f() > 0; + } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/conditions_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/conditions_ok.exp index 9bf052073c277..ceba201d6cbba 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/conditions_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/conditions_ok.exp @@ -29,11 +29,4 @@ module 0x42::M { emit $t1 to $t0 if Gt($t2, 7); } - spec fun $add_some(x: &mut u64): u64; - spec fun $multiple_results(x: u64): (u64, bool) { - Tuple(x, true) - } - spec fun $with_emits(_guid: vector,_msg: #0,x: u64): u64 { - x - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.exp new file mode 100644 index 0000000000000..98da5547cd5b5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.exp @@ -0,0 +1,67 @@ +// -- Model dump before bytecode pipeline +module 0x42::m { + spec { + invariant forall a: address: TypeDomain
(): Implies(exists(a), { + let (x: address): (address) = Tuple(a); + { + let r: bool = { + let (a: address): (address) = Tuple(x); + Lt(select m::S.f({ + let (a: address): (address) = Tuple(a); + global(a) + }), 10) + }; + r + } + }); + } + + struct S { + f: u64, + } + spec { + invariant { + let (x: num): (num) = Tuple(select m::S.f()); + { + let r: bool = { + let (x: num): (num) = Tuple(x); + Gt(x, 0) + }; + r + } + }; + } + + private fun function_code_spec_block(x: u64): u64 { + spec { + assert { + let (x: num): (num) = Tuple($t0); + { + let r: bool = { + let (y: num): (num) = Tuple(x); + Gt(y, 0) + }; + r + } + }; + } + ; + Add(x, 1) + } + private fun function_spec_block(x: u64): u64 { + Add(x, 1) + } + spec { + ensures Eq(result0(), { + let (x: num): (num) = Tuple($t0); + { + let r: num = { + let (x: num): (num) = Tuple(x); + Add(x, 1) + }; + r + } + }); + } + +} // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.move b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.move new file mode 100644 index 0000000000000..4b41738d621e5 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_in_spec.move @@ -0,0 +1,33 @@ +module 0x42::m { + + inline fun exec(f: |T|R, x: T): R { + let r = f(x); + spec { assert r == f(x); }; + r + } + + // Function spec block + fun function_spec_block(x: u64): u64 { + x + 1 + } + spec function_spec_block { + ensures result == exec(|x| x + 1, x); + } + + // Function code spec block + fun function_code_spec_block(x: u64): u64 { + spec { assert exec(|y| y > 0, x); }; + x + 1 + } + + // Struct spec block + struct S has key { f: u64 } + spec S { invariant exec(|x| x > 0, f); } + + // Global invariant + spec module { + invariant forall a: address: + exists(a) ==> exec(|a| get(a).f < 10, a); + } + inline fun get(a: address): &R { borrow_global(a) } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_spec_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_spec_ok.exp index 6b302e91d9e78..c5c471f77575f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_spec_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_fun_spec_ok.exp @@ -1,6 +1,3 @@ // -- Model dump before bytecode pipeline module 0x42::M { - spec fun $f(): u64 { - 42 - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference.exp index 0bc70a721e0f3..6073b62bbaa43 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference.exp @@ -10,5 +10,4 @@ module 0x42::m { i: u64 = Add(i, 1) } } - spec fun $foo(); } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.exp index 085e36ded8894..f60c5fa68e8f8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.exp @@ -1,15 +1,7 @@ - -Diagnostics: -warning: Unused parameter `length`. Consider removing or prefixing with an underscore: `_length` - ┌─ tests/checking/specs/inline_spec_inference_bitvector.move:3:18 - │ -3 │ public fun new(length: u64) { - │ ^^^^^^ - // -- Model dump before bytecode pipeline module 0x42::bit_vector_infer { use std::vector; - public fun new(length: u64) { + public fun new(_length: u64) { { let counter: u64 = 1; if Gt(counter, 0) { @@ -29,5 +21,4 @@ module 0x42::bit_vector_infer { } } } - spec fun $new(length: u64); } // end 0x42::bit_vector_infer diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.move b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.move index 9ba7c517d8625..68fb7b0e27889 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.move +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_bitvector.move @@ -1,14 +1,15 @@ module 0x42::bit_vector_infer { - use std::vector; - public fun new(length: u64) { - let counter = 1; - if (counter > 0) { - counter = counter - 1; - }; - let bit_field = vector::empty(); - vector::push_back(&mut bit_field, false); - spec { - assert len(bit_field) == 0; - }; - } + use std::vector; + + public fun new(_length: u64) { + let counter = 1; + if (counter > 0) { + counter = counter - 1; + }; + let bit_field = vector::empty(); + vector::push_back(&mut bit_field, false); + spec { + assert len(bit_field) == 0; + }; + } } diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.exp index ba2b61989a9db..d0b499f33c6f9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.exp @@ -1,15 +1,7 @@ - -Diagnostics: -warning: Unused parameter `length`. Consider removing or prefixing with an underscore: `_length` - ┌─ tests/checking/specs/inline_spec_inference_vector.move:3:18 - │ -3 │ public fun new(length: u64) { - │ ^^^^^^ - // -- Model dump before bytecode pipeline module 0x42::bit_vector { use std::vector; - public fun new(length: u64) { + public fun new(_length: u64) { { let bit_field: vector = vector::empty(); spec { @@ -20,5 +12,4 @@ module 0x42::bit_vector { Tuple() } } - spec fun $new(length: u64); } // end 0x42::bit_vector diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.move b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.move index b3553f91088c7..0cdff718ffa7e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.move +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_inference_vector.move @@ -1,10 +1,11 @@ module 0x42::bit_vector { - use std::vector; - public fun new(length: u64) { - let bit_field = vector::empty(); - spec { - assert len(bit_field) == 0; - }; - vector::push_back(&mut bit_field, false); - } + use std::vector; + + public fun new(_length: u64) { + let bit_field = vector::empty(); + spec { + assert len(bit_field) == 0; + }; + vector::push_back(&mut bit_field, false); + } } diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_old.exp b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_old.exp index c5b510eea37df..f0d2ba60255f7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_old.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/inline_spec_old.exp @@ -7,7 +7,4 @@ module 0x42::m { ; Tuple() } - spec fun $foo(vec: vector) { - Tuple() - } } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/intrinsic_decl_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/intrinsic_decl_ok.exp index 2353e842beb44..afb27295027cf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/intrinsic_decl_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/intrinsic_decl_ok.exp @@ -3,9 +3,15 @@ module 0x42::M { struct MyTable1 { dummy_field: bool, } + spec { + } + struct MyTable2 { dummy_field: bool, } + spec { + } + private native fun contains(t: &M::MyTable2<#0, #1>,k: #0): bool; private native fun borrow(t: &M::MyTable2<#0, #1>,k: #0):  private native fun borrow_mut(t: &mut M::MyTable1<#0, #1>,k: #0): &mut #1; @@ -14,14 +20,6 @@ module 0x42::M { private native fun new(): M::MyTable1<#0, #1>; private native fun new2(): M::MyTable2<#0, #1>; private native fun remove(t: &mut M::MyTable2<#0, #1>,k: #0): #1; - spec fun $borrow(t: M::MyTable2<#0, #1>,k: #0): #1; - spec fun $borrow_mut(t: &mut M::MyTable1<#0, #1>,k: #0): &mut #1; - spec fun $contains(t: M::MyTable2<#0, #1>,k: #0): bool; - spec fun $destroy_empty(t: M::MyTable1<#0, #1>); - spec fun $length(t: M::MyTable1<#0, #1>): u64; - spec fun $new(): M::MyTable1<#0, #1>; - spec fun $new2(): M::MyTable2<#0, #1>; - spec fun $remove(t: &mut M::MyTable2<#0, #1>,k: #0): #1; spec fun spec_len(t: M::MyTable1<#0, #1>): num; spec fun spec_set(t: M::MyTable1<#0, #1>,k: #0,v: #1): M::MyTable1<#0, #1>; spec fun spec_get(t: M::MyTable1<#0, #1>,k: #0): #1; diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.exp b/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.exp index 882bb5275426b..e2e58234c2fdf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.exp @@ -1,40 +1,25 @@ Diagnostics: -error: expected `bool` but found a value of type `num` - ┌─ tests/checking/specs/invariants_err.move:9:15 +error: data invariants cannot depend on global state but found dependency to `M::S` + ┌─ tests/checking/specs/invariants_err.move:9:9 │ -9 │ invariant x + 1; - │ ^^^^^ +9 │ invariant exists(@0x0); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `old(..)` expression not allowed in this context - ┌─ tests/checking/specs/invariants_err.move:11:15 +error: data invariants cannot depend on global state but found dependency to `M::S` + ┌─ tests/checking/specs/invariants_err.move:10:9 │ -11 │ invariant old(x) > 0; - │ ^^^^^^ +10 │ invariant global(@0x0).x == x; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: invalid reference to post state - ┌─ tests/checking/specs/invariants_err.move:11:5 +error: data invariants cannot depend on global state but found dependency to `M::spec_var` + ┌─ tests/checking/specs/invariants_err.move:11:9 │ -11 │ invariant old(x) > 0; - │ ^^^^^^^^^^^^^^^^^^^^^ - │ │ │ - │ │ expression referring to post state - │ not allowed to refer to post state +11 │ invariant spec_var > 0; + │ ^^^^^^^^^^^^^^^^^^^^^^^ -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/checking/specs/invariants_err.move:13:5 +error: data invariants cannot depend on global state but found dependency to `M::spec_var` + ┌─ tests/checking/specs/invariants_err.move:13:9 │ -13 │ invariant exists(@0x0); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/checking/specs/invariants_err.move:14:5 - │ -14 │ invariant global(@0x0).x == x; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/checking/specs/invariants_err.move:15:5 - │ -15 │ invariant spec_var > 0; - │ ^^^^^^^^^^^^^^^^^^^^^^^ +13 │ invariant rec_fun(true); + │ ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.move b/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.move index 9c37c34404fd6..a89207c1ac304 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.move +++ b/third_party/move/move-compiler-v2/tests/checking/specs/invariants_err.move @@ -1,38 +1,30 @@ module 0x42::M { - struct S has key { - x: u64, - } + struct S has key { + x: u64, + } - spec S { - // Expression not a bool - invariant x + 1; - // Old expression in data invariant - invariant old(x) > 0; - // Direct dependency from global state - invariant exists(@0x0); - invariant global(@0x0).x == x; - invariant spec_var > 0; - // Indirect dependency from global state via function call. - invariant rec_fun(true); - } + spec S { + // Direct dependency from global state + invariant exists(@0x0); + invariant global(@0x0).x == x; + invariant spec_var > 0; + // Indirect dependency from global state via function call. + invariant rec_fun(true); + } - spec module { - global spec_var: num; + spec module { + global spec_var: num; - fun rec_fun(c: bool): bool { - if (c) { - rec_fun2(c) - } else { - spec_var > 0 + fun rec_fun(c: bool): bool { + if (c) { + rec_fun2(c) + } else { + spec_var > 0 + } + } + fun rec_fun2(c: bool): bool { + rec_fun(!c) } - } - fun rec_fun2(c: bool): bool { - rec_fun(!c) - } } - - // Type instantiation for global memory operations is not a struct type - invariant exists(@0x0); - invariant global(@0x1) == global(@0x2); } diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/lets_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/lets_ok.exp index 24a4ed6fe14c8..4cba29d734223 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/lets_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/lets_ok.exp @@ -10,5 +10,4 @@ module 0x42::M { ensures Eq(result0(), Add(Old($t0), one)); } - spec fun $foo(x: &mut u64): u64; } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.exp b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.exp deleted file mode 100644 index 80bc624459dce..0000000000000 --- a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.exp +++ /dev/null @@ -1,9 +0,0 @@ - -Diagnostics: -error: calling impure function `move_function_in_spec::change` is not allowed - ┌─ tests/checking/specs/move_function_in_spec.move:20:20 - │ -20 │ assert change(account_address, account_address); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - │ - = impure function `move_function_in_spec::change(address, address): bool` diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.exp b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.exp new file mode 100644 index 0000000000000..503c51878f53d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.exp @@ -0,0 +1,10 @@ + +Diagnostics: +error: specification expression cannot call impure Move function `change` + ┌─ tests/checking/specs/move_function_in_spec_err.move:25:20 + │ +11 │ let ty = borrow_global_mut(target); + │ ----------------------------------- in `change`: mutably borrows from global storage + · +25 │ assert change(account_address, account_address); + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ called here diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.move b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.move similarity index 88% rename from third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.move rename to third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.move index 211b6ecf0f147..88a93b9d31d34 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec.move +++ b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_err.move @@ -1,13 +1,18 @@ -module 0x42::move_function_in_spec { +module 0x42::move_function_in_spec_err { struct TypeInfo has key, copy, drop, store { account_address: address, } - public native fun type_of(): TypeInfo; + + public fun type_of(): TypeInfo { + abort 1 + } + public fun change(target: address, new_addr: address): bool acquires TypeInfo { let ty = borrow_global_mut(target); ty.account_address = new_addr; true } + public fun no_change(target: address, new_addr: address): bool acquires TypeInfo { let ty = borrow_global(target); ty.account_address == new_addr diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.exp new file mode 100644 index 0000000000000..dd83317856e3d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.exp @@ -0,0 +1,40 @@ +// -- Model dump before bytecode pipeline +module 0x42::move_function_in_spec { + struct TypeInfo { + account_address: address, + } + private fun foo() { + { + let type_info: move_function_in_spec::TypeInfo = move_function_in_spec::type_of(); + { + let account_address: address = select move_function_in_spec::TypeInfo.account_address(type_info); + spec { + assert move_function_in_spec::$no_change(account_address, account_address); + assert Eq
(account_address, select move_function_in_spec::TypeInfo.account_address(move_function_in_spec::$type_of<#0>())); + } + ; + Tuple() + } + } + } + public fun no_change(target: address,new_addr: address): bool + acquires move_function_in_spec::TypeInfo(*) + { + { + let ty: &move_function_in_spec::TypeInfo = BorrowGlobal(Immutable)(target); + Eq
(select move_function_in_spec::TypeInfo.account_address(ty), new_addr) + } + } + public fun type_of(): move_function_in_spec::TypeInfo { + Abort(1) + } + spec fun $no_change(target: address,new_addr: address): bool { + { + let ty: &move_function_in_spec::TypeInfo = global(target); + Eq
(select move_function_in_spec::TypeInfo.account_address(ty), new_addr) + } + } + spec fun $type_of(): move_function_in_spec::TypeInfo { + Tuple() + } +} // end 0x42::move_function_in_spec diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.move b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.move new file mode 100644 index 0000000000000..95461a02c1750 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/move_function_in_spec_ok.move @@ -0,0 +1,23 @@ +module 0x42::move_function_in_spec { + struct TypeInfo has key, copy, drop, store { + account_address: address, + } + + public fun type_of(): TypeInfo { + abort 1 + } + + public fun no_change(target: address, new_addr: address): bool acquires TypeInfo { + let ty = borrow_global(target); + ty.account_address == new_addr + } + + fun foo() { + let type_info = type_of(); + let account_address = type_info.account_address; + spec { + assert no_change(account_address, account_address); + assert account_address == type_of().account_address; + }; + } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/schemas_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/schemas_ok.exp index 077f2e53353c7..074391a1a469d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/schemas_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/schemas_ok.exp @@ -22,13 +22,4 @@ module 0x42::M { requires Gt($t0, $t1); } - spec fun $add(x: u64): u64 { - Add(x, 1) - } - spec fun $id(x: u64): u64 { - x - } - spec fun $multiple(_x: u64,_y: u64) { - Tuple() - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.exp b/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.exp new file mode 100644 index 0000000000000..82eeb4909b28a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.exp @@ -0,0 +1,76 @@ + +Diagnostics: +error: specification expression cannot call impure Move function `impure_borrow` + ┌─ tests/checking/specs/spec_pureness_checks.move:29:48 + │ + 8 │ let r = &mut x; + │ ------ in `impure_borrow`: mutably borrows value + · +29 │ spec fun cannot_call_impure(x: u64): u64 { impure_borrow(1) } + │ ^^^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `impure_indirect` + ┌─ tests/checking/specs/spec_pureness_checks.move:31:57 + │ + 8 │ let r = &mut x; + │ ------ in `impure_borrow`: mutably borrows value + · +19 │ impure_borrow(x) + │ ---------------- transitively calling `impure_borrow` from `impure_indirect` here + · +31 │ spec fun cannot_call_impure_indirect(x: u64): u64 { impure_indirect(1) } + │ ^^^^^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `impure_assign` + ┌─ tests/checking/specs/spec_pureness_checks.move:33:55 + │ +14 │ x = x + 1; + │ --------- in `impure_assign`: assigns variable + · +33 │ spec fun cannot_call_impure_assign(x: u64): u64 { impure_assign(x) } + │ ^^^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `uses_return` + ┌─ tests/checking/specs/spec_pureness_checks.move:35:37 + │ +23 │ if (x > 0) return x + 1; + │ ------------ in `uses_return`: return not allowed in specifications + · +35 │ spec fun cannot_return(): u64 { uses_return(2) } + │ ^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `impure_indirect` + ┌─ tests/checking/specs/spec_pureness_checks.move:41:27 + │ + 8 │ let r = &mut x; + │ ------ in `impure_borrow`: mutably borrows value + · +19 │ impure_borrow(x) + │ ---------------- transitively calling `impure_borrow` from `impure_indirect` here + · +41 │ ensures result == impure_indirect(x); + │ ^^^^^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `impure_indirect` + ┌─ tests/checking/specs/spec_pureness_checks.move:46:20 + │ + 8 │ let r = &mut x; + │ ------ in `impure_borrow`: mutably borrows value + · +19 │ impure_borrow(x) + │ ---------------- transitively calling `impure_borrow` from `impure_indirect` here + · +46 │ assert impure_indirect(x) == 2; + │ ^^^^^^^^^^^^^^^^^^ called here + +error: specification expression cannot call impure Move function `impure_indirect` + ┌─ tests/checking/specs/spec_pureness_checks.move:52:19 + │ + 8 │ let r = &mut x; + │ ------ in `impure_borrow`: mutably borrows value + · +19 │ impure_borrow(x) + │ ---------------- transitively calling `impure_borrow` from `impure_indirect` here + · +52 │ invariant impure_indirect(22) == 2; + │ ^^^^^^^^^^^^^^^^^^^ called here diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.move b/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.move new file mode 100644 index 0000000000000..5177a42ce796e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/specs/spec_pureness_checks.move @@ -0,0 +1,54 @@ +module 0x42::m { + + fun pure(x: u64): u64 { x + 1 } + + native fun impure_native(x: u64): u64; + + fun impure_borrow(x: u64): u64 { + let r = &mut x; + *r = *r + 2; + x + } + + fun impure_assign(x: u64): u64 { + x = x + 1; + x + } + + fun impure_indirect(x: u64): u64 { + impure_borrow(x) + } + + fun uses_return(x: u64): u64 { + if (x > 0) return x + 1; + x + } + + spec fun can_call_pure(): u64 { pure(1) } + + spec fun cannot_call_impure(x: u64): u64 { impure_borrow(1) } + + spec fun cannot_call_impure_indirect(x: u64): u64 { impure_indirect(1) } + + spec fun cannot_call_impure_assign(x: u64): u64 { impure_assign(x) } + + spec fun cannot_return(): u64 { uses_return(2) } + + fun impure_in_fun_spec(x: u64): u64 { + x + 1 + } + spec impure_in_fun_spec { + ensures result == impure_indirect(x); + } + + fun impure_in_inline_spec(x: u64): u64 { + spec { + assert impure_indirect(x) == 2; + }; + x + 1 + } + + spec module { + invariant impure_indirect(22) == 2; + } +} diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/structs_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/structs_ok.exp index 0507c1947e0c2..1cd90f24203b8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/structs_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/structs_ok.exp @@ -18,9 +18,6 @@ module 0x42::M { public fun f(r: M::R): M::T { pack M::T(select M::S.x(select M::R.s(r))) } - spec fun $f(r: M::R): M::T { - pack M::T(select M::S.x(select M::R.s(r))) - } spec fun struct_access(s: M::S): u64 { select M::S.x(s) } diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/type_variance_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/type_variance_ok.exp index dbc2cca54b4be..2c0d1376d130b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/type_variance_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/type_variance_ok.exp @@ -7,7 +7,4 @@ module 0x42::M { ensures Eq>(result0(), SingleVec(1)); } - spec fun $foo(v: vector): vector { - v - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/specs/update_field_ok.exp b/third_party/move/move-compiler-v2/tests/checking/specs/update_field_ok.exp index af12897d427cc..9ac5e2b67ce7d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/specs/update_field_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/specs/update_field_ok.exp @@ -13,7 +13,6 @@ module 0x42::update_field_ok { ensures Eq(Freeze($t0), update_field_ok::assign_x_1(Old($t0))); } - spec fun $f(r: &mut update_field_ok::R); spec fun assign_x_1(r: update_field_ok::R): update_field_ok::R { update update_field_ok::R.x(r, 1) } diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/annotated_types.exp b/third_party/move/move-compiler-v2/tests/checking/typing/annotated_types.exp index ba2f0120d44ba..7043502d05cac 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/annotated_types.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/annotated_types.exp @@ -14,5 +14,4 @@ module 0x8675309::M { (_, _, M::R{ dummy_field: _ }): (u64, M::S, M::R) = Tuple(0, pack M::S(false), pack M::R(false)); Tuple() } - spec fun $t(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp index 7a189e787ef63..b3c0c129ced7f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp @@ -20,13 +20,4 @@ module 0x42::tuple_invalid { 1 } } - spec fun $tuple(x: u64): (u64, tuple_invalid::S) { - Tuple(x, pack tuple_invalid::S(Add(x, 1))) - } - spec fun $use_tuple1(x: u64): u64 { - { - let x: (u64, tuple_invalid::S) = tuple_invalid::$tuple(x); - 1 - } - } } // end 0x42::tuple_invalid diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple_wg.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple_wg.exp index 912c670093189..a250c827c1d81 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple_wg.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple_wg.exp @@ -13,19 +13,6 @@ module 0xc0ffee::dummy1 { private fun baz() { Tuple() } - spec fun $bar(b: bool) { - { - let (): () = if b { - dummy1::$baz() - } else { - Tuple() - }; - Tuple() - } - } - spec fun $baz() { - Tuple() - } } // end 0xc0ffee::dummy1 module 0xc0ffee::dummy2 { struct State { @@ -37,5 +24,4 @@ module 0xc0ffee::dummy2 { Tuple() } } - spec fun $tuple_assignments(s: &signer,state: dummy2::State); } // end 0xc0ffee::dummy2 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_unpack_references.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_unpack_references.exp index 3f9273f39b802..0f18c3222f7a4 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_unpack_references.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_unpack_references.exp @@ -55,7 +55,4 @@ module 0x8675309::M { } } } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_add.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_add.exp index 38e9859936b3f..560e23ec63ac8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_add.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_add.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Add(0, 0); - Add(1, 0); - Add(0, 1); - Add(0, 1); - Add(0, 1); - Add(0, 1); - Add(0, 1); - Add(0, 1); + 0; + 1; + 1; + 1; + 1; + 1; + 1; + 1; Add(Copy(x), Move(x)); Add(select M::R.f(r), select M::R.f(r)); Add(Add(Add(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_and.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_and.exp index 423cd4759e1ba..543d37df14725 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_and.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_and.exp @@ -4,17 +4,16 @@ module 0x8675309::M { f: bool, } private fun t0(x: bool,r: M::R) { - And(true, false); - And(false, true); - And(true, false); - And(true, true); + false; + false; + false; + true; And(Copy(x), Move(x)); And(select M::R.f(r), select M::R.f(r)); - And(And(true, false), And(true, false)); + false; { let M::R{ f: _ }: M::R = r; Tuple() } } - spec fun $t0(x: bool,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_and.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_and.exp index b14fc8ec4ceea..71c2416e6c98c 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_and.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_and.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - BitAnd(0, 0); - BitAnd(1, 0); - BitAnd(0, 1); - BitAnd(0, 1); - BitAnd(0, 1); - BitAnd(0, 1); - BitAnd(0, 1); - BitAnd(0, 1); + 0; + 0; + 0; + 0; + 0; + 0; + 0; + 0; BitAnd(Copy(x), Move(x)); BitAnd(select M::R.f(r), select M::R.f(r)); BitAnd(BitAnd(BitAnd(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_or.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_or.exp index 25f3dc95d374c..8f66b1c8d0fea 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_or.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_bit_or.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - BitOr(0, 0); - BitOr(1, 0); - BitOr(0, 1); - BitOr(0, 1); - BitOr(0, 1); - BitOr(0, 1); - BitOr(0, 1); - BitOr(0, 1); + 0; + 1; + 1; + 1; + 1; + 1; + 1; + 1; BitOr(Copy(x), Move(x)); BitOr(select M::R.f(r), select M::R.f(r)); BitOr(BitOr(BitOr(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_div.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_div.exp index e8af5e865fc7a..a1b45684f38d7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_div.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_div.exp @@ -6,12 +6,12 @@ module 0x8675309::M { private fun t0(x: u64,r: M::R) { Div(0, 0); Div(1, 0); - Div(0, 1); - Div(0, 1); - Div(0, 1); - Div(0, 1); - Div(0, 1); - Div(0, 1); + 0; + 0; + 0; + 0; + 0; + 0; Div(Copy(x), Move(x)); Div(select M::R.f(r), select M::R.f(r)); Div(Div(Div(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_geq.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_geq.exp index 9b75ba64bb02c..f630f7b9f1efc 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_geq.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_geq.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Ge(0, 0); - Ge(1, 0); - Ge(0, 1); - Ge(0, 1); - Ge(0, 1); - Ge(0, 1); - Ge(0, 1); - Ge(0, 1); + true; + true; + false; + false; + false; + false; + false; + false; Ge(Copy(x), Move(x)); Ge(select M::R.f(r), select M::R.f(r)); And(Ge(1, select M::R.f(r)), Ge(select M::R.f(r), 0)); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_gt.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_gt.exp index 0bb2052589f3d..46805bd4a7680 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_gt.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_gt.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Gt(0, 0); - Gt(1, 0); - Gt(0, 1); - Gt(0, 1); - Gt(0, 1); - Gt(0, 1); - Gt(0, 1); - Gt(0, 1); + false; + true; + false; + false; + false; + false; + false; + false; Gt(Copy(x), Move(x)); Gt(select M::R.f(r), select M::R.f(r)); And(Gt(1, select M::R.f(r)), Gt(select M::R.f(r), 0)); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_leq.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_leq.exp index 679d7c85ebed1..64c12af920785 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_leq.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_leq.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Le(0, 0); - Le(1, 0); - Le(0, 1); - Le(0, 1); - Le(0, 1); - Le(0, 1); - Le(0, 1); - Le(0, 1); + true; + false; + true; + true; + true; + true; + true; + true; Le(Copy(x), Move(x)); Le(select M::R.f(r), select M::R.f(r)); And(Le(1, select M::R.f(r)), Le(select M::R.f(r), 0)); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_lt.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_lt.exp index 497115f9f5cab..5c026e724bfe5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_lt.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_lt.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Lt(0, 0); - Lt(1, 0); - Lt(0, 1); - Lt(0, 1); - Lt(0, 1); - Lt(0, 1); - Lt(0, 1); - Lt(0, 1); + false; + false; + true; + true; + true; + true; + true; + true; Lt(Copy(x), Move(x)); Lt(select M::R.f(r), select M::R.f(r)); And(Lt(1, select M::R.f(r)), Lt(select M::R.f(r), 0)); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_mod.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_mod.exp index 8b1996edabf49..22932659c4c62 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_mod.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_mod.exp @@ -6,12 +6,12 @@ module 0x8675309::M { private fun t0(x: u64,r: M::R) { Mod(0, 0); Mod(1, 0); - Mod(0, 1); - Mod(0, 1); - Mod(0, 1); - Mod(0, 1); - Mod(0, 1); - Mod(0, 1); + 0; + 0; + 0; + 0; + 0; + 0; Mod(Copy(x), Move(x)); Mod(select M::R.f(r), select M::R.f(r)); Mod(Mod(Mod(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_mul.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_mul.exp index 512c7fbff2a96..7f94287c27364 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_mul.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_mul.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Mul(0, 0); - Mul(1, 0); - Mul(0, 1); - Mul(0, 1); - Mul(0, 1); - Mul(0, 1); - Mul(0, 1); - Mul(0, 1); + 0; + 0; + 0; + 0; + 0; + 0; + 0; + 0; Mul(Copy(x), Move(x)); Mul(select M::R.f(r), select M::R.f(r)); Mul(Mul(Mul(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_or.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_or.exp index 978261426d04e..55885283b3a8f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_or.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_or.exp @@ -4,17 +4,16 @@ module 0x8675309::M { f: bool, } private fun t0(x: bool,r: M::R) { - Or(true, false); - Or(false, true); - Or(true, false); - Or(true, true); + true; + true; + true; + true; Or(Copy(x), Move(x)); Or(select M::R.f(r), select M::R.f(r)); - Or(Or(true, false), Or(true, false)); + true; { let M::R{ f: _ }: M::R = r; Tuple() } } - spec fun $t0(x: bool,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_shl.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_shl.exp index 6fc6a13d786fc..8269bc78a32cf 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_shl.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_shl.exp @@ -5,17 +5,16 @@ module 0x8675309::M { b: u8, } private fun t0(x: u64,b: u8,r: M::R) { - Shl(0, 0); - Shl(1, 0); - Shl(0, 1); - Shl(0, 1); - Add(0, 1); - Shl(0, 1); - Shl(0, 1); + 0; + 1; + 0; + 0; + 1; + 0; + 0; Shl(Copy(x), Copy(b)); Shl(select M::R.f(r), select M::R.b(r)); Shl(Shl(Shl(1, select M::R.b(r)), select M::R.b(r)), 0); M::R{ f: _, b: _ }: M::R = r } - spec fun $t0(x: u64,b: u8,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_shr.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_shr.exp index cb38e2b9c8795..a6be9c9ad1bc9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_shr.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_shr.exp @@ -5,17 +5,16 @@ module 0x8675309::M { b: u8, } private fun t0(x: u64,b: u8,r: M::R) { - Shr(0, 0); - Shr(1, 0); - Shr(0, 1); - Shr(0, 1); - Add(0, 1); - Shr(0, 1); - Shr(0, 1); + 0; + 1; + 0; + 0; + 1; + 0; + 0; Shr(Copy(x), Copy(b)); Shr(select M::R.f(r), select M::R.b(r)); Shr(Shr(Shr(1, select M::R.b(r)), select M::R.b(r)), 0); M::R{ f: _, b: _ }: M::R = r } - spec fun $t0(x: u64,b: u8,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_sub.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_sub.exp index a88dd6dda55c8..7d5c5d56c48db 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_sub.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_sub.exp @@ -4,8 +4,8 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Sub(0, 0); - Sub(1, 0); + 0; + 1; Sub(0, 1); Sub(0, 1); Sub(0, 1); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/binary_xor.exp b/third_party/move/move-compiler-v2/tests/checking/typing/binary_xor.exp index 437433de65a87..e22e7ab1cb884 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/binary_xor.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/binary_xor.exp @@ -4,14 +4,14 @@ module 0x8675309::M { f: u64, } private fun t0(x: u64,r: M::R) { - Xor(0, 0); - Xor(1, 0); - Xor(0, 1); - Xor(0, 1); - Xor(0, 1); - Xor(0, 1); - Xor(0, 1); - Xor(0, 1); + 0; + 1; + 1; + 1; + 1; + 1; + 1; + 1; Xor(Copy(x), Move(x)); Xor(select M::R.f(r), select M::R.f(r)); Xor(Xor(Xor(1, select M::R.f(r)), select M::R.f(r)), 0); @@ -20,5 +20,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bind_unpack_references.exp b/third_party/move/move-compiler-v2/tests/checking/typing/bind_unpack_references.exp index d42536bd8e4fc..8fb1c92371dd1 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/bind_unpack_references.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/bind_unpack_references.exp @@ -43,7 +43,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bind_with_type_annot.exp b/third_party/move/move-compiler-v2/tests/checking/typing/bind_with_type_annot.exp index 3ff70e8fffe86..b1f83a37dd8ff 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/bind_with_type_annot.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/bind_with_type_annot.exp @@ -4,20 +4,13 @@ module 0x8675309::M { f: u64, } private fun t0() { + 0; { - let (): () = Tuple(); - { - let x: u64 = 0; - x; - { - let (x: u64, b: bool, M::R{ f: f: u64 }): (u64, bool, M::R) = Tuple(0, false, pack M::R(0)); - x; - b; - f; - Tuple() - } - } + let (x: u64, b: bool, M::R{ f: f: u64 }): (u64, bool, M::R) = Tuple(0, false, pack M::R(0)); + 0; + false; + 0; + Tuple() } } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/block_empty.exp b/third_party/move/move-compiler-v2/tests/checking/typing/block_empty.exp index 68cedf499bcff..010d6c24957fd 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/block_empty.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/block_empty.exp @@ -6,5 +6,4 @@ module 0x8675309::M { Tuple(); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/block_single_expr.exp b/third_party/move/move-compiler-v2/tests/checking/typing/block_single_expr.exp index b4969cbd26d35..d95820b32500b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/block_single_expr.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/block_single_expr.exp @@ -11,5 +11,4 @@ module 0x8675309::M { Tuple(0, false); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/block_with_statements.exp b/third_party/move/move-compiler-v2/tests/checking/typing/block_with_statements.exp index 2fac5f8683052..49da61a60044d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/block_with_statements.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/block_with_statements.exp @@ -4,18 +4,9 @@ module 0x8675309::M { dummy_field: bool, } private fun t0() { - { - let x: u64 = 0; - x - }; - { - let x: u64 = 0; - Borrow(Immutable)(x) - }; - { - let y: u64 = 0; - Borrow(Mutable)(Add(y, 1)) - }; + 0; + Borrow(Immutable)(0); + Borrow(Mutable)(1); M::R{ dummy_field: _ }: M::R = { let r: M::R = { let r: M::R = pack M::R(false); @@ -23,11 +14,7 @@ module 0x8675309::M { }; r }; - { - let x: u64 = 0; - Tuple(x, false) - }; + Tuple(0, false); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field.exp index a77fef2dbd839..7c47ac2ae0367 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field.exp @@ -6,7 +6,4 @@ module 0x8675309::M { private fun t0(s: &M::S,s_mut: &mut M::S,s_mut2: &mut M::S): (&u64, &u64, &mut u64) { Tuple(Borrow(Immutable)(select M::S.f(s)), Borrow(Immutable)(select M::S.f(s_mut)), Borrow(Mutable)(select M::S.f(s_mut2))) } - spec fun $t0(s: M::S,s_mut: M::S,s_mut2: M::S): (&u64, &u64, &mut u64) { - Tuple(select M::S.f(s), select M::S.f(s_mut), select M::S.f(s_mut2)) - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_chain.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_chain.exp index ad13c220f998e..3c302dc7a8381 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_chain.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_chain.exp @@ -21,5 +21,4 @@ module 0x8675309::M { Borrow(Mutable)(select M::X3.f(select M::X2.x3(select M::X1.x2(x1_mut)))); Tuple() } - spec fun $t0(x1: &M::X1,x1_mut: &mut M::X1); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_complex_root_expr.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_complex_root_expr.exp index 6bfa662fcf6ff..218cb1bd72df0 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_complex_root_expr.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_complex_root_expr.exp @@ -35,5 +35,4 @@ module 0x8675309::M { })); Tuple() } - spec fun $t0(cond: bool,s: &M::S,s_mut: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp index efe070de3778c..4df8a3de37629 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_internal.exp @@ -6,9 +6,6 @@ module 0x2::X { public fun s(): X::S { pack X::S(0) } - spec fun $s(): X::S { - pack X::S(0) - } } // end 0x2::X module 0x2::M { use 0x2::X; // resolved as: 0x2::X @@ -20,5 +17,4 @@ module 0x2::M { Abort(0) } } - spec fun $t0(); } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_non_ref_root.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_non_ref_root.exp index 20fe1ff6501e1..4c6f111bc8d45 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_non_ref_root.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_field_non_ref_root.exp @@ -18,5 +18,4 @@ module 0x8675309::M { })); Tuple() } - spec fun $t0(cond: bool,s: M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local.exp index 842809ea10afb..8ad47b62f6fa0 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local.exp @@ -40,6 +40,4 @@ module 0x8675309::M { } } } - spec fun $t0(b: bool,u: u64,s: M::S,r: M::R): M::R; - spec fun $t1(): M::R; } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp.exp index 12292632d81c8..7a4a44001c2a9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp.exp @@ -15,5 +15,4 @@ module 0x8675309::M { Borrow(Mutable)(pack M::S(false)); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp_resource.exp b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp_resource.exp index 2b3434f013fb1..0f0cb380f57f7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp_resource.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/borrow_local_temp_resource.exp @@ -11,5 +11,4 @@ module 0x8675309::M { Borrow(Mutable)(pack M::R(false)); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/break_any_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/break_any_type.exp index 7faf5076ad68d..83c13df9c03f2 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/break_any_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/break_any_type.exp @@ -26,7 +26,4 @@ module 0x8675309::M { } } } - spec fun $foo(c: M::Coin); - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/break_outside_loop.exp b/third_party/move/move-compiler-v2/tests/checking/typing/break_outside_loop.exp index 87fe5354e59ff..7352449fc0bf1 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/break_outside_loop.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/break_outside_loop.exp @@ -22,7 +22,4 @@ module 0x8675309::M { }; break } - spec fun $bar(); - spec fun $baz(x: u64): u64; - spec fun $foo(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/cast.exp b/third_party/move/move-compiler-v2/tests/checking/typing/cast.exp index a92e650209354..bf716645ad244 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/cast.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/cast.exp @@ -2,88 +2,28 @@ module 0x8675309::M { private fun t0(x8: u8,x64: u64,x128: u128) { { - let _: u8 = Cast(0); + let _: u8 = x8; { - let _: u64 = Cast(0); + let _: u64 = x64; { - let _: u128 = Cast(0); + let _: u128 = x128; { - let _: u8 = Cast(x8); + let _: u8 = Cast(x64); { - let _: u64 = Cast(x64); + let _: u64 = Cast(x128); { - let _: u128 = Cast(x128); + let _: u128 = Cast(x8); { - let _: u8 = Cast(x64); + let _: u8 = Cast(x128); { - let _: u64 = Cast(x128); + let _: u64 = Cast(x8); { - let _: u128 = Cast(x8); + let _: u128 = Cast(x64); { - let _: u8 = Cast(x128); + let _: u8 = Cast(340282366920938463463374607431768211455); { - let _: u64 = Cast(x8); - { - let _: u128 = Cast(x64); - { - let _: u8 = Cast(340282366920938463463374607431768211455); - { - let _: u64 = Cast(340282366920938463463374607431768211455); - { - let _: u128 = Cast(340282366920938463463374607431768211455); - Tuple() - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - spec fun $t0(x8: u8,x64: u64,x128: u128) { - { - let _: u8 = Cast(0); - { - let _: u64 = Cast(0); - { - let _: u128 = Cast(0); - { - let _: u8 = Cast(x8); - { - let _: u64 = Cast(x64); - { - let _: u128 = Cast(x128); - { - let _: u8 = Cast(x64); - { - let _: u64 = Cast(x128); - { - let _: u128 = Cast(x8); - { - let _: u8 = Cast(x128); - { - let _: u64 = Cast(x8); - { - let _: u128 = Cast(x64); - { - let _: u8 = Cast(340282366920938463463374607431768211455); - { - let _: u64 = Cast(340282366920938463463374607431768211455); - { - let _: u128 = Cast(340282366920938463463374607431768211455); - Tuple() - } - } - } - } + let _: u64 = Cast(340282366920938463463374607431768211455); + Tuple() } } } diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/conditional_global_operations.exp b/third_party/move/move-compiler-v2/tests/checking/typing/conditional_global_operations.exp index 7bb53ab5b96d2..03893e577f7ed 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/conditional_global_operations.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/conditional_global_operations.exp @@ -33,8 +33,4 @@ module 0x42::M { private fun ignore(_x: #0) { Abort(0) } - spec fun $ex(s: &signer,a1: address); - spec fun $ignore(_x: #0) { - Abort(0) - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/constant_all_valid_types.exp b/third_party/move/move-compiler-v2/tests/checking/typing/constant_all_valid_types.exp index 42c80841a05d9..925d790a3832e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/constant_all_valid_types.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/constant_all_valid_types.exp @@ -21,27 +21,6 @@ module 0x42::M { private fun t7(): vector { [97, 98, 99, 100] } - spec fun $t1(): u8 { - 0 - } - spec fun $t2(): u64 { - 0 - } - spec fun $t3(): u128 { - 0 - } - spec fun $t4(): bool { - false - } - spec fun $t5(): address { - 0x0 - } - spec fun $t6(): vector { - [1, 35] - } - spec fun $t7(): vector { - [97, 98, 99, 100] - } } // end 0x42::M module _0 { private fun t() { @@ -54,5 +33,4 @@ module _0 { [97, 98, 99, 100]; Tuple() } - spec fun $t(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/continue_any_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/continue_any_type.exp index cf34500b7cefe..cbe7dcef440a5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/continue_any_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/continue_any_type.exp @@ -26,7 +26,4 @@ module 0x8675309::M { } } } - spec fun $foo(c: M::Coin); - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/continue_outside_loop.exp b/third_party/move/move-compiler-v2/tests/checking/typing/continue_outside_loop.exp index f5e6c9a154f1e..d181cba0ed945 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/continue_outside_loop.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/continue_outside_loop.exp @@ -10,5 +10,4 @@ module 0x8675309::M { }; continue } - spec fun $foo(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/decl_unpack_references.exp b/third_party/move/move-compiler-v2/tests/checking/typing/decl_unpack_references.exp index 756da9b1792c5..4387496e98c3d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/decl_unpack_references.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/decl_unpack_references.exp @@ -37,7 +37,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/declare_with_type_annot.exp b/third_party/move/move-compiler-v2/tests/checking/typing/declare_with_type_annot.exp index c3ca89cbcda59..5cd9dba7c12ef 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/declare_with_type_annot.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/declare_with_type_annot.exp @@ -31,26 +31,8 @@ module 0x8675309::M { } private fun t0() { { - let (): (); - { - let x: u64; - { - let (x: u64, b: bool, M::R{ f: f: u64 }): (u64, bool, M::R); - Tuple() - } - } - } - } - spec fun $t0() { - { - let (): (); - { - let x: u64; - { - let (x: u64, b: bool, M::R{ f: f: u64 }): (u64, bool, M::R); - Tuple() - } - } + let (x: u64, b: bool, M::R{ f: f: u64 }): (u64, bool, M::R); + Tuple() } } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/derefrence.exp b/third_party/move/move-compiler-v2/tests/checking/typing/derefrence.exp index ee09b2e44f2ae..dc3e30ffad76f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/derefrence.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/derefrence.exp @@ -22,5 +22,4 @@ module 0x8675309::M { Deref(Borrow(Mutable)(select M::S.x(s_mut))); Tuple() } - spec fun $t0(x: &u64,x_mut: &mut u64,s: &M::S,s_mut: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/derefrence_reference.exp b/third_party/move/move-compiler-v2/tests/checking/typing/derefrence_reference.exp index 71a64776b02f1..e0ceb030cd10d 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/derefrence_reference.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/derefrence_reference.exp @@ -19,6 +19,4 @@ module 0x8675309::M { M::R{ dummy_field: _ }: M::R = Deref(Borrow(Mutable)(select M::B.r(b))); Tuple() } - spec fun $t0(r: &M::R,b: &M::B); - spec fun $t1(r: &mut M::R,b: &mut M::B); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/entry_on_any_vis.exp b/third_party/move/move-compiler-v2/tests/checking/typing/entry_on_any_vis.exp index 5fc41c86824fd..cd2aba36667c8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/entry_on_any_vis.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/entry_on_any_vis.exp @@ -9,13 +9,4 @@ module 0x2::M { friend entry fun f3() { Tuple() } - spec fun $f1() { - Tuple() - } - spec fun $f2() { - Tuple() - } - spec fun $f3() { - Tuple() - } } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq.exp b/third_party/move/move-compiler-v2/tests/checking/typing/eq.exp index a1638a37de6c5..a6accfca58e00 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/eq.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq.exp @@ -10,14 +10,14 @@ module 0x8675309::M { u: u64, } private fun t0(r: &M::R,r_mut: &mut M::R,s: M::S,s_ref: &M::S,s_mut: &mut M::S) { - Eq(0, 1); - Eq(0, 1); - Eq(0, 1); - Eq(0, 1); - Eq(0, 1); + false; + false; + false; + false; + false; Eq(Borrow(Immutable)(0), Borrow(Immutable)(1)); - Eq(true, false); - Eq(0, 1); + false; + false; Eq(Borrow(Immutable)(s), s_ref); Eq(Freeze(Borrow(Mutable)(s)), s_ref); Eq(Freeze(Borrow(Mutable)(s)), Freeze(s_mut)); @@ -33,5 +33,4 @@ module 0x8675309::M { Eq>(pack M::G(1), pack M::G(1)); Tuple() } - spec fun $t0(r: &M::R,r_mut: &mut M::R,s: M::S,s_ref: &M::S,s_mut: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline.exp b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline.exp index c325410bd1c70..cca546c4be80f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq_inline.exp @@ -9,14 +9,7 @@ warning: Unused parameter `f`. Consider removing or prefixing with an underscore // -- Model dump before bytecode pipeline module 0x42::m { private fun g() { - { - let (): (); - Tuple() - }; + Tuple(); Tuple() } - spec fun $foo(f: |&u64|) { - Tuple() - } - spec fun $g(); } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/eq_ref.exp b/third_party/move/move-compiler-v2/tests/checking/typing/eq_ref.exp index ee57d6ba08b58..6e434221162d6 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/eq_ref.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/eq_ref.exp @@ -12,7 +12,4 @@ module 0x42::m { Eq(Borrow(Immutable)(x), Borrow(Immutable)(y)); Tuple() } - spec fun $mut_ref_to_mut_ref(x: u64,y: u64); - spec fun $mut_ref_to_ref(x: u64,y: u64); - spec fun $ref_to_ref(x: u64,y: u64); } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/exp_list.exp b/third_party/move/move-compiler-v2/tests/checking/typing/exp_list.exp index 2532506ca21b2..2545066f07559 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/exp_list.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/exp_list.exp @@ -12,10 +12,4 @@ module 0x8675309::M { private fun t1(s: &M::S,r: &mut M::R): (u64, &M::S, &mut M::R) { Tuple(0, s, r) } - spec fun $t0(): (u64, M::S, M::R>) { - Tuple(0, pack M::S(false), pack M::R>(pack M::R(1))) - } - spec fun $t1(s: M::S,r: M::R): (u64, &M::S, &mut M::R) { - Tuple(0, s, r) - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/exp_list_resource_drop.exp b/third_party/move/move-compiler-v2/tests/checking/typing/exp_list_resource_drop.exp index 0949d153eda39..a4df2dd650411 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/exp_list_resource_drop.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/exp_list_resource_drop.exp @@ -15,5 +15,4 @@ module 0x8675309::M { Tuple(0, pack M::S(false), pack M::Box(Abort(0))); Tuple() } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/explicit_copy.exp b/third_party/move/move-compiler-v2/tests/checking/typing/explicit_copy.exp index dc0795516822a..7d8da10d750b3 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/explicit_copy.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/explicit_copy.exp @@ -8,16 +8,12 @@ module 0x8675309::M { } private fun t() { { - let u: u64 = 0; - { - let s: M::S = pack M::S(false); - Copy(u); - Copy(s); - s; - u; - Tuple() - } + let s: M::S = pack M::S(false); + Copy(0); + Copy(s); + s; + 0; + Tuple() } } - spec fun $t(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/explicit_move.exp b/third_party/move/move-compiler-v2/tests/checking/typing/explicit_move.exp index 6ff641ac71490..fca6d43199aa7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/explicit_move.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/explicit_move.exp @@ -21,5 +21,4 @@ module 0x8675309::M { } } } - spec fun $t(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins.exp b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins.exp index 7199fbb4b4663..49fea56f30c37 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins.exp @@ -43,6 +43,4 @@ module 0x8675309::M { } } } - spec fun $t0(a: &signer); - spec fun $t1(a: &signer); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_inferred.exp b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_inferred.exp index 65c968be2d1be..7d309300ae608 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_inferred.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_inferred.exp @@ -14,5 +14,4 @@ module 0x42::m { } } } - spec fun $foo(input: address): address; } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp index 03bac03de308e..8089a2fe7cb57 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/global_builtins_script.exp @@ -6,9 +6,6 @@ module 0x42::M { public fun new(): M::R { pack M::R(false) } - spec fun $new(): M::R { - pack M::R(false) - } } // end 0x42::M module _0 { use 0x42::M; // resolved as: 0x42::M @@ -20,5 +17,4 @@ module _0 { Tuple() } } - spec fun $test(account: signer); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/hex_and_decimal_address.exp b/third_party/move/move-compiler-v2/tests/checking/typing/hex_and_decimal_address.exp index 1008cd13e4cec..579a7a863a3ef 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/hex_and_decimal_address.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/hex_and_decimal_address.exp @@ -9,12 +9,6 @@ module 0x7b::M { public fun take(_s: M::S) { Tuple() } - spec fun $s(): M::S { - pack M::S(false) - } - spec fun $take(_s: M::S) { - Tuple() - } } // end 0x7b::M module _0 { private fun main() { @@ -24,5 +18,4 @@ module _0 { M::take(M::s()); Tuple() } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/if_branches_subtype.exp b/third_party/move/move-compiler-v2/tests/checking/typing/if_branches_subtype.exp index f9b7809d7dced..966b296b43294 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/if_branches_subtype.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/if_branches_subtype.exp @@ -48,52 +48,4 @@ module 0x8675309::M { } } } - spec fun $t0(cond: bool,u: u64,u_mut: u64) { - { - let _: u64 = if cond { - u - } else { - u_mut - }; - { - let _: u64 = if cond { - u_mut - } else { - u - }; - { - let _: u64 = if cond { - u_mut - } else { - u_mut - }; - Tuple() - } - } - } - } - spec fun $t1(cond: bool,u: u64,u_mut: u64) { - { - let (_, _): (&u64, &u64) = if cond { - Tuple(u, u) - } else { - Tuple(u_mut, u_mut) - }; - { - let (_, _): (&u64, &u64) = if cond { - Tuple(u_mut, u) - } else { - Tuple(u, u_mut) - }; - { - let (_, _): (&u64, &u64) = if cond { - Tuple(u, u_mut) - } else { - Tuple(u_mut, u) - }; - Tuple() - } - } - } - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/if_condition.exp b/third_party/move/move-compiler-v2/tests/checking/typing/if_condition.exp index 39ebe1a21b29e..554498b46c986 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/if_condition.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/if_condition.exp @@ -13,23 +13,15 @@ module 0x8675309::M { } } private fun t1() { - if { - let x: bool = true; - x - } { + if true { Tuple() } else { Tuple() }; - if { - let x: bool = false; - x - } { + if false { Tuple() } else { Tuple() } } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/if_default_else.exp b/third_party/move/move-compiler-v2/tests/checking/typing/if_default_else.exp index 8fb3f3768d6cc..4794c6c8e1d7c 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/if_default_else.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/if_default_else.exp @@ -14,11 +14,8 @@ module 0x8675309::M { }; { let (): () = if cond { - { - let x: u64 = 0; - x; - Tuple() - } + 0; + Tuple() } else { Tuple() }; @@ -26,5 +23,4 @@ module 0x8675309::M { } } } - spec fun $t0(cond: bool); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/if_matched_branches.exp b/third_party/move/move-compiler-v2/tests/checking/typing/if_matched_branches.exp index 7e0cbb686ac44..dde6ad390175b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/if_matched_branches.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/if_matched_branches.exp @@ -52,7 +52,4 @@ module 0x8675309::M { }; Tuple() } - spec fun $t0(cond: bool); - spec fun $t1(cond: bool); - spec fun $t2(cond: bool); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field.exp index e2c6d6e090dbc..093708d3ebf02 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field.exp @@ -6,7 +6,4 @@ module 0x8675309::M { private fun t0(s: &M::S,s_mut: &mut M::S): (u64, u64) { Tuple(select M::S.f(s), select M::S.f(s_mut)) } - spec fun $t0(s: M::S,s_mut: M::S): (u64, u64) { - Tuple(select M::S.f(s), select M::S.f(s_mut)) - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_chain.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_chain.exp index af55a403647b7..997680d55682e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_chain.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_chain.exp @@ -16,5 +16,4 @@ module 0x8675309::M { select M::X3.f(select M::X2.x3(x2_mut)); Tuple() } - spec fun $t0(x1: &M::X1,x1_mut: &mut M::X1,x2: &M::X2,x2_mut: &mut M::X2); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_complex_root_expr.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_complex_root_expr.exp index 23cc396f13965..a147b6c595b52 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_complex_root_expr.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_complex_root_expr.exp @@ -30,5 +30,4 @@ module 0x8675309::M { }); Tuple() } - spec fun $t0(cond: bool,s: &M::S,s_mut: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp index 1cb824d404b3a..b4233e2508643 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_internal.exp @@ -6,9 +6,6 @@ module 0x2::X { public fun s(): X::S { pack X::S(0) } - spec fun $s(): X::S { - pack X::S(0) - } } // end 0x2::X module 0x2::M { use 0x2::X; // resolved as: 0x2::X @@ -20,5 +17,4 @@ module 0x2::M { Abort(0) } } - spec fun $t0(); } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp index 3b81d3426b962..52450acd4c3d5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_non_local_root.exp @@ -24,11 +24,4 @@ module 0x8675309::M { }); Tuple() } - spec fun $bar(): M::S { - pack M::S(0) - } - spec fun $foo(): M::S { - Abort(0) - } - spec fun $t0(cond: bool,_s: M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_root.exp b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_root.exp index a5763794a2c48..7f7277f58a41e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_root.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/implicit_deref_borrow_field_non_ref_root.exp @@ -12,5 +12,4 @@ module 0x8675309::M { }); Tuple() } - spec fun $t0(cond: bool,s: M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/large_binop.exp b/third_party/move/move-compiler-v2/tests/checking/typing/large_binop.exp index 1326a8e29d353..f73d7143c36ca 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/large_binop.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/large_binop.exp @@ -1,8 +1,7 @@ // -- Model dump before bytecode pipeline module _0 { private fun main() { - Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(Or(And(And(true, true), Not(false)), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))), And(And(Neq>([104, 101, 108, 108, 111], [98, 121, 101]), And(true, true)), Not(false))), And(Eq(Shl(1, 7), 128), Eq(Shr(128, 7), 1))), And(Eq(Div(255, 2), 127), Eq(Mod(255, 2), 1))), And(Eq(Add(254, 1), 255), Eq(Sub(255, 255), 0))), And(Eq(BitAnd(255, 255), 255), Eq(BitOr(255, 255), 255))), And(Eq(Xor(255, 255), 0), Eq>([66], [66]))); + true; Tuple() } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/loop_body.exp b/third_party/move/move-compiler-v2/tests/checking/typing/loop_body.exp index 01b2ba7f6ba1e..c38a819cc31da 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/loop_body.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/loop_body.exp @@ -17,11 +17,8 @@ module 0x8675309::M { } private fun t3() { loop { - { - let x: u64 = 0; - x; - Tuple() - } + 0; + Tuple() } } private fun t4() { @@ -61,47 +58,4 @@ module 0x8675309::M { } } } - spec fun $t0() { - loop { - Tuple() - } - } - spec fun $t1() { - loop { - Tuple() - } - } - spec fun $t2() { - loop { - Tuple() - } - } - spec fun $t3(); - spec fun $t4() { - loop { - if true { - Tuple() - } else { - Tuple() - } - } - } - spec fun $t5(); - spec fun $t6() { - loop { - continue - } - } - spec fun $t7() { - loop { - continue - } - } - spec fun $t8() { - loop { - loop { - break - } - } - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type.exp index 1a3e75d31ec27..6e4b1c4bce1ba 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/loop_result_type.exp @@ -16,11 +16,8 @@ module 0x2::M { } private fun t1(): u64 { loop { - { - let x: u64 = 0; - x; - Tuple() - } + 0; + Tuple() } } private fun t2() { @@ -54,36 +51,4 @@ module 0x2::M { } } } - spec fun $foo(_x: u64) { - Tuple() - } - spec fun $t0(): X::R { - loop { - Tuple() - } - } - spec fun $t1(): u64; - spec fun $t2() { - M::$foo(loop { - Tuple() - }) - } - spec fun $t3(): X::R; - spec fun $t4() { - { - let (): () = loop { - break - }; - { - let (): () = loop { - if false { - break - } else { - Tuple() - } - }; - Tuple() - } - } - } } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments.exp b/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments.exp index 7e3ee1ac1072f..f48682cc04cc9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments.exp @@ -3,7 +3,4 @@ module _0 { private fun main(_sender: signer,_a: address,_x8: u8,_x64: u64,_x128: u128,_b: bool,_v8: vector,_va: vector
,_v64: vector,_v128: vector,_vb: vector,_vv8: vector>,_vva: vector>,_vv64: vector>,_vv128: vector>,_vvb: vector>,_vvv8: vector>>,_vvva: vector>>,_vvv64: vector>>,_vvv128: vector>>,_vvvb: vector>>,_vvvv8: vector>>>,_vvvva: vector>>>,_vvvv64: vector>>>,_vvvv128: vector>>>,_vvvvb: vector>>>) { Tuple() } - spec fun $main(_sender: signer,_a: address,_x8: u8,_x64: u64,_x128: u128,_b: bool,_v8: vector,_va: vector
,_v64: vector,_v128: vector,_vb: vector,_vv8: vector>,_vva: vector>,_vv64: vector>,_vv128: vector>,_vvb: vector>,_vvv8: vector>>,_vvva: vector>>,_vvv64: vector>>,_vvv128: vector>>,_vvvb: vector>>,_vvvv8: vector>>>,_vvvva: vector>>>,_vvvv64: vector>>>,_vvvv128: vector>>>,_vvvvb: vector>>>) { - Tuple() - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments_various_caes.exp b/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments_various_caes.exp index c88109be5b297..4506397b17329 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments_various_caes.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/main_arguments_various_caes.exp @@ -12,14 +12,10 @@ module 0x42::M { public fun eat(r: M::R) { M::R{ dummy_field: _ }: M::R = r } - spec fun $eat(r: M::R); } // end 0x42::M module _0 { use 0x42::M::{S, R, Cup}; // resolved as: 0x42::M private fun main(_s: &signer,_a0: #0,_a1: vector<#0>,_a2: vector>,_a3: M::S,_a4: M::R,_a5: M::Cup,_a6: M::Cup<#0>,_a7: vector) { Abort(0) } - spec fun $main(_s: signer,_a0: #0,_a1: vector<#0>,_a2: vector>,_a3: M::S,_a4: M::R,_a5: M::Cup,_a6: M::Cup<#0>,_a7: vector) { - Abort(0) - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/main_call_entry.exp b/third_party/move/move-compiler-v2/tests/checking/typing/main_call_entry.exp index 31ba22c857ba3..f8cdb6a2f8ceb 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/main_call_entry.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/main_call_entry.exp @@ -3,15 +3,9 @@ module 0x2::X { public entry fun foo() { Tuple() } - spec fun $foo() { - Tuple() - } } // end 0x2::X module _0 { private fun main() { X::foo() } - spec fun $main() { - X::$foo() - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/main_with_type_parameters.exp b/third_party/move/move-compiler-v2/tests/checking/typing/main_with_type_parameters.exp index 9882da01f472b..cb4ca6a2d2269 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/main_with_type_parameters.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/main_with_type_parameters.exp @@ -3,7 +3,4 @@ module _0 { private fun main() { Tuple() } - spec fun $main() { - Tuple() - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/module_call_entry_function.exp b/third_party/move/move-compiler-v2/tests/checking/typing/module_call_entry_function.exp index ee275a066ee18..cf5eb639e99ea 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/module_call_entry_function.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/module_call_entry_function.exp @@ -3,9 +3,6 @@ module 0x2::Y { friend fun f_friend() { Tuple() } - spec fun $f_friend() { - Tuple() - } } // end 0x2::Y module 0x2::X { public fun f_public() { @@ -14,12 +11,6 @@ module 0x2::X { public entry fun f_script() { Tuple() } - spec fun $f_public() { - Tuple() - } - spec fun $f_script() { - Tuple() - } } // end 0x2::X module 0x2::M { use 0x2::X; // resolved as: 0x2::X @@ -57,37 +48,4 @@ module 0x2::M { public entry fun f_script_call_self_script() { M::f_script() } - spec fun $f_friend() { - Tuple() - } - spec fun $f_private() { - Tuple() - } - spec fun $f_public() { - Tuple() - } - spec fun $f_script() { - Tuple() - } - spec fun $f_script_call_friend() { - Y::$f_friend() - } - spec fun $f_script_call_public() { - X::$f_public() - } - spec fun $f_script_call_script() { - X::$f_script() - } - spec fun $f_script_call_self_friend() { - M::$f_friend() - } - spec fun $f_script_call_self_private() { - M::$f_private() - } - spec fun $f_script_call_self_public() { - M::$f_public() - } - spec fun $f_script_call_self_script() { - M::$f_script() - } } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/module_call_explicit_type_arguments.exp b/third_party/move/move-compiler-v2/tests/checking/typing/module_call_explicit_type_arguments.exp index 2e8833c975bc3..5b26dfa27bfad 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/module_call_explicit_type_arguments.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/module_call_explicit_type_arguments.exp @@ -15,9 +15,4 @@ module 0x8675309::M { M::foo(u, v); Tuple() } - spec fun $foo(_x: #0,_y: #1) { - Tuple() - } - spec fun $t1(); - spec fun $t2(t: #0,u: #1,v: #2); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/move_from_type_argument.exp b/third_party/move/move-compiler-v2/tests/checking/typing/move_from_type_argument.exp index 65c968be2d1be..7d309300ae608 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/move_from_type_argument.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/move_from_type_argument.exp @@ -14,5 +14,4 @@ module 0x42::m { } } } - spec fun $foo(input: address): address; } // end 0x42::m diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutable_eq_and_neq.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutable_eq_and_neq.exp index ea06e14486f78..fa05b02099235 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutable_eq_and_neq.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutable_eq_and_neq.exp @@ -42,17 +42,4 @@ module 0x8675309::M { select M::B.f(select M::P.b1(p)) = comp } } - spec fun $t(r1: &mut u64,r2: &mut u64,s: &mut M::S); - spec fun $t1(p: M::P) { - { - let comp: bool = Eq(select M::P.b1(p), select M::P.b2(p)); - select M::B.f(select M::P.b1(p)) = comp - } - } - spec fun $t2(p: M::P) { - { - let comp: bool = Neq(select M::P.b1(p), select M::P.b2(p)); - select M::B.f(select M::P.b1(p)) = comp - } - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutate.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutate.exp index 4f7d4648eaca7..54038d4b21d70 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutate.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutate.exp @@ -31,15 +31,4 @@ module 0x8675309::M { Tuple() } } - spec fun $bar(s: M::S): M::S { - s - } - spec fun $baz(): M::S { - pack M::S(0) - } - spec fun $foo(x: u64): u64 { - x - } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp index cf5af9d3c293a..f9d183712c210 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_field_internal.exp @@ -6,9 +6,6 @@ module 0x2::X { public fun s(): X::S { pack X::S(0) } - spec fun $s(): X::S { - pack X::S(0) - } } // end 0x2::X module 0x2::M { use 0x2::X; // resolved as: 0x2::X @@ -20,5 +17,4 @@ module 0x2::M { Abort(0) } } - spec fun $t0(); } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_immutable.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_immutable.exp index ee9bbe548d5da..79e4bf2e421fa 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_immutable.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_immutable.exp @@ -18,5 +18,4 @@ module 0x8675309::M { } } } - spec fun $t0(s: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_resource.exp b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_resource.exp index c7efc8c2c837f..f307869a7753b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/mutate_resource.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/mutate_resource.exp @@ -15,7 +15,4 @@ module 0x8675309::M { r = x; Tuple() } - spec fun $t0(r: &mut M::R); - spec fun $t1(r: &mut #0,x: #0); - spec fun $t2(r: &mut #0,x: #0); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/neq.exp b/third_party/move/move-compiler-v2/tests/checking/typing/neq.exp index 01c6b99e9459f..46e6ed2a45ad9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/neq.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/neq.exp @@ -10,14 +10,14 @@ module 0x8675309::M { u: u64, } private fun t0(r: &M::R,r_mut: &mut M::R,s: M::S,s_ref: &M::S,s_mut: &mut M::S) { - Neq(0, 1); - Neq(0, 1); - Neq(0, 1); - Neq(0, 1); - Neq(0, 1); + true; + true; + true; + true; + true; Neq(Borrow(Immutable)(0), Borrow(Immutable)(1)); - Neq(true, false); - Neq(0, 1); + true; + true; Neq(Borrow(Immutable)(s), s_ref); Neq(Freeze(Borrow(Mutable)(s)), s_ref); Neq(Freeze(Borrow(Mutable)(s)), Freeze(s_mut)); @@ -33,5 +33,4 @@ module 0x8675309::M { Neq>(pack M::G(1), pack M::G(2)); Tuple() } - spec fun $t0(r: &M::R,r_mut: &mut M::R,s: M::S,s_ref: &M::S,s_mut: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/nested_post_process.exp b/third_party/move/move-compiler-v2/tests/checking/typing/nested_post_process.exp index 0e735613d04d3..57638fc0f6cd1 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/nested_post_process.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/nested_post_process.exp @@ -49,6 +49,4 @@ module 0x42::simple_map { } } } - spec fun $borrow(map: &simple_map::SimpleMap<#0, #1>,key: �):  - spec fun $find(map: &simple_map::SimpleMap<#0, #1>,key: �): option::Option; } // end 0x42::simple_map diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/other_builtins.exp b/third_party/move/move-compiler-v2/tests/checking/typing/other_builtins.exp index 5f0f4ab5f522e..5744a7d5ce9e7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/other_builtins.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/other_builtins.exp @@ -6,20 +6,16 @@ module 0x8675309::M { private fun foo(x: &mut u64) { Freeze(x); Freeze>(Borrow(Mutable)(M::any>())); - if And(true, false) { + if false { Tuple() } else { Abort(Deref(x)) }; - if Or(true, false) { + if true { Tuple() } else { - Abort(Cast(0)) + Abort(0) }; Tuple() } - spec fun $any(): #0 { - Abort(0) - } - spec fun $foo(x: &mut u64); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/pack.exp b/third_party/move/move-compiler-v2/tests/checking/typing/pack.exp index 11761557cc90e..0f3dc465a790b 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/pack.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/pack.exp @@ -27,27 +27,23 @@ module 0x8675309::M { } }; { - let f: u64 = 0; + let s: M::S = pack M::S(0); { - let s: M::S = pack M::S(0); + let n1: M::Nat = pack M::Nat(0); { - let n1: M::Nat = pack M::Nat(f); - { - let n2: M::Nat = pack M::Nat(Deref(Borrow(Immutable)(s))); - M::R{ s: _, f: _, n1: _, n2: _ }: M::R = { - let $s: M::S = s; - { - let $n2: M::Nat = n2; - pack M::R($s, f, n1, $n2) - } - }; - pack M::Nat>>(pack M::Nat>(pack M::Nat(pack M::S(f)))); - Tuple() - } + let n2: M::Nat = pack M::Nat(Deref(Borrow(Immutable)(s))); + M::R{ s: _, f: _, n1: _, n2: _ }: M::R = { + let $s: M::S = s; + { + let $n2: M::Nat = n2; + pack M::R($s, 0, n1, $n2) + } + }; + pack M::Nat>>(pack M::Nat>(pack M::Nat(pack M::S(0)))); + Tuple() } } } } } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/return_any_type.exp b/third_party/move/move-compiler-v2/tests/checking/typing/return_any_type.exp index aaf22fedf1e51..aaa4fa5685abc 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/return_any_type.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/return_any_type.exp @@ -15,7 +15,4 @@ module 0x8675309::M { M::foo(return Tuple()); Tuple() } - spec fun $foo(c: M::Coin); - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/return_type_explicit_exp.exp b/third_party/move/move-compiler-v2/tests/checking/typing/return_type_explicit_exp.exp index 239cdbbf7bb8c..087f85511cbb4 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/return_type_explicit_exp.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/return_type_explicit_exp.exp @@ -23,7 +23,4 @@ module 0x8675309::M { }; Abort(0) } - spec fun $t0(); - spec fun $t1(): u64; - spec fun $t2(): (u64, bool, M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/return_type_last_exp.exp b/third_party/move/move-compiler-v2/tests/checking/typing/return_type_last_exp.exp index 0c9bae328ce60..d469d10153e28 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/return_type_last_exp.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/return_type_last_exp.exp @@ -12,13 +12,4 @@ module 0x8675309::M { private fun t2(): (u64, bool, M::R) { Tuple(0, false, pack M::R(false)) } - spec fun $t0() { - Tuple() - } - spec fun $t1(): u64 { - 0 - } - spec fun $t2(): (u64, bool, M::R) { - Tuple(0, false, pack M::R(false)) - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/seq_ignores_value.exp b/third_party/move/move-compiler-v2/tests/checking/typing/seq_ignores_value.exp index 9f003662ab785..36751b65e11ae 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/seq_ignores_value.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/seq_ignores_value.exp @@ -23,8 +23,4 @@ module 0x8675309::M { }; Tuple() } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(); - spec fun $t3(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/typing/shadowing.exp index 86887e80731ab..68a67cb66924f 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/shadowing.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/shadowing.exp @@ -5,69 +5,39 @@ module 0x8675309::M { b: bool, } private fun t0() { - { - let x: u64 = 0; - { - let x: bool = false; - x; - Tuple() - }; - x; - { - let x: bool = false; - x; - Tuple() - }; - x; - { - let x: bool = false; - { - let x: address = 0x0; - x; - Tuple() - }; - x; - Tuple() - }; - x; - Tuple() - } + false; + Tuple(); + 0; + false; + Tuple(); + 0; + 0x0; + Tuple(); + false; + Tuple(); + 0; + Tuple() } private fun t1(cond: bool) { - { - let x: u64 = 0; - if cond { - { - let (a: bool, x: bool): (bool, bool) = Tuple(false, false); - And(a, x); - Tuple() - } - } else { - { - let x: address = 0x0; - x; - Tuple() - } - }; - x; + if cond { + false; Tuple() - } + } else { + 0x0; + Tuple() + }; + 0; + Tuple() } private fun t2() { - { - let x: u64 = 0; - loop { - { - let M::S{ f: _, b: x: bool }: M::S = pack M::S(0, false); - x; - break - } - }; - x; - Tuple() - } + loop { + { + let M::S{ f: _, b: x: bool }: M::S = pack M::S(0, false); + false; + break + } + }; + 0; + Tuple() } - spec fun $t0(); - spec fun $t1(cond: bool); - spec fun $t2(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/spec_block_ok.exp b/third_party/move/move-compiler-v2/tests/checking/typing/spec_block_ok.exp index 8be671873873c..34634cdef94de 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/spec_block_ok.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/spec_block_ok.exp @@ -5,7 +5,4 @@ module 0x8675309::M { } } - spec fun $specs_in_fun(_x: u64) { - NoOp() - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_annotation.exp b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_annotation.exp index b01b49417042f..8eb85819927a8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_annotation.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_annotation.exp @@ -19,6 +19,4 @@ module 0x8675309::M { Tuple(Borrow(Mutable)(0), Borrow(Mutable)(0)); Tuple() } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_args.exp b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_args.exp index f350c2215671f..4c9d1b229c259 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_args.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_args.exp @@ -28,19 +28,4 @@ module 0x8675309::M { M::imm_imm(Freeze(Borrow(Mutable)(0)), Freeze(Borrow(Mutable)(0))); Tuple() } - spec fun $imm(_x: #0) { - Tuple() - } - spec fun $imm_imm(_x: #0,_y: #0) { - Tuple() - } - spec fun $imm_mut(_x: #0,_y: #0) { - Tuple() - } - spec fun $mut_imm(_x: #0,_y: #0) { - Tuple() - } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(f: |(&u64, &mut u64)|); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_assign.exp b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_assign.exp index 6fe9decfc40b6..c7e1c0988c8b9 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_assign.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_assign.exp @@ -32,6 +32,4 @@ module 0x8675309::M { } } } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_bind.exp b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_bind.exp index 4cd2751ce513e..f54d3af58d527 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_bind.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_bind.exp @@ -28,6 +28,4 @@ module 0x8675309::M { } } } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_return.exp b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_return.exp index 60952791f2a33..0b17827c593fd 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/subtype_return.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/subtype_return.exp @@ -18,19 +18,4 @@ module 0x8675309::M { private fun t4(u1: &mut u64,u2: &mut u64): (&u64, &u64) { Tuple(u1, u2) } - spec fun $t0(u: u64): u64 { - u - } - spec fun $t1(s: M::S): M::S { - s - } - spec fun $t2(u1: u64,u2: u64): (&u64, &mut u64) { - Tuple(u1, u2) - } - spec fun $t3(u1: u64,u2: u64): (&mut u64, &u64) { - Tuple(u1, u2) - } - spec fun $t4(u1: u64,u2: u64): (&u64, &u64) { - Tuple(u1, u2) - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_pack.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_pack.exp index 5ed59ad9639e2..0d0ae4c52ac2e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_pack.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_pack.exp @@ -15,5 +15,4 @@ module 0x42::M { } } } - spec fun $t0(); } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack.exp index 85d43827dec17..ad69dde0ab356 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack.exp @@ -20,8 +20,4 @@ module 0x8675309::M { } } } - spec fun $new(): M::Box<#0> { - Abort(0) - } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack_assign.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack_assign.exp index cdeef21cf8eb5..8d92a003aa660 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack_assign.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_single_unpack_assign.exp @@ -28,8 +28,4 @@ module 0x8675309::M { } } } - spec fun $new(): M::Box<#0> { - Abort(0) - } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_pack.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_pack.exp index 4d031b81d7522..00bbfae97d9e5 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_pack.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_pack.exp @@ -12,15 +12,6 @@ module 0x2::Container { public fun put(_self: &mut Container::T<#0>,_item: #0) { Abort(0) } - spec fun $get(_self: Container::T<#0>): #0 { - Abort(0) - } - spec fun $new(): Container::T<#0> { - Abort(0) - } - spec fun $put(_self: Container::T<#0>,_item: #0) { - Abort(0) - } } // end 0x2::Container module 0x2::M { use 0x2::Container; // resolved as: 0x2::Container @@ -41,5 +32,4 @@ module 0x2::M { } } } - spec fun $t0(): M::Box; } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack.exp index d34b5061d2012..7cd966403489e 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack.exp @@ -12,15 +12,6 @@ module 0x2::Container { public fun put(_self: &mut Container::T<#0>,_item: #0) { Abort(0) } - spec fun $get(_self: Container::T<#0>): #0 { - Abort(0) - } - spec fun $new(): Container::T<#0> { - Abort(0) - } - spec fun $put(_self: Container::T<#0>,_item: #0) { - Abort(0) - } } // end 0x2::Container module 0x2::M { use 0x2::Container; // resolved as: 0x2::Container @@ -52,9 +43,4 @@ module 0x2::M { } } } - spec fun $new(): M::Box<#0> { - Abort(0) - } - spec fun $t0(): u64; - spec fun $t1(): M::Box>; } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack_assign.exp b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack_assign.exp index 0776470333b1d..85dc36f23ede4 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack_assign.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/type_variable_join_threaded_unpack_assign.exp @@ -12,15 +12,6 @@ module 0x2::Container { public fun put(_self: &mut Container::T<#0>,_item: #0) { Abort(0) } - spec fun $get(_self: Container::T<#0>): #0 { - Abort(0) - } - spec fun $new(): Container::T<#0> { - Abort(0) - } - spec fun $put(_self: Container::T<#0>,_item: #0) { - Abort(0) - } } // end 0x2::Container module 0x2::M { use 0x2::Container; // resolved as: 0x2::Container @@ -60,9 +51,4 @@ module 0x2::M { } } } - spec fun $new(): M::Box<#0> { - Abort(0) - } - spec fun $t0(): u64; - spec fun $t1(): M::Box>; } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unary_not.exp b/third_party/move/move-compiler-v2/tests/checking/typing/unary_not.exp index a46cbc97f9ce5..00574c36072b0 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/unary_not.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/unary_not.exp @@ -4,8 +4,8 @@ module 0x8675309::M { f: bool, } private fun t0(x: bool,r: M::R) { - Not(true); - Not(false); + false; + true; Not(x); Not(Copy(x)); Not(Move(x)); @@ -15,5 +15,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: bool,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unit.exp b/third_party/move/move-compiler-v2/tests/checking/typing/unit.exp index 23cb098cc0778..0e7cba1feba85 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/unit.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/unit.exp @@ -1,11 +1,7 @@ // -- Model dump before bytecode pipeline module 0x8675309::M { private fun foo() { - { - let (): () = Tuple(); - Tuple(); - Tuple() - } + Tuple(); + Tuple() } - spec fun $foo(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param.exp b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param.exp index 215ee9169cc65..5563a7c328b11 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/unused_lambda_param.exp @@ -27,39 +27,15 @@ warning: Function `0xc0ffee::m::unused_lambda_suppressed2` is unused: it has no // -- Model dump before bytecode pipeline module 0xc0ffee::m { private fun unused_lambda() { - { - let (p: u64): (u64) = Tuple(0); - { - let (x: u64): (u64) = Tuple(p); - 1 - } - }; + 1; Tuple() } private fun unused_lambda_suppressed1() { - { - let (p: u64): (u64) = Tuple(0); - { - let (_x: u64): (u64) = Tuple(p); - 1 - } - }; + 1; Tuple() } private fun unused_lambda_suppressed2() { - { - let (p: u64): (u64) = Tuple(0); - { - let (_): (u64) = Tuple(p); - 1 - } - }; + 1; Tuple() } - spec fun $test(p: u64,f: |u64|u64): u64 { - (f)(p) - } - spec fun $unused_lambda(); - spec fun $unused_lambda_suppressed1(); - spec fun $unused_lambda_suppressed2(); } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/unused_local.exp b/third_party/move/move-compiler-v2/tests/checking/typing/unused_local.exp index 157ab8a038951..91477eb246aa7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/unused_local.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/unused_local.exp @@ -139,16 +139,10 @@ module 0x8675309::M { g: bool, } private fun t0() { - { - let x: u64; - Tuple() - } + Tuple() } private fun t1() { - { - let (x: u64, y: u64): (u64, u64); - Tuple() - } + Tuple() } private fun t2() { { @@ -160,16 +154,10 @@ module 0x8675309::M { Tuple() } private fun unused_local_suppressed1() { - { - let _x: u64; - Tuple() - } + Tuple() } private fun unused_local_suppressed2() { - { - let _: u64; - Tuple() - } + Tuple() } private native fun unused_native_ok(x: u64,y: bool); private fun unused_param(x: u64) { @@ -187,53 +175,4 @@ module 0x8675309::M { private fun unused_param_suppressed2(_x: u64) { Tuple() } - spec fun $t0() { - { - let x: u64; - Tuple() - } - } - spec fun $t1() { - { - let (x: u64, y: u64): (u64, u64); - Tuple() - } - } - spec fun $t2() { - { - let M::S{ f: f: u64, g: g: bool }: M::S; - Tuple() - } - } - spec fun $two_unused(x: u64,y: bool) { - Tuple() - } - spec fun $unused_local_suppressed1() { - { - let _x: u64; - Tuple() - } - } - spec fun $unused_local_suppressed2() { - { - let _: u64; - Tuple() - } - } - spec fun $unused_native_ok(x: u64,y: bool); - spec fun $unused_param(x: u64) { - Tuple() - } - spec fun $unused_param1_used_param2(x: u64,y: bool): bool { - y - } - spec fun $unused_param2_used_param1(x: u64,y: bool): u64 { - x - } - spec fun $unused_param_suppressed1(_: u64) { - Tuple() - } - spec fun $unused_param_suppressed2(_x: u64) { - Tuple() - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/use_local.exp b/third_party/move/move-compiler-v2/tests/checking/typing/use_local.exp index 1864514388e39..5cc996e832f89 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/use_local.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/use_local.exp @@ -8,18 +8,14 @@ module 0x8675309::M { } private fun t() { { - let u: u64 = 0; + let s: M::S = pack M::S(false); { - let s: M::S = pack M::S(false); - { - let r: M::R = pack M::R(false); - u; - s; - M::R{ dummy_field: _ }: M::R = r; - Tuple() - } + let r: M::R = pack M::R(false); + 0; + s; + M::R{ dummy_field: _ }: M::R = r; + Tuple() } } } - spec fun $t(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/values.exp b/third_party/move/move-compiler-v2/tests/checking/typing/values.exp index dffa79fc17165..4b5bcacdedbcc 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/values.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/values.exp @@ -8,5 +8,4 @@ module 0x8675309::M { false; Tuple() } - spec fun $t(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/vector_basic_cases.exp b/third_party/move/move-compiler-v2/tests/checking/typing/vector_basic_cases.exp index a815d680f653b..97e9c3cb46940 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/vector_basic_cases.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/vector_basic_cases.exp @@ -4,9 +4,9 @@ module 0x42::Test { dummy_field: bool, } private fun many() { - Vector(0, 1, 2); - Vector(0, 1, 2); - Vector(0, 1, 2); + [Number(0), Number(1), Number(2)]; + [Number(0), Number(1), Number(2)]; + [Number(0), Number(1), Number(2)]; Vector
(0x0, 0x1); Vector(pack Test::X(false), pack Test::X(false)); Vector>(Vector
(), Vector
()); @@ -18,16 +18,13 @@ module 0x42::Test { Tuple() } private fun one() { - Vector(0); - Vector(0); - Vector(0); + [Number(0)]; + [Number(0)]; + [Number(0)]; Vector
(0x0); Vector(pack Test::X(false)); Vector>(Vector
()); Vector>>(Vector>(Vector
())); Tuple() } - spec fun $many(); - spec fun $none(); - spec fun $one(); } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/while_body.exp b/third_party/move/move-compiler-v2/tests/checking/typing/while_body.exp index 19ed6818eefe9..c71c0fe643d07 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/while_body.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/while_body.exp @@ -24,11 +24,8 @@ module 0x8675309::M { }; loop { if cond { - { - let x: u64 = 0; - x; - Tuple() - } + 0; + Tuple() } else { break } @@ -93,5 +90,4 @@ module 0x8675309::M { } } } - spec fun $t0(cond: bool); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/while_condition.exp b/third_party/move/move-compiler-v2/tests/checking/typing/while_condition.exp index 30e41c621b911..a939866f306f8 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/while_condition.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/while_condition.exp @@ -18,26 +18,18 @@ module 0x8675309::M { } private fun t1() { loop { - if { - let foo: bool = true; - foo - } { + if true { Tuple() } else { break } }; loop { - if { - let bar: bool = false; - bar - } { + if false { Tuple() } else { break } } } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp index e9ef22451ae94..da933d7ffa6a1 100644 --- a/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp +++ b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp @@ -1,33 +1,6 @@ // -- Model dump before bytecode pipeline module 0xc0ffee::m { public fun test(): u64 { - { - let x: u64 = 1; - { - let x: u64 = Add(x, 1); - { - let y: u64 = 2; - { - let y: u64 = Add(y, 1); - Add(x, y) - } - } - } - } - } - spec fun $test(): u64 { - { - let x: u256 = 1; - { - let x: num = Add(x, 1); - { - let y: u256 = 2; - { - let y: num = Add(y, 1); - Add(x, y) - } - } - } - } + 5 } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/checking/visibility-checker/module_call_visibility_friend.exp b/third_party/move/move-compiler-v2/tests/checking/visibility-checker/module_call_visibility_friend.exp index 3fb95539ee5ed..f3424d16dd504 100644 --- a/third_party/move/move-compiler-v2/tests/checking/visibility-checker/module_call_visibility_friend.exp +++ b/third_party/move/move-compiler-v2/tests/checking/visibility-checker/module_call_visibility_friend.exp @@ -3,17 +3,11 @@ module 0x2::Y { friend fun f_friend() { Tuple() } - spec fun $f_friend() { - Tuple() - } } // end 0x2::Y module 0x2::X { public fun f_public() { Tuple() } - spec fun $f_public() { - Tuple() - } } // end 0x2::X module 0x2::M { use 0x2::X; // resolved as: 0x2::X @@ -54,40 +48,4 @@ module 0x2::M { public fun f_public_call_self_friend() { M::f_friend() } - spec fun $f_friend() { - Tuple() - } - spec fun $f_friend_call_friend() { - Y::$f_friend() - } - spec fun $f_friend_call_public() { - X::$f_public() - } - spec fun $f_friend_call_self_friend() { - M::$f_friend() - } - spec fun $f_friend_call_self_private() { - M::$f_private() - } - spec fun $f_friend_call_self_public() { - M::$f_public() - } - spec fun $f_private() { - Tuple() - } - spec fun $f_private_call_friend() { - Y::$f_friend() - } - spec fun $f_private_call_self_friend() { - M::$f_friend() - } - spec fun $f_public() { - Tuple() - } - spec fun $f_public_call_friend() { - Y::$f_friend() - } - spec fun $f_public_call_self_friend() { - M::$f_friend() - } } // end 0x2::M diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp index f88ff69ddd5b9..b9389c1b55e8d 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/const.exp @@ -3,67 +3,67 @@ Diagnostics: warning: Unused local variable `const_true`. Consider removing or prefixing with an underscore: `_const_true` ┌─ tests/file-format-generator/const.move:3:13 │ -3 │ let const_true = true; +3 │ let const_true = u(true); │ ^^^^^^^^^^ warning: Unused local variable `const_false`. Consider removing or prefixing with an underscore: `_const_false` ┌─ tests/file-format-generator/const.move:4:13 │ -4 │ let const_false = false; +4 │ let const_false = u(false); │ ^^^^^^^^^^^ warning: Unused local variable `hex_u8`. Consider removing or prefixing with an underscore: `_hex_u8` ┌─ tests/file-format-generator/const.move:5:13 │ -5 │ let hex_u8: u8 = 0x1; +5 │ let hex_u8: u8 = u(0x1); │ ^^^^^^ warning: Unused local variable `hex_u16`. Consider removing or prefixing with an underscore: `_hex_u16` ┌─ tests/file-format-generator/const.move:6:13 │ -6 │ let hex_u16: u16 = 0x1BAE; +6 │ let hex_u16: u16 = u(0x1BAE); │ ^^^^^^^ warning: Unused local variable `hex_u32`. Consider removing or prefixing with an underscore: `_hex_u32` ┌─ tests/file-format-generator/const.move:7:13 │ -7 │ let hex_u32: u32 = 0xDEAD80; +7 │ let hex_u32: u32 = u(0xDEAD80); │ ^^^^^^^ warning: Unused local variable `hex_u64`. Consider removing or prefixing with an underscore: `_hex_u64` ┌─ tests/file-format-generator/const.move:8:13 │ -8 │ let hex_u64: u64 = 0xCAFE; +8 │ let hex_u64: u64 = u(0xCAFE); │ ^^^^^^^ warning: Unused local variable `hex_u128`. Consider removing or prefixing with an underscore: `_hex_u128` ┌─ tests/file-format-generator/const.move:9:13 │ -9 │ let hex_u128: u128 = 0xDEADBEEF; +9 │ let hex_u128: u128 = u(0xDEADBEEF); │ ^^^^^^^^ warning: Unused local variable `hex_u256`. Consider removing or prefixing with an underscore: `_hex_u256` ┌─ tests/file-format-generator/const.move:10:13 │ -10 │ let hex_u256: u256 = 0x1123_456A_BCDE_F; +10 │ let hex_u256: u256 = u(0x1123_456A_BCDE_F); │ ^^^^^^^^ warning: Unused local variable `a`. Consider removing or prefixing with an underscore: `_a` ┌─ tests/file-format-generator/const.move:11:13 │ -11 │ let a = @0x42; +11 │ let a = u(@0x42); │ ^ warning: Unused local variable `vec`. Consider removing or prefixing with an underscore: `_vec` ┌─ tests/file-format-generator/const.move:12:13 │ -12 │ let vec = vector[1, 2, 3]; +12 │ let vec = u(vector[1, 2, 3]); │ ^^^ warning: Unused local variable `s`. Consider removing or prefixing with an underscore: `_s` ┌─ tests/file-format-generator/const.move:13:13 │ -13 │ let s = b"Hello!\n"; +13 │ let s = u(b"Hello!\n"); │ ^ @@ -86,30 +86,45 @@ L9: loc9: vector L10: loc10: vector B0: 0: LdTrue - 1: StLoc[0](loc0: bool) - 2: LdFalse - 3: StLoc[1](loc1: bool) - 4: LdU8(1) - 5: StLoc[2](loc2: u8) - 6: LdU16(7086) - 7: StLoc[3](loc3: u16) - 8: LdU32(14593408) - 9: StLoc[4](loc4: u32) - 10: LdU64(51966) - 11: StLoc[5](loc5: u64) - 12: LdU128(3735928559) - 13: StLoc[6](loc6: u128) - 14: LdU256(301490978409967) - 15: StLoc[7](loc7: u256) - 16: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66]) - 17: StLoc[8](loc8: address) - 18: LdU64(1) - 19: LdU64(2) - 20: LdU64(3) - 21: VecPack(1, 3) - 22: StLoc[9](loc9: vector) - 23: LdConst[1](Vector(U8): [7, 72, 101, 108, 108, 111, 33, 10]) - 24: StLoc[10](loc10: vector) - 25: Ret + 1: Call u(bool): bool + 2: StLoc[0](loc0: bool) + 3: LdFalse + 4: Call u(bool): bool + 5: StLoc[1](loc1: bool) + 6: LdU8(1) + 7: Call u(u8): u8 + 8: StLoc[2](loc2: u8) + 9: LdU16(7086) + 10: Call u(u16): u16 + 11: StLoc[3](loc3: u16) + 12: LdU32(14593408) + 13: Call u(u32): u32 + 14: StLoc[4](loc4: u32) + 15: LdU64(51966) + 16: Call u(u64): u64 + 17: StLoc[5](loc5: u64) + 18: LdU128(3735928559) + 19: Call u(u128): u128 + 20: StLoc[6](loc6: u128) + 21: LdU256(301490978409967) + 22: Call u(u256): u256 + 23: StLoc[7](loc7: u256) + 24: LdConst[0](Address: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66]) + 25: Call u
(address): address + 26: StLoc[8](loc8: address) + 27: LdConst[1](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 28: Call u>(vector): vector + 29: StLoc[9](loc9: vector) + 30: LdConst[2](Vector(U8): [7, 72, 101, 108, 108, 111, 33, 10]) + 31: Call u>(vector): vector + 32: StLoc[10](loc10: vector) + 33: Ret +} +u(Arg0: Ty0): Ty0 /* def_idx: 1 */ { +B0: + 0: MoveLoc[0](Arg0: Ty0) + 1: StLoc[1](loc0: Ty0) + 2: MoveLoc[1](loc0: Ty0) + 3: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/const.move b/third_party/move/move-compiler-v2/tests/file-format-generator/const.move index bcf33b7fb78f7..5d0592cdb3e5c 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/const.move +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/const.move @@ -1,15 +1,17 @@ module 0x42::constant { fun test_constans() { - let const_true = true; - let const_false = false; - let hex_u8: u8 = 0x1; - let hex_u16: u16 = 0x1BAE; - let hex_u32: u32 = 0xDEAD80; - let hex_u64: u64 = 0xCAFE; - let hex_u128: u128 = 0xDEADBEEF; - let hex_u256: u256 = 0x1123_456A_BCDE_F; - let a = @0x42; - let vec = vector[1, 2, 3]; - let s = b"Hello!\n"; + let const_true = u(true); + let const_false = u(false); + let hex_u8: u8 = u(0x1); + let hex_u16: u16 = u(0x1BAE); + let hex_u32: u32 = u(0xDEAD80); + let hex_u64: u64 = u(0xCAFE); + let hex_u128: u128 = u(0xDEADBEEF); + let hex_u256: u256 = u(0x1123_456A_BCDE_F); + let a = u(@0x42); + let vec = u(vector[1, 2, 3]); + let s = u(b"Hello!\n"); } + + fun u(x: T): T { x } } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/has_script.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/has_script.exp index 57b8b93cd12ce..614f9200d1c9b 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/has_script.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/has_script.exp @@ -6,16 +6,14 @@ script { main() /* def_idx: 0 */ { B0: - 0: LdU64(1) - 1: LdU64(1) - 2: Eq - 3: BrFalse(5) + 0: LdTrue + 1: BrFalse(3) B1: - 4: Branch(7) + 2: Branch(5) B2: - 5: LdU64(1) - 6: Abort + 3: LdU64(1) + 4: Abort B3: - 7: Ret + 5: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp index b97a5dfd70042..0e8b6fde03bca 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/vector.exp @@ -69,75 +69,59 @@ B8: } create(): vector /* def_idx: 1 */ { B0: - 0: LdU64(1) - 1: LdU64(2) - 2: LdU64(3) - 3: VecPack(5, 3) - 4: Ret + 0: LdConst[0](Vector(U64): [3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0]) + 1: Ret } test_fold() /* def_idx: 2 */ { -L0: loc0: vector +L0: loc0: u64 L1: loc1: vector -L2: loc2: vector +L2: loc2: u64 L3: loc3: u64 L4: loc4: u64 -L5: loc5: vector +L5: loc5: u64 L6: loc6: u64 -L7: loc7: u64 -L8: loc8: u64 -L9: loc9: u64 -L10: loc10: u64 B0: - 0: LdU64(1) - 1: VecPack(5, 1) - 2: StLoc[0](loc0: vector) - 3: MoveLoc[0](loc0: vector) - 4: StLoc[1](loc1: vector) - 5: LdU64(0) - 6: MoveLoc[1](loc1: vector) - 7: StLoc[2](loc2: vector) - 8: StLoc[3](loc3: u64) - 9: MoveLoc[3](loc3: u64) - 10: StLoc[4](loc4: u64) - 11: MoveLoc[2](loc2: vector) - 12: StLoc[5](loc5: vector) - 13: MutBorrowLoc[5](loc5: vector) - 14: Call 1vector::reverse(&mut vector) + 0: LdU64(0) + 1: StLoc[0](loc0: u64) + 2: LdConst[1](Vector(U64): [1, 1, 0, 0, 0, 0, 0, 0, 0]) + 3: StLoc[1](loc1: vector) + 4: MutBorrowLoc[1](loc1: vector) + 5: Call 1vector::reverse(&mut vector) B1: - 15: ImmBorrowLoc[5](loc5: vector) - 16: Call 1vector::is_empty(&vector): bool - 17: Not - 18: BrFalse(27) + 6: ImmBorrowLoc[1](loc1: vector) + 7: Call 1vector::is_empty(&vector): bool + 8: Not + 9: BrFalse(18) B2: - 19: MutBorrowLoc[5](loc5: vector) - 20: VecPopBack(5) - 21: StLoc[6](loc6: u64) - 22: MoveLoc[6](loc6: u64) - 23: StLoc[7](loc7: u64) - 24: LdU64(0) - 25: StLoc[4](loc4: u64) - 26: Branch(28) + 10: MutBorrowLoc[1](loc1: vector) + 11: VecPopBack(5) + 12: StLoc[2](loc2: u64) + 13: MoveLoc[2](loc2: u64) + 14: StLoc[3](loc3: u64) + 15: LdU64(0) + 16: StLoc[0](loc0: u64) + 17: Branch(19) B3: - 27: Branch(29) + 18: Branch(20) B4: - 28: Branch(15) + 19: Branch(6) B5: - 29: MoveLoc[4](loc4: u64) - 30: StLoc[8](loc8: u64) - 31: MoveLoc[8](loc8: u64) - 32: StLoc[9](loc9: u64) - 33: LdU64(0) - 34: StLoc[10](loc10: u64) - 35: MoveLoc[9](loc9: u64) - 36: MoveLoc[10](loc10: u64) - 37: Eq - 38: BrFalse(40) + 20: MoveLoc[0](loc0: u64) + 21: StLoc[4](loc4: u64) + 22: MoveLoc[4](loc4: u64) + 23: StLoc[5](loc5: u64) + 24: LdU64(0) + 25: StLoc[6](loc6: u64) + 26: MoveLoc[5](loc5: u64) + 27: MoveLoc[6](loc6: u64) + 28: Eq + 29: BrFalse(31) B6: - 39: Branch(42) + 30: Branch(33) B7: - 40: LdU64(0) - 41: Abort + 31: LdU64(0) + 32: Abort B8: - 42: Ret + 33: Ret } } diff --git a/third_party/move/move-compiler-v2/tests/folding/constant_values.exp b/third_party/move/move-compiler-v2/tests/folding/constant_values.exp index c24e8d033ef8a..31646be86d937 100644 --- a/third_party/move/move-compiler-v2/tests/folding/constant_values.exp +++ b/third_party/move/move-compiler-v2/tests/folding/constant_values.exp @@ -18,22 +18,4 @@ module 0x8675309::M { private fun int8(): u8 { 1 } - spec fun $int128(): u128 { - 4 - } - spec fun $int16(): u16 { - 123 - } - spec fun $int256(): u256 { - 4 - } - spec fun $int32(): u32 { - Add(84, 53) - } - spec fun $int64(): u64 { - Add(2, 3) - } - spec fun $int8(): u8 { - 1 - } } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp b/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp index 4283ac757c503..875ed6741eeb9 100644 --- a/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp +++ b/third_party/move/move-compiler-v2/tests/folding/non_constant_empty_vec.exp @@ -21,22 +21,4 @@ module 0x42::M { public fun empty_struct_vec_vec(): vector> { Vector>() } - spec fun $empty_generic_vec(): vector<#0> { - Vector<#0>() - } - spec fun $empty_generic_vec_vec(): vector> { - Vector>() - } - spec fun $empty_signer_vec(): vector { - Vector() - } - spec fun $empty_signer_vec_vec(): vector> { - Vector>() - } - spec fun $empty_struct_vec(): vector { - Vector() - } - spec fun $empty_struct_vec_vec(): vector> { - Vector>() - } } // end 0x42::M diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.exp index 38de981d922f6..560bf63d49ec9 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/basic.exp @@ -15,21 +15,6 @@ module 0xcafe::m { x }, x)) } - spec fun $map(x: u64,f: |u64|u64): u64 { - (f)(x) - } - spec fun $no_name_clash(x: u64,c: u64): u64 { - m::$map(x, |y: num| Add(y, c)) - } - spec fun $with_name_clash1(x: u64,c: u64): u64 { - m::$map(x, |x: num| Add(x, c)) - } - spec fun $with_name_clash2(x: u64,c: u64): u64 { - m::$map(x, |x: num| Add({ - let x: num = Add(c, 1); - x - }, x)) - } } // end 0xcafe::m @@ -59,19 +44,4 @@ module 0xcafe::m { x }, x) } - spec fun $map(x: u64,f: |u64|u64): u64 { - (f)(x) - } - spec fun $no_name_clash(x: u64,c: u64): u64 { - m::$map(x, |y: num| Add(y, c)) - } - spec fun $with_name_clash1(x: u64,c: u64): u64 { - m::$map(x, |x: num| Add(x, c)) - } - spec fun $with_name_clash2(x: u64,c: u64): u64 { - m::$map(x, |x: num| Add({ - let x: num = Add(c, 1); - x - }, x)) - } } // end 0xcafe::m diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.exp index 1f67a4cf35842..b3fe694d0cb5f 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/modify.exp @@ -41,35 +41,6 @@ module 0xcafe::m { private fun map(x: u64,f: |u64|u64): u64 { (f)(x) } - spec fun $assigns_local(x: u64,c: u64): u64; - spec fun $assigns_param(x: u64,c: u64): u64; - spec fun $borrows_local(x: u64): u64 { - { - let z: u256 = 1; - m::$map(x, |y: num| { - let r: u256 = z; - Add(y, r) - }) - } - } - spec fun $borrows_param(x: u64,c: u64): u64 { - m::$map(x, |y: num| { - let r: u64 = c; - Add(y, r) - }) - } - spec fun $immutable_borrow_ok(x: u64): u64 { - { - let z: u256 = 1; - m::$map(x, |y: num| { - let r: u256 = z; - Add(y, r) - }) - } - } - spec fun $map(x: u64,f: |u64|u64): u64 { - (f)(x) - } } // end 0xcafe::m diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.exp index bd11df0f60632..9ddfd3b736119 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/nested.exp @@ -9,15 +9,6 @@ module 0xcafe::m { private fun nested(x: u64,c: u64): u64 { m::map1(x, |y: u64| Cast(m::map2(Cast(Sub(y, c)), |y: u8| Add(y, Cast(c))))) } - spec fun $map1(x: u64,f: |u64|u64): u64 { - (f)(x) - } - spec fun $map2(x: u8,f: |u8|u8): u8 { - (f)(x) - } - spec fun $nested(x: u64,c: u64): u64 { - m::$map1(x, |y: num| Cast(m::$map2(Cast(Sub(y, c)), |y: num| Add(y, Cast(c))))) - } } // end 0xcafe::m @@ -38,13 +29,4 @@ module 0xcafe::m { private fun nested$lambda$2(c: u64,y: u64): u64 { Cast(m::map2(Cast(Sub(y, c)), closure m::nested$lambda$1(c))) } - spec fun $map1(x: u64,f: |u64|u64): u64 { - (f)(x) - } - spec fun $map2(x: u8,f: |u8|u8): u8 { - (f)(x) - } - spec fun $nested(x: u64,c: u64): u64 { - m::$map1(x, |y: num| Cast(m::$map2(Cast(Sub(y, c)), |y: num| Add(y, Cast(c))))) - } } // end 0xcafe::m diff --git a/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.exp b/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.exp index 736b844b35412..ef4ec3980fdd8 100644 --- a/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.exp +++ b/third_party/move/move-compiler-v2/tests/lambda-lifting/pattern.exp @@ -12,15 +12,6 @@ module 0xcafe::m { Add(x, y) }) } - spec fun $consume(s: m::S<#0>,x: #0,f: |(m::S<#0>, #0)|#0): #0 { - (f)(s, x) - } - spec fun $pattern(s: m::S,x: u64): u64 { - m::$consume(s, x, |(m::S{ x: x: num }, _y: u64): (m::S, u64)| { - let y: num = x; - Add(x, y) - }) - } } // end 0xcafe::m @@ -44,13 +35,4 @@ module 0xcafe::m { } } } - spec fun $consume(s: m::S<#0>,x: #0,f: |(m::S<#0>, #0)|#0): #0 { - (f)(s, x) - } - spec fun $pattern(s: m::S,x: u64): u64 { - m::$consume(s, x, |(m::S{ x: x: num }, _y: u64): (m::S, u64)| { - let y: num = x; - Add(x, y) - }) - } } // end 0xcafe::m diff --git a/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp b/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp index feca359d3c8b3..9af0dd7a91309 100644 --- a/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp +++ b/third_party/move/move-compiler-v2/tests/live-var/mut_inline.exp @@ -5,122 +5,116 @@ fun m::foo(): u64 { var $t0: u64 var $t1: vector var $t2: vector - var $t3: u64 - var $t4: u64 + var $t3: &mut vector + var $t4: &mut vector var $t5: u64 var $t6: &mut vector - var $t7: &mut vector + var $t7: u64 var $t8: u64 - var $t9: &mut vector + var $t9: u64 var $t10: u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: &vector - var $t15: bool - var $t16: bool - var $t17: bool - var $t18: &u64 - var $t19: &u64 - var $t20: &vector + var $t11: &vector + var $t12: bool + var $t13: bool + var $t14: bool + var $t15: &u64 + var $t16: &u64 + var $t17: &vector + var $t18: u64 + var $t19: u64 + var $t20: u64 var $t21: u64 var $t22: u64 var $t23: u64 var $t24: u64 - var $t25: u64 - var $t26: u64 - var $t27: u64 - var $t28: bool - var $t29: bool - var $t30: &u64 - var $t31: &u64 - var $t32: &vector + var $t25: bool + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: u64 var $t33: u64 var $t34: u64 var $t35: u64 - var $t36: u64 - var $t37: u64 + var $t36: &u64 + var $t37: &vector var $t38: u64 - var $t39: &u64 - var $t40: &vector - var $t41: u64 - 0: $t3 := 1 - 1: $t4 := 2 - 2: $t5 := 3 - 3: $t2 := vector($t3, $t4, $t5) - 4: $t1 := infer($t2) - 5: $t7 := borrow_local($t1) - 6: $t6 := infer($t7) - 7: $t9 := infer($t6) - 8: $t11 := 0 - 9: $t10 := infer($t11) - 10: $t14 := freeze_ref($t9) - 11: $t13 := vector::length($t14) - 12: $t12 := infer($t13) - 13: label L0 - 14: $t15 := <($t10, $t12) - 15: if ($t15) goto 16 else goto 34 - 16: label L2 - 17: $t20 := freeze_ref($t9) - 18: $t19 := vector::borrow($t20, $t10) - 19: $t18 := infer($t19) - 20: $t21 := read_ref($t18) - 21: $t22 := 1 - 22: $t17 := >($t21, $t22) - 23: $t16 := !($t17) - 24: if ($t16) goto 25 else goto 28 - 25: label L5 - 26: goto 38 - 27: goto 29 - 28: label L6 - 29: label L7 - 30: $t24 := 1 - 31: $t23 := +($t10, $t24) - 32: $t10 := infer($t23) - 33: goto 36 - 34: label L3 - 35: goto 38 - 36: label L4 - 37: goto 13 - 38: label L1 - 39: $t25 := infer($t10) - 40: $t27 := 1 - 41: $t26 := +($t10, $t27) - 42: $t10 := infer($t26) - 43: label L8 - 44: $t28 := <($t10, $t12) - 45: if ($t28) goto 46 else goto 66 - 46: label L10 - 47: $t32 := freeze_ref($t9) - 48: $t31 := vector::borrow($t32, $t10) - 49: $t30 := infer($t31) - 50: $t33 := read_ref($t30) - 51: $t34 := 1 - 52: $t29 := >($t33, $t34) - 53: if ($t29) goto 54 else goto 60 - 54: label L13 - 55: vector::swap($t9, $t25, $t10) - 56: $t36 := 1 - 57: $t35 := +($t25, $t36) - 58: $t25 := infer($t35) - 59: goto 61 - 60: label L14 - 61: label L15 - 62: $t38 := 1 - 63: $t37 := +($t10, $t38) - 64: $t10 := infer($t37) - 65: goto 68 - 66: label L11 - 67: goto 70 - 68: label L12 - 69: goto 43 - 70: label L9 - 71: $t8 := infer($t25) - 72: $t40 := freeze_ref($t6) - 73: $t41 := 0 - 74: $t39 := vector::borrow($t40, $t41) - 75: $t0 := read_ref($t39) - 76: return $t0 + 0: $t2 := ["1", "2", "3"] + 1: $t1 := infer($t2) + 2: $t4 := borrow_local($t1) + 3: $t3 := infer($t4) + 4: $t6 := infer($t3) + 5: $t8 := 0 + 6: $t7 := infer($t8) + 7: $t11 := freeze_ref($t6) + 8: $t10 := vector::length($t11) + 9: $t9 := infer($t10) + 10: label L0 + 11: $t12 := <($t7, $t9) + 12: if ($t12) goto 13 else goto 31 + 13: label L2 + 14: $t17 := freeze_ref($t6) + 15: $t16 := vector::borrow($t17, $t7) + 16: $t15 := infer($t16) + 17: $t18 := read_ref($t15) + 18: $t19 := 1 + 19: $t14 := >($t18, $t19) + 20: $t13 := !($t14) + 21: if ($t13) goto 22 else goto 25 + 22: label L5 + 23: goto 35 + 24: goto 26 + 25: label L6 + 26: label L7 + 27: $t21 := 1 + 28: $t20 := +($t7, $t21) + 29: $t7 := infer($t20) + 30: goto 33 + 31: label L3 + 32: goto 35 + 33: label L4 + 34: goto 10 + 35: label L1 + 36: $t22 := infer($t7) + 37: $t24 := 1 + 38: $t23 := +($t7, $t24) + 39: $t7 := infer($t23) + 40: label L8 + 41: $t25 := <($t7, $t9) + 42: if ($t25) goto 43 else goto 63 + 43: label L10 + 44: $t29 := freeze_ref($t6) + 45: $t28 := vector::borrow($t29, $t7) + 46: $t27 := infer($t28) + 47: $t30 := read_ref($t27) + 48: $t31 := 1 + 49: $t26 := >($t30, $t31) + 50: if ($t26) goto 51 else goto 57 + 51: label L13 + 52: vector::swap($t6, $t22, $t7) + 53: $t33 := 1 + 54: $t32 := +($t22, $t33) + 55: $t22 := infer($t32) + 56: goto 58 + 57: label L14 + 58: label L15 + 59: $t35 := 1 + 60: $t34 := +($t7, $t35) + 61: $t7 := infer($t34) + 62: goto 65 + 63: label L11 + 64: goto 67 + 65: label L12 + 66: goto 40 + 67: label L9 + 68: $t5 := infer($t22) + 69: $t37 := freeze_ref($t3) + 70: $t38 := 0 + 71: $t36 := vector::borrow($t37, $t38) + 72: $t0 := read_ref($t36) + 73: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -130,197 +124,188 @@ fun m::foo(): u64 { var $t0: u64 var $t1: vector var $t2: vector - var $t3: u64 - var $t4: u64 + var $t3: &mut vector + var $t4: &mut vector var $t5: u64 var $t6: &mut vector - var $t7: &mut vector + var $t7: u64 var $t8: u64 - var $t9: &mut vector + var $t9: u64 var $t10: u64 - var $t11: u64 - var $t12: u64 - var $t13: u64 - var $t14: &vector - var $t15: bool - var $t16: bool - var $t17: bool - var $t18: &u64 - var $t19: &u64 - var $t20: &vector + var $t11: &vector + var $t12: bool + var $t13: bool + var $t14: bool + var $t15: &u64 + var $t16: &u64 + var $t17: &vector + var $t18: u64 + var $t19: u64 + var $t20: u64 var $t21: u64 var $t22: u64 var $t23: u64 var $t24: u64 - var $t25: u64 - var $t26: u64 - var $t27: u64 - var $t28: bool - var $t29: bool - var $t30: &u64 - var $t31: &u64 - var $t32: &vector + var $t25: bool + var $t26: bool + var $t27: &u64 + var $t28: &u64 + var $t29: &vector + var $t30: u64 + var $t31: u64 + var $t32: u64 var $t33: u64 var $t34: u64 var $t35: u64 - var $t36: u64 - var $t37: u64 + var $t36: &u64 + var $t37: &vector var $t38: u64 - var $t39: &u64 - var $t40: &vector - var $t41: u64 # live vars: - 0: $t3 := 1 - # live vars: $t3 - 1: $t4 := 2 - # live vars: $t3, $t4 - 2: $t5 := 3 - # live vars: $t3, $t4, $t5 - 3: $t2 := vector($t3, $t4, $t5) + 0: $t2 := ["1", "2", "3"] # live vars: $t2 - 4: $t1 := infer($t2) + 1: $t1 := infer($t2) # live vars: $t1 - 5: $t7 := borrow_local($t1) - # live vars: $t7 - 6: $t6 := infer($t7) - # live vars: $t6 - 7: $t9 := infer($t6) - # live vars: $t6, $t9 - 8: $t11 := 0 - # live vars: $t6, $t9, $t11 - 9: $t10 := infer($t11) - # live vars: $t6, $t9, $t10 - 10: $t14 := freeze_ref($t9) - # live vars: $t6, $t9, $t10, $t14 - 11: $t13 := vector::length($t14) - # live vars: $t6, $t9, $t10, $t13 - 12: $t12 := infer($t13) - # live vars: $t6, $t9, $t10, $t12 - 13: label L0 - # live vars: $t6, $t9, $t10, $t12 - 14: $t15 := <($t10, $t12) - # live vars: $t6, $t9, $t10, $t12, $t15 - 15: if ($t15) goto 16 else goto 34 - # live vars: $t6, $t9, $t10, $t12 - 16: label L2 - # live vars: $t6, $t9, $t10, $t12 - 17: $t20 := freeze_ref($t9) - # live vars: $t6, $t9, $t10, $t12, $t20 - 18: $t19 := vector::borrow($t20, $t10) - # live vars: $t6, $t9, $t10, $t12, $t19 - 19: $t18 := infer($t19) - # live vars: $t6, $t9, $t10, $t12, $t18 - 20: $t21 := read_ref($t18) - # live vars: $t6, $t9, $t10, $t12, $t21 - 21: $t22 := 1 - # live vars: $t6, $t9, $t10, $t12, $t21, $t22 - 22: $t17 := >($t21, $t22) - # live vars: $t6, $t9, $t10, $t12, $t17 - 23: $t16 := !($t17) - # live vars: $t6, $t9, $t10, $t12, $t16 - 24: if ($t16) goto 25 else goto 28 - # live vars: $t6, $t9, $t10, $t12 - 25: label L5 - # live vars: $t6, $t9, $t10, $t12 - 26: goto 38 - # live vars: $t6, $t9, $t10, $t12 - 27: goto 29 - # live vars: $t6, $t9, $t10, $t12 - 28: label L6 - # live vars: $t6, $t9, $t10, $t12 - 29: label L7 - # live vars: $t6, $t9, $t10, $t12 - 30: $t24 := 1 - # live vars: $t6, $t9, $t10, $t12, $t24 - 31: $t23 := +($t10, $t24) - # live vars: $t6, $t9, $t12, $t23 - 32: $t10 := infer($t23) - # live vars: $t6, $t9, $t10, $t12 - 33: goto 36 - # live vars: $t6, $t9, $t10, $t12 - 34: label L3 - # live vars: $t6, $t9, $t10, $t12 - 35: goto 38 - # live vars: $t6, $t9, $t10, $t12 - 36: label L4 - # live vars: $t6, $t9, $t10, $t12 - 37: goto 13 - # live vars: $t6, $t9, $t10, $t12 - 38: label L1 - # live vars: $t6, $t9, $t10, $t12 - 39: $t25 := infer($t10) - # live vars: $t6, $t9, $t10, $t12, $t25 - 40: $t27 := 1 - # live vars: $t6, $t9, $t10, $t12, $t25, $t27 - 41: $t26 := +($t10, $t27) - # live vars: $t6, $t9, $t12, $t25, $t26 - 42: $t10 := infer($t26) - # live vars: $t6, $t9, $t10, $t12, $t25 - 43: label L8 - # live vars: $t6, $t9, $t10, $t12, $t25 - 44: $t28 := <($t10, $t12) - # live vars: $t6, $t9, $t10, $t12, $t25, $t28 - 45: if ($t28) goto 46 else goto 66 - # live vars: $t6, $t9, $t10, $t12, $t25 - 46: label L10 - # live vars: $t6, $t9, $t10, $t12, $t25 - 47: $t32 := freeze_ref($t9) - # live vars: $t6, $t9, $t10, $t12, $t25, $t32 - 48: $t31 := vector::borrow($t32, $t10) - # live vars: $t6, $t9, $t10, $t12, $t25, $t31 - 49: $t30 := infer($t31) - # live vars: $t6, $t9, $t10, $t12, $t25, $t30 - 50: $t33 := read_ref($t30) - # live vars: $t6, $t9, $t10, $t12, $t25, $t33 - 51: $t34 := 1 - # live vars: $t6, $t9, $t10, $t12, $t25, $t33, $t34 - 52: $t29 := >($t33, $t34) - # live vars: $t6, $t9, $t10, $t12, $t25, $t29 - 53: if ($t29) goto 54 else goto 60 - # live vars: $t6, $t9, $t10, $t12, $t25 - 54: label L13 - # live vars: $t6, $t9, $t10, $t12, $t25 - 55: vector::swap($t9, $t25, $t10) - # live vars: $t6, $t9, $t10, $t12, $t25 - 56: $t36 := 1 - # live vars: $t6, $t9, $t10, $t12, $t25, $t36 - 57: $t35 := +($t25, $t36) - # live vars: $t6, $t9, $t10, $t12, $t35 - 58: $t25 := infer($t35) - # live vars: $t6, $t9, $t10, $t12, $t25 - 59: goto 61 - # live vars: $t6, $t9, $t10, $t12, $t25 - 60: label L14 - # live vars: $t6, $t9, $t10, $t12, $t25 - 61: label L15 - # live vars: $t6, $t9, $t10, $t12, $t25 - 62: $t38 := 1 - # live vars: $t6, $t9, $t10, $t12, $t25, $t38 - 63: $t37 := +($t10, $t38) - # live vars: $t6, $t9, $t12, $t25, $t37 - 64: $t10 := infer($t37) - # live vars: $t6, $t9, $t10, $t12, $t25 - 65: goto 68 - # live vars: $t6, $t9, $t10, $t12, $t25 - 66: label L11 - # live vars: $t6, $t25 - 67: goto 70 - # live vars: $t6, $t9, $t10, $t12, $t25 - 68: label L12 - # live vars: $t6, $t9, $t10, $t12, $t25 - 69: goto 43 - # live vars: $t6, $t25 - 70: label L9 - # live vars: $t6, $t25 - 71: $t8 := infer($t25) - # live vars: $t6 - 72: $t40 := freeze_ref($t6) - # live vars: $t40 - 73: $t41 := 0 - # live vars: $t40, $t41 - 74: $t39 := vector::borrow($t40, $t41) - # live vars: $t39 - 75: $t0 := read_ref($t39) + 2: $t4 := borrow_local($t1) + # live vars: $t4 + 3: $t3 := infer($t4) + # live vars: $t3 + 4: $t6 := infer($t3) + # live vars: $t3, $t6 + 5: $t8 := 0 + # live vars: $t3, $t6, $t8 + 6: $t7 := infer($t8) + # live vars: $t3, $t6, $t7 + 7: $t11 := freeze_ref($t6) + # live vars: $t3, $t6, $t7, $t11 + 8: $t10 := vector::length($t11) + # live vars: $t3, $t6, $t7, $t10 + 9: $t9 := infer($t10) + # live vars: $t3, $t6, $t7, $t9 + 10: label L0 + # live vars: $t3, $t6, $t7, $t9 + 11: $t12 := <($t7, $t9) + # live vars: $t3, $t6, $t7, $t9, $t12 + 12: if ($t12) goto 13 else goto 31 + # live vars: $t3, $t6, $t7, $t9 + 13: label L2 + # live vars: $t3, $t6, $t7, $t9 + 14: $t17 := freeze_ref($t6) + # live vars: $t3, $t6, $t7, $t9, $t17 + 15: $t16 := vector::borrow($t17, $t7) + # live vars: $t3, $t6, $t7, $t9, $t16 + 16: $t15 := infer($t16) + # live vars: $t3, $t6, $t7, $t9, $t15 + 17: $t18 := read_ref($t15) + # live vars: $t3, $t6, $t7, $t9, $t18 + 18: $t19 := 1 + # live vars: $t3, $t6, $t7, $t9, $t18, $t19 + 19: $t14 := >($t18, $t19) + # live vars: $t3, $t6, $t7, $t9, $t14 + 20: $t13 := !($t14) + # live vars: $t3, $t6, $t7, $t9, $t13 + 21: if ($t13) goto 22 else goto 25 + # live vars: $t3, $t6, $t7, $t9 + 22: label L5 + # live vars: $t3, $t6, $t7, $t9 + 23: goto 35 + # live vars: $t3, $t6, $t7, $t9 + 24: goto 26 + # live vars: $t3, $t6, $t7, $t9 + 25: label L6 + # live vars: $t3, $t6, $t7, $t9 + 26: label L7 + # live vars: $t3, $t6, $t7, $t9 + 27: $t21 := 1 + # live vars: $t3, $t6, $t7, $t9, $t21 + 28: $t20 := +($t7, $t21) + # live vars: $t3, $t6, $t9, $t20 + 29: $t7 := infer($t20) + # live vars: $t3, $t6, $t7, $t9 + 30: goto 33 + # live vars: $t3, $t6, $t7, $t9 + 31: label L3 + # live vars: $t3, $t6, $t7, $t9 + 32: goto 35 + # live vars: $t3, $t6, $t7, $t9 + 33: label L4 + # live vars: $t3, $t6, $t7, $t9 + 34: goto 10 + # live vars: $t3, $t6, $t7, $t9 + 35: label L1 + # live vars: $t3, $t6, $t7, $t9 + 36: $t22 := infer($t7) + # live vars: $t3, $t6, $t7, $t9, $t22 + 37: $t24 := 1 + # live vars: $t3, $t6, $t7, $t9, $t22, $t24 + 38: $t23 := +($t7, $t24) + # live vars: $t3, $t6, $t9, $t22, $t23 + 39: $t7 := infer($t23) + # live vars: $t3, $t6, $t7, $t9, $t22 + 40: label L8 + # live vars: $t3, $t6, $t7, $t9, $t22 + 41: $t25 := <($t7, $t9) + # live vars: $t3, $t6, $t7, $t9, $t22, $t25 + 42: if ($t25) goto 43 else goto 63 + # live vars: $t3, $t6, $t7, $t9, $t22 + 43: label L10 + # live vars: $t3, $t6, $t7, $t9, $t22 + 44: $t29 := freeze_ref($t6) + # live vars: $t3, $t6, $t7, $t9, $t22, $t29 + 45: $t28 := vector::borrow($t29, $t7) + # live vars: $t3, $t6, $t7, $t9, $t22, $t28 + 46: $t27 := infer($t28) + # live vars: $t3, $t6, $t7, $t9, $t22, $t27 + 47: $t30 := read_ref($t27) + # live vars: $t3, $t6, $t7, $t9, $t22, $t30 + 48: $t31 := 1 + # live vars: $t3, $t6, $t7, $t9, $t22, $t30, $t31 + 49: $t26 := >($t30, $t31) + # live vars: $t3, $t6, $t7, $t9, $t22, $t26 + 50: if ($t26) goto 51 else goto 57 + # live vars: $t3, $t6, $t7, $t9, $t22 + 51: label L13 + # live vars: $t3, $t6, $t7, $t9, $t22 + 52: vector::swap($t6, $t22, $t7) + # live vars: $t3, $t6, $t7, $t9, $t22 + 53: $t33 := 1 + # live vars: $t3, $t6, $t7, $t9, $t22, $t33 + 54: $t32 := +($t22, $t33) + # live vars: $t3, $t6, $t7, $t9, $t32 + 55: $t22 := infer($t32) + # live vars: $t3, $t6, $t7, $t9, $t22 + 56: goto 58 + # live vars: $t3, $t6, $t7, $t9, $t22 + 57: label L14 + # live vars: $t3, $t6, $t7, $t9, $t22 + 58: label L15 + # live vars: $t3, $t6, $t7, $t9, $t22 + 59: $t35 := 1 + # live vars: $t3, $t6, $t7, $t9, $t22, $t35 + 60: $t34 := +($t7, $t35) + # live vars: $t3, $t6, $t9, $t22, $t34 + 61: $t7 := infer($t34) + # live vars: $t3, $t6, $t7, $t9, $t22 + 62: goto 65 + # live vars: $t3, $t6, $t7, $t9, $t22 + 63: label L11 + # live vars: $t3, $t22 + 64: goto 67 + # live vars: $t3, $t6, $t7, $t9, $t22 + 65: label L12 + # live vars: $t3, $t6, $t7, $t9, $t22 + 66: goto 40 + # live vars: $t3, $t22 + 67: label L9 + # live vars: $t3, $t22 + 68: $t5 := infer($t22) + # live vars: $t3 + 69: $t37 := freeze_ref($t3) + # live vars: $t37 + 70: $t38 := 0 + # live vars: $t37, $t38 + 71: $t36 := vector::borrow($t37, $t38) + # live vars: $t36 + 72: $t0 := read_ref($t36) # live vars: $t0 - 76: return $t0 + 73: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp index 571e6bb7e66b1..6c96a94dd70d5 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified.exp @@ -9,15 +9,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - Add(x, y) - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified2.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified2.exp index 1e6e699ad9a14..d377138ca51b4 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified2.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified2.exp @@ -12,18 +12,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - { - let _z: u256 = x; - y - } - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp index 10d5c77f2e428..f8a87bfb50170 100644 --- a/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp +++ b/third_party/move/move-compiler-v2/tests/no-simplifier/moved_var_not_simplified3.exp @@ -12,16 +12,4 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - { - let _: u256 = x; - y - } - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_borrowed_local_invalid.exp b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_borrowed_local_invalid.exp index 5e324db087c18..cbecc2b6ba22e 100644 --- a/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_borrowed_local_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/reference-safety/v1-tests/return_borrowed_local_invalid.exp @@ -13,7 +13,7 @@ error: cannot return a reference derived from local `v1` since it is not a param 26 │ │ id(&s4.f)) │ ╰──────────────────^ returned here -error: cannot return a reference derived from local `v2` since it is not a parameter +error: cannot return a reference derived from value since it is not a parameter ┌─ tests/reference-safety/v1-tests/return_borrowed_local_invalid.move:19:9 │ 19 │ ╭ (&mut v1, @@ -42,7 +42,7 @@ error: cannot return a reference derived from local `v3` since it is not a param 26 │ │ id(&s4.f)) │ ╰──────────────────^ returned here -error: cannot return a reference derived from local `v4` since it is not a parameter +error: cannot return a reference derived from value since it is not a parameter ┌─ tests/reference-safety/v1-tests/return_borrowed_local_invalid.move:19:9 │ 19 │ ╭ (&mut v1, diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp index 1678ba1ea06f4..b7d690e43dc92 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/always_false_branch.exp @@ -12,5 +12,4 @@ module 0xc0ffee::m { }; 0 } - spec fun $test(): u64; } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/assign_unpack_references.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/assign_unpack_references.exp index bf076b20eb029..602e1a5fbeb30 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/assign_unpack_references.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/assign_unpack_references.exp @@ -55,9 +55,6 @@ module 0x8675309::M { } } } - spec fun $t0(); - spec fun $t1(); - spec fun $t2(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp index 540be6e08074b..580551a3a0f29 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/binary_add.exp @@ -62,5 +62,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(x: u64,r: M::R); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp index 38b60b351a17b..dacb5b0be3cf7 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/bind_with_type_annot.exp @@ -35,5 +35,4 @@ module 0x8675309::M { Tuple() } } - spec fun $t0(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp index fdc405e831258..62bfa312532fe 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/constant_all_valid_types.exp @@ -65,31 +65,9 @@ module 0x42::M { private fun t7(): vector { [97, 98, 99, 100] } - spec fun $t1(): u8 { - 0 - } - spec fun $t2(): u64 { - 0 - } - spec fun $t3(): u128 { - 0 - } - spec fun $t4(): bool { - false - } - spec fun $t5(): address { - 0x0 - } - spec fun $t6(): vector { - [1, 35] - } - spec fun $t7(): vector { - [97, 98, 99, 100] - } } // end 0x42::M module _0 { private fun t() { Tuple() } - spec fun $t(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp index 7264326e6c4ab..e5132322bc003 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/double_nesting.exp @@ -1,13 +1,7 @@ // -- Model dump before bytecode pipeline module 0x42::mathtest2 { - spec fun $fun2(a: u64,b: u64,c: u64): u64 { - Cast(Add(Add(Mul(7, Cast(a)), Mul(11, Cast(b))), Mul(13, Cast(c)))) - } } // end 0x42::mathtest2 module 0x42::mathtest { - spec fun $fun1(a: u64,b: u64,c: u64): u64 { - Cast(Add(Add(Mul(2, Cast(a)), Mul(3, Cast(b))), Mul(5, Cast(c)))) - } } // end 0x42::mathtest module 0x42::test { use 0x42::mathtest; // resolved as: 0x42::mathtest @@ -20,10 +14,4 @@ module 0x42::test { }; Tuple() } - spec fun $test_nested_fun1() { - { - let a: u64 = mathtest::$fun1(2, mathtest::$fun1(3, mathtest2::$fun2(4, 5, 6), 7), mathtest2::$fun2(8, 9, mathtest::$fun1(10, mathtest2::$fun2(11, 12, 13), 14))); - Tuple() - } - } } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp index e209dfebff5c0..4ac34e7e2ade2 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/else_assigns_if_doesnt.exp @@ -22,5 +22,4 @@ module _0 { } } } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp index 207ef9b0ce121..efd3bd232a7b9 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_else_doesnt.exp @@ -22,5 +22,4 @@ module _0 { } } } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp index 321f2dff1fd14..ea573dd8c39a5 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_assigns_no_else.exp @@ -23,5 +23,4 @@ module _0 { Tuple() } } - spec fun $main(); } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp index 7d747c62cb701..d77d8e0a4b01b 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/if_condition.exp @@ -52,6 +52,4 @@ module 0x8675309::M { private fun t1() { Tuple() } - spec fun $t0(); - spec fun $t1(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp index 2e72a5e95492c..6541388dec1c1 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified.exp @@ -9,15 +9,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - Add(x, y) - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified2.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified2.exp index a0bf1c1bd0a8c..a7c40cc3ad9d9 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified2.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/moved_var_not_simplified2.exp @@ -12,18 +12,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - { - let _z: u256 = x; - y - } - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp index 35b5cb830c1f3..ba0a03aa56369 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/recursive_nesting.exp @@ -1,20 +1,11 @@ // -- Model dump before bytecode pipeline module 0x42::mathtest { - spec fun $mul_div(a: u64,b: u64,c: u64): u64 { - Cast(Div(Mul(Cast(a), Cast(b)), Cast(c))) - } } // end 0x42::mathtest module 0x42::mathtest2 { use 0x42::mathtest; // resolved as: 0x42::mathtest - spec fun $mul_div2(a: u64,b: u64,c: u64): u64 { - mathtest::$mul_div(b, a, c) - } } // end 0x42::mathtest2 module 0x42::mathtest3 { use 0x42::mathtest2; // resolved as: 0x42::mathtest2 - spec fun $mul_div3(a: u64,b: u64,c: u64): u64 { - mathtest2::$mul_div2(b, a, c) - } } // end 0x42::mathtest3 module 0x42::test { use 0x42::mathtest; // resolved as: 0x42::mathtest @@ -28,10 +19,4 @@ module 0x42::test { }; Tuple() } - spec fun $test_nested_mul_div() { - { - let a: u64 = mathtest::$mul_div(mathtest3::$mul_div3(1, 1, 1), mathtest::$mul_div(1, 1, 1), mathtest2::$mul_div2(1, 1, 1)); - Tuple() - } - } } // end 0x42::test diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp index 391386dcd2877..e7715ccabf3bf 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign.exp @@ -17,13 +17,4 @@ module _0 { } } } - spec fun $main() { - { - let x: u64; - { - let y: u64 = x; - Tuple() - } - } - } } // end _0 diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp index fcc23bdce4045..04e5c0984a968 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_loop.exp @@ -62,8 +62,4 @@ module 0x8675309::M { } } } - spec fun $tborrow1(); - spec fun $tborrow2(cond: bool); - spec fun $tcopy(cond: bool); - spec fun $tmove(); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp index 0e3895e383a11..26da21abbf036 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier-elimination/use_before_assign_while.exp @@ -76,10 +76,6 @@ module 0x8675309::M { } } } - spec fun $tborrow1(cond: bool); - spec fun $tborrow2(cond: bool); - spec fun $tcopy(cond: bool); - spec fun $tmove(cond: bool); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp b/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp index db1a990014d9e..7fc23f62bf2bf 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/bug_11112.exp @@ -33,5 +33,4 @@ module 0xcafe::vectors { } } } - spec fun $test_for_each_mut(); } // end 0xcafe::vectors diff --git a/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp b/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp index 903a8f78baf1c..2a849205ade5c 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/conditional_borrow.exp @@ -94,8 +94,4 @@ module 0x8675::M { public fun testb(): u64 { Add(M::test1b(pack M::S(7)), M::test1b(pack M::S(2))) } - spec fun $test(): u64; - spec fun $test1(r: u64): u64; - spec fun $test1b(r: M::S): u64; - spec fun $testb(): u64; } // end 0x8675::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp b/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp index 49ef45553fe64..103457c42d5f2 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/deep_exp.exp @@ -3,22 +3,4 @@ module 0x42::Test { public fun test(): u64 { 625 } - spec fun $f1(x: u64): u64 { - Test::$f2(Test::$f2(Test::$f2(Test::$f2(Test::$f2(x))))) - } - spec fun $f2(x: u64): u64 { - Test::$f3(Test::$f3(Test::$f3(Test::$f3(Test::$f3(x))))) - } - spec fun $f3(x: u64): u64 { - Test::$f4(Test::$f4(Test::$f4(Test::$f4(Test::$f4(x))))) - } - spec fun $f4(x: u64): u64 { - Test::$f5(Test::$f5(Test::$f5(Test::$f5(Test::$f5(x))))) - } - spec fun $f5(x: u64): u64 { - Add(x, 1) - } - spec fun $test(): u64 { - Test::$f1(0) - } } // end 0x42::Test diff --git a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp index 7da62cb8333af..4e64252a12e5a 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified.exp @@ -9,15 +9,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - Add(x, y) - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified2.exp b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified2.exp index d7e54813d8776..dc67de934dbc9 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified2.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/moved_var_not_simplified2.exp @@ -12,18 +12,6 @@ module 0xc0ffee::m { } } } - spec fun $test(): u8 { - { - let x: u256 = 40; - { - let y: u256 = Move(x); - { - let _z: u256 = x; - y - } - } - } - } } // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/simplifier/random.exp b/third_party/move/move-compiler-v2/tests/simplifier/random.exp index d8e0fcb185fb1..6475c0d47fbef 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/random.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/random.exp @@ -127,16 +127,6 @@ module 0x8675::M { } } } - spec fun $id(r: #0): #0 { - r - } - spec fun $id_mut(r: #0): #0 { - r - } - spec fun $iterloop(x: u64,y: &u64): u64; - spec fun $t0(); - spec fun $test1(r: u64): u64; - spec fun $test1a(x: u64,r: &u64): u64; } // end 0x8675::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp index a3d584e157614..ba31566abd4aa 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test1.exp @@ -27,6 +27,4 @@ module 0x8675::M { } } } - spec fun $test(): u64; - spec fun $test1(r: u64): u64; } // end 0x8675::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp index fb470086fff36..38ae1ecd3dc74 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test2.exp @@ -27,6 +27,4 @@ module 0x8675::M { } } } - spec fun $test(): u64; - spec fun $test1(r: u64): u64; } // end 0x8675::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp index 258409f593f30..bbfdba9bdbe4e 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test3.exp @@ -27,6 +27,4 @@ module 0x8675::M { } } } - spec fun $test(): u64; - spec fun $test1(r: u64): u64; } // end 0x8675::M diff --git a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test4.exp b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test4.exp index 7ae9bbb7e1ee8..a3cc781bc1513 100644 --- a/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test4.exp +++ b/third_party/move/move-compiler-v2/tests/simplifier/simplifier_test4.exp @@ -38,14 +38,6 @@ module 0x8675309::M { M::bar(Borrow(Mutable)(select M::S.f(s)), select M::S.f(s) = 0; 1) } - spec fun $bar(_s: u64,_u: u64) { - Tuple() - } - spec fun $foo(_s: M::S,_u: u64) { - Tuple() - } - spec fun $t0(s: &mut M::S); - spec fun $t1(s: &mut M::S); } // end 0x8675309::M diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index 221870cf103ef..516c10e5fbfac 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -5,9 +5,12 @@ use codespan_reporting::{diagnostic::Severity, term::termcolor::Buffer}; use log::debug; use move_compiler_v2::{ - annotate_units, ast_simplifier, disassemble_compiled_units, - env_pipeline::{lambda_lifter, lambda_lifter::LambdaLiftingOptions, EnvProcessorPipeline}, - flow_insensitive_checkers, function_checker, inliner, logging, pipeline, + annotate_units, ast_simplifier, check_and_rewrite_pipeline, disassemble_compiled_units, + env_pipeline::{ + lambda_lifter, lambda_lifter::LambdaLiftingOptions, rewrite_target::RewritingScope, + spec_rewriter, EnvProcessorPipeline, + }, + logging, pipeline, pipeline::{ ability_processor::AbilityProcessor, avail_copies_analysis::AvailCopiesAnalysisProcessor, copy_propagation::CopyPropagation, dead_store_elimination::DeadStoreElimination, @@ -98,30 +101,16 @@ fn test_runner(path: &Path) -> datatest_stable::Result<()> { impl TestConfig { fn get_config_from_path(path: &Path, options: &mut Options) -> TestConfig { - // Construct options, compiler and collect output. - let path = path.to_string_lossy(); - // The default transformation pipeline on the GlobalEnv - let mut env_pipeline = EnvProcessorPipeline::default(); - env_pipeline.add( - "unused checks", - flow_insensitive_checkers::check_for_unused_vars_and_params, - ); - env_pipeline.add( - "type parameter check", - function_checker::check_for_function_typed_parameters, - ); - env_pipeline.add( - "access and use check before inlining", - |env: &mut GlobalEnv| function_checker::check_access_and_use(env, true), - ); - env_pipeline.add("inlining", inliner::run_inlining); - env_pipeline.add( - "access and use check after inlining", - |env: &mut GlobalEnv| function_checker::check_access_and_use(env, false), - ); + // The transformation pipeline on the GlobalEnv + let mut env_pipeline = + check_and_rewrite_pipeline(options, false, RewritingScope::CompilationTarget); + // Add the specification rewriter for testing here as well, even though it is not run + // as part of regular compilation, but only as part of a prover run. + env_pipeline.add("specification rewriter", spec_rewriter::run_spec_rewriter); + // The bytecode transformation pipeline let mut pipeline = FunctionTargetPipeline::default(); - + let path = path.to_string_lossy(); if path.contains("/inlining/") || path.contains("/folding/") || path.contains("/simplifier/") diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/borrow_if_unfoldable.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/borrow_if_unfoldable.exp index 0df202d0dcff7..de63385453201 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/borrow_if_unfoldable.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/borrow_if_unfoldable.exp @@ -2,36 +2,34 @@ [variant baseline] fun _0::main($t0: bool) { - var $t1: u64 - var $t2: u64 - var $t3: &u64 - var $t4: &u64 - var $t5: bool - var $t6: u64 - var $t7: &u64 + var $t1: &u64 + var $t2: &u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: &u64 + var $t7: u64 var $t8: u64 - var $t9: u64 - 0: $t2 := 5 - 1: $t1 := infer($t2) - 2: if ($t0) goto 3 else goto 7 - 3: label L0 - 4: $t4 := borrow_local($t1) - 5: $t3 := infer($t4) - 6: goto 8 - 7: label L1 - 8: label L2 - 9: $t7 := move($t3) - 10: $t6 := read_ref($t7) - 11: $t8 := 5 - 12: $t5 := ==($t6, $t8) - 13: if ($t5) goto 14 else goto 16 - 14: label L3 - 15: goto 19 - 16: label L4 - 17: $t9 := 42 - 18: abort($t9) - 19: label L5 - 20: return () + 0: if ($t0) goto 1 else goto 6 + 1: label L0 + 2: $t3 := 5 + 3: $t2 := borrow_local($t3) + 4: $t1 := infer($t2) + 5: goto 7 + 6: label L1 + 7: label L2 + 8: $t6 := move($t1) + 9: $t5 := read_ref($t6) + 10: $t7 := 5 + 11: $t4 := ==($t5, $t7) + 12: if ($t4) goto 13 else goto 15 + 13: label L3 + 14: goto 18 + 15: label L4 + 16: $t8 := 42 + 17: abort($t8) + 18: label L5 + 19: return () } @@ -46,55 +44,52 @@ error: use of possibly unassigned local `ref` [variant baseline] fun _0::main($t0: bool) { - var $t1: u64 - var $t2: u64 - var $t3: &u64 - var $t4: &u64 - var $t5: bool - var $t6: u64 - var $t7: &u64 + var $t1: &u64 + var $t2: &u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: &u64 + var $t7: u64 var $t8: u64 - var $t9: u64 - # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 0: $t2 := 5 - # before: { no: $t1, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 1: $t1 := infer($t2) - # before: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 2: if ($t0) goto 3 else goto 7 - # before: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 3: label L0 - # before: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t3, $t5, $t6, $t7, $t8, $t9 } - 4: $t4 := borrow_local($t1) - # before: { no: $t3, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t5, $t6, $t7, $t8, $t9 } - 5: $t3 := infer($t4) - # before: { no: $t5, $t6, $t7, $t8, $t9 }, after: { no: $t5, $t6, $t7, $t8, $t9 } - 6: goto 8 - # before: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 7: label L1 - # before: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t3, $t4 }, after: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t3, $t4 } - 8: label L2 - # before: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t3, $t4 }, after: { no: $t5, $t6, $t8, $t9 }{ maybe: $t3, $t4 } - 9: $t7 := move($t3) - # before: { no: $t5, $t6, $t8, $t9 }{ maybe: $t3, $t4 }, after: { no: $t5, $t8, $t9 }{ maybe: $t3, $t4 } - 10: $t6 := read_ref($t7) - # before: { no: $t5, $t8, $t9 }{ maybe: $t3, $t4 }, after: { no: $t5, $t9 }{ maybe: $t3, $t4 } - 11: $t8 := 5 - # before: { no: $t5, $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 12: $t5 := ==($t6, $t8) - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 13: if ($t5) goto 14 else goto 16 - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 14: label L3 - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 15: goto 19 - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 16: label L4 - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { maybe: $t3, $t4 } - 17: $t9 := 42 - # before: { maybe: $t3, $t4 }, after: { maybe: $t3, $t4 } - 18: abort($t9) - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 19: label L5 - # before: { no: $t9 }{ maybe: $t3, $t4 }, after: { no: $t9 }{ maybe: $t3, $t4 } - 20: return () + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 0: if ($t0) goto 1 else goto 6 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 1: label L0 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 } + 2: $t3 := 5 + # before: { no: $t1, $t2, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t4, $t5, $t6, $t7, $t8 } + 3: $t2 := borrow_local($t3) + # before: { no: $t1, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t4, $t5, $t6, $t7, $t8 } + 4: $t1 := infer($t2) + # before: { no: $t4, $t5, $t6, $t7, $t8 }, after: { no: $t4, $t5, $t6, $t7, $t8 } + 5: goto 7 + # before: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 6: label L1 + # before: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3 } + 7: label L2 + # before: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t4, $t5, $t7, $t8 }{ maybe: $t1, $t2, $t3 } + 8: $t6 := move($t1) + # before: { no: $t4, $t5, $t7, $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t4, $t7, $t8 }{ maybe: $t1, $t2, $t3 } + 9: $t5 := read_ref($t6) + # before: { no: $t4, $t7, $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t4, $t8 }{ maybe: $t1, $t2, $t3 } + 10: $t7 := 5 + # before: { no: $t4, $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 11: $t4 := ==($t5, $t7) + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 12: if ($t4) goto 13 else goto 15 + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 13: label L3 + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 14: goto 18 + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 15: label L4 + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { maybe: $t1, $t2, $t3 } + 16: $t8 := 42 + # before: { maybe: $t1, $t2, $t3 }, after: { maybe: $t1, $t2, $t3 } + 17: abort($t8) + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 18: label L5 + # before: { no: $t8 }{ maybe: $t1, $t2, $t3 }, after: { no: $t8 }{ maybe: $t1, $t2, $t3 } + 19: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/struct_use_before_assign.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/struct_use_before_assign.exp index b367a3537bdaf..c4f0d16923b6c 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/struct_use_before_assign.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/struct_use_before_assign.exp @@ -73,22 +73,20 @@ fun M::main() { [variant baseline] fun M::main2() { var $t0: u64 - var $t1: u64 - var $t2: u64 - var $t3: M::R - var $t4: M::R + var $t1: M::R + var $t2: M::R + var $t3: u64 + var $t4: u64 var $t5: u64 var $t6: u64 var $t7: u64 - var $t8: u64 - 0: $t1 := 0 - 1: $t0 := infer($t1) - 2: $t4 := pack M::R($t0, $t2) - 3: $t3 := infer($t4) - 4: ($t5, $t6) := unpack M::R($t3) - 5: $t7 := infer($t6) - 6: $t8 := infer($t5) - 7: return () + 0: $t3 := 0 + 1: $t2 := pack M::R($t3, $t0) + 2: $t1 := infer($t2) + 3: ($t4, $t5) := unpack M::R($t1) + 4: $t6 := infer($t5) + 5: $t7 := infer($t4) + 6: return () } @@ -181,30 +179,27 @@ fun M::main() { [variant baseline] fun M::main2() { var $t0: u64 - var $t1: u64 - var $t2: u64 - var $t3: M::R - var $t4: M::R + var $t1: M::R + var $t2: M::R + var $t3: u64 + var $t4: u64 var $t5: u64 var $t6: u64 var $t7: u64 - var $t8: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } - 0: $t1 := 0 - # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t3, $t4, $t5, $t6, $t7, $t8 } - 1: $t0 := infer($t1) - # before: { no: $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t3, $t5, $t6, $t7, $t8 } - 2: $t4 := pack M::R($t0, $t2) - # before: { no: $t2, $t3, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t5, $t6, $t7, $t8 } - 3: $t3 := infer($t4) - # before: { no: $t2, $t5, $t6, $t7, $t8 }, after: { no: $t2, $t7, $t8 } - 4: ($t5, $t6) := unpack M::R($t3) - # before: { no: $t2, $t7, $t8 }, after: { no: $t2, $t8 } - 5: $t7 := infer($t6) - # before: { no: $t2, $t8 }, after: { no: $t2 } - 6: $t8 := infer($t5) - # before: { no: $t2 }, after: { no: $t2 } - 7: return () + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t2, $t4, $t5, $t6, $t7 } + 0: $t3 := 0 + # before: { no: $t0, $t1, $t2, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t1, $t4, $t5, $t6, $t7 } + 1: $t2 := pack M::R($t3, $t0) + # before: { no: $t0, $t1, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t4, $t5, $t6, $t7 } + 2: $t1 := infer($t2) + # before: { no: $t0, $t4, $t5, $t6, $t7 }, after: { no: $t0, $t6, $t7 } + 3: ($t4, $t5) := unpack M::R($t1) + # before: { no: $t0, $t6, $t7 }, after: { no: $t0, $t7 } + 4: $t6 := infer($t5) + # before: { no: $t0, $t7 }, after: { no: $t0 } + 5: $t7 := infer($t4) + # before: { no: $t0 }, after: { no: $t0 } + 6: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrow-tests/borrow_if.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrow-tests/borrow_if.exp index 85b55b6d7c532..98b9c0f9276cc 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrow-tests/borrow_if.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrow-tests/borrow_if.exp @@ -2,38 +2,36 @@ [variant baseline] fun _0::main() { - var $t0: u64 - var $t1: u64 + var $t0: &u64 + var $t1: bool var $t2: &u64 - var $t3: bool - var $t4: &u64 - var $t5: bool - var $t6: u64 - var $t7: &u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: &u64 + var $t7: u64 var $t8: u64 - var $t9: u64 - 0: $t1 := 5 - 1: $t0 := infer($t1) - 2: $t3 := true - 3: if ($t3) goto 4 else goto 8 - 4: label L0 - 5: $t4 := borrow_local($t0) - 6: $t2 := infer($t4) - 7: goto 9 - 8: label L1 - 9: label L2 - 10: $t7 := move($t2) - 11: $t6 := read_ref($t7) - 12: $t8 := 5 - 13: $t5 := ==($t6, $t8) - 14: if ($t5) goto 15 else goto 17 - 15: label L3 - 16: goto 20 - 17: label L4 - 18: $t9 := 42 - 19: abort($t9) - 20: label L5 - 21: return () + 0: $t1 := true + 1: if ($t1) goto 2 else goto 7 + 2: label L0 + 3: $t3 := 5 + 4: $t2 := borrow_local($t3) + 5: $t0 := infer($t2) + 6: goto 8 + 7: label L1 + 8: label L2 + 9: $t6 := move($t0) + 10: $t5 := read_ref($t6) + 11: $t7 := 5 + 12: $t4 := ==($t5, $t7) + 13: if ($t4) goto 14 else goto 16 + 14: label L3 + 15: goto 19 + 16: label L4 + 17: $t8 := 42 + 18: abort($t8) + 19: label L5 + 20: return () } @@ -48,58 +46,55 @@ error: use of possibly unassigned local `ref` [variant baseline] fun _0::main() { - var $t0: u64 - var $t1: u64 + var $t0: &u64 + var $t1: bool var $t2: &u64 - var $t3: bool - var $t4: &u64 - var $t5: bool - var $t6: u64 - var $t7: &u64 + var $t3: u64 + var $t4: bool + var $t5: u64 + var $t6: &u64 + var $t7: u64 var $t8: u64 - var $t9: u64 - # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 0: $t1 := 5 - # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 } - 1: $t0 := infer($t1) - # before: { no: $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } - 2: $t3 := true - # before: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } - 3: if ($t3) goto 4 else goto 8 - # before: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } - 4: label L0 - # before: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t5, $t6, $t7, $t8, $t9 } - 5: $t4 := borrow_local($t0) - # before: { no: $t2, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t5, $t6, $t7, $t8, $t9 } - 6: $t2 := infer($t4) - # before: { no: $t5, $t6, $t7, $t8, $t9 }, after: { no: $t5, $t6, $t7, $t8, $t9 } - 7: goto 9 - # before: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 }, after: { no: $t2, $t4, $t5, $t6, $t7, $t8, $t9 } - 8: label L1 - # before: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t2, $t4 }, after: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t2, $t4 } - 9: label L2 - # before: { no: $t5, $t6, $t7, $t8, $t9 }{ maybe: $t2, $t4 }, after: { no: $t5, $t6, $t8, $t9 }{ maybe: $t2, $t4 } - 10: $t7 := move($t2) - # before: { no: $t5, $t6, $t8, $t9 }{ maybe: $t2, $t4 }, after: { no: $t5, $t8, $t9 }{ maybe: $t2, $t4 } - 11: $t6 := read_ref($t7) - # before: { no: $t5, $t8, $t9 }{ maybe: $t2, $t4 }, after: { no: $t5, $t9 }{ maybe: $t2, $t4 } - 12: $t8 := 5 - # before: { no: $t5, $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 13: $t5 := ==($t6, $t8) - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 14: if ($t5) goto 15 else goto 17 - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 15: label L3 - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 16: goto 20 - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 17: label L4 - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { maybe: $t2, $t4 } - 18: $t9 := 42 - # before: { maybe: $t2, $t4 }, after: { maybe: $t2, $t4 } - 19: abort($t9) - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 20: label L5 - # before: { no: $t9 }{ maybe: $t2, $t4 }, after: { no: $t9 }{ maybe: $t2, $t4 } - 21: return () + # before: { no: $t0, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 0: $t1 := true + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 1: if ($t1) goto 2 else goto 7 + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 2: label L0 + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t4, $t5, $t6, $t7, $t8 } + 3: $t3 := 5 + # before: { no: $t0, $t2, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t4, $t5, $t6, $t7, $t8 } + 4: $t2 := borrow_local($t3) + # before: { no: $t0, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t4, $t5, $t6, $t7, $t8 } + 5: $t0 := infer($t2) + # before: { no: $t4, $t5, $t6, $t7, $t8 }, after: { no: $t4, $t5, $t6, $t7, $t8 } + 6: goto 8 + # before: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 }, after: { no: $t0, $t2, $t3, $t4, $t5, $t6, $t7, $t8 } + 7: label L1 + # before: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t0, $t2, $t3 } + 8: label L2 + # before: { no: $t4, $t5, $t6, $t7, $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t4, $t5, $t7, $t8 }{ maybe: $t0, $t2, $t3 } + 9: $t6 := move($t0) + # before: { no: $t4, $t5, $t7, $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t4, $t7, $t8 }{ maybe: $t0, $t2, $t3 } + 10: $t5 := read_ref($t6) + # before: { no: $t4, $t7, $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t4, $t8 }{ maybe: $t0, $t2, $t3 } + 11: $t7 := 5 + # before: { no: $t4, $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 12: $t4 := ==($t5, $t7) + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 13: if ($t4) goto 14 else goto 16 + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 14: label L3 + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 15: goto 19 + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 16: label L4 + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { maybe: $t0, $t2, $t3 } + 17: $t8 := 42 + # before: { maybe: $t0, $t2, $t3 }, after: { maybe: $t0, $t2, $t3 } + 18: abort($t8) + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 19: label L5 + # before: { no: $t8 }{ maybe: $t0, $t2, $t3 }, after: { no: $t8 }{ maybe: $t0, $t2, $t3 } + 20: return () } diff --git a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp index c74844dceea23..20bf8e77052d9 100644 --- a/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp +++ b/third_party/move/move-compiler-v2/tests/uninit-use-checker/v1-borrows/eq_unassigned_local.exp @@ -2,16 +2,14 @@ [variant baseline] fun _0::main() { - var $t0: u64 - var $t1: u64 + var $t0: &u64 + var $t1: bool var $t2: &u64 - var $t3: bool - var $t4: &u64 - 0: $t1 := 5 - 1: $t0 := infer($t1) - 2: $t4 := borrow_local($t0) - 3: $t3 := ==($t2, $t4) - 4: return () + var $t3: u64 + 0: $t3 := 5 + 1: $t2 := borrow_local($t3) + 2: $t1 := ==($t0, $t2) + 3: return () } @@ -26,19 +24,16 @@ error: use of unassigned local `ref` [variant baseline] fun _0::main() { - var $t0: u64 - var $t1: u64 + var $t0: &u64 + var $t1: bool var $t2: &u64 - var $t3: bool - var $t4: &u64 - # before: { no: $t0, $t1, $t2, $t3, $t4 }, after: { no: $t0, $t2, $t3, $t4 } - 0: $t1 := 5 - # before: { no: $t0, $t2, $t3, $t4 }, after: { no: $t2, $t3, $t4 } - 1: $t0 := infer($t1) - # before: { no: $t2, $t3, $t4 }, after: { no: $t2, $t3 } - 2: $t4 := borrow_local($t0) - # before: { no: $t2, $t3 }, after: { no: $t2 } - 3: $t3 := ==($t2, $t4) - # before: { no: $t2 }, after: { no: $t2 } - 4: return () + var $t3: u64 + # before: { no: $t0, $t1, $t2, $t3 }, after: { no: $t0, $t1, $t2 } + 0: $t3 := 5 + # before: { no: $t0, $t1, $t2 }, after: { no: $t0, $t1 } + 1: $t2 := borrow_local($t3) + # before: { no: $t0, $t1 }, after: { no: $t0 } + 2: $t1 := ==($t0, $t2) + # before: { no: $t0 }, after: { no: $t0 } + 3: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp index 8067cf5841074..4aa5c9df3934e 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/borrowed_var.exp @@ -2,23 +2,23 @@ [variant baseline] fun m::test() { - var $t0: u64 - var $t1: u64 - var $t2: &u64 + var $t0: &u64 + var $t1: &u64 + var $t2: u64 var $t3: &u64 var $t4: &u64 - var $t5: &u64 + var $t5: u64 var $t6: bool var $t7: u64 var $t8: u64 - 0: $t1 := 5 - 1: $t0 := infer($t1) - 2: $t3 := borrow_local($t0) - 3: $t2 := infer($t3) - 4: $t4 := infer($t2) - 5: $t5 := borrow_local($t0) - 6: $t2 := infer($t5) - 7: $t7 := read_ref($t2) + 0: $t2 := 5 + 1: $t1 := borrow_local($t2) + 2: $t0 := infer($t1) + 3: $t3 := infer($t0) + 4: $t5 := 5 + 5: $t4 := borrow_local($t5) + 6: $t0 := infer($t4) + 7: $t7 := read_ref($t0) 8: $t8 := 5 9: $t6 := ==($t7, $t8) 10: return () @@ -28,31 +28,31 @@ fun m::test() { [variant baseline] fun m::test() { - var $t0: u64 - var $t1: u64 - var $t2: &u64 + var $t0: &u64 + var $t1: &u64 + var $t2: u64 var $t3: &u64 var $t4: &u64 - var $t5: &u64 + var $t5: u64 var $t6: bool var $t7: u64 var $t8: u64 # live vars: - 0: $t1 := 5 + 0: $t2 := 5 + # live vars: $t2 + 1: $t1 := borrow_local($t2) # live vars: $t1 - 1: $t0 := infer($t1) - # live vars: $t0 - 2: $t3 := borrow_local($t0) - # live vars: $t0, $t3 - 3: $t2 := infer($t3) - # live vars: $t0, $t2 - 4: $t4 := infer($t2) + 2: $t0 := infer($t1) # live vars: $t0 - 5: $t5 := borrow_local($t0) + 3: $t3 := infer($t0) + # live vars: + 4: $t5 := 5 # live vars: $t5 - 6: $t2 := infer($t5) - # live vars: $t2 - 7: $t7 := read_ref($t2) + 5: $t4 := borrow_local($t5) + # live vars: $t4 + 6: $t0 := infer($t4) + # live vars: $t0 + 7: $t7 := read_ref($t0) # live vars: $t7 8: $t8 := 5 # live vars: $t7, $t8 @@ -65,24 +65,24 @@ fun m::test() { [variant baseline] fun m::test() { - var $t0: u64 - var $t1: u64 - var $t2: &u64 [unused] + var $t0: &u64 [unused] + var $t1: &u64 + var $t2: u64 var $t3: &u64 var $t4: &u64 - var $t5: &u64 + var $t5: u64 var $t6: bool - var $t7: u64 [unused] + var $t7: u64 var $t8: u64 - 0: $t1 := 5 - 1: $t0 := infer($t1) - 2: $t3 := borrow_local($t0) - 3: $t3 := infer($t3) - 4: $t4 := infer($t3) - 5: $t5 := borrow_local($t0) - 6: $t3 := infer($t5) - 7: $t1 := read_ref($t3) + 0: $t2 := 5 + 1: $t1 := borrow_local($t2) + 2: $t1 := infer($t1) + 3: $t3 := infer($t1) + 4: $t5 := 5 + 5: $t4 := borrow_local($t5) + 6: $t1 := infer($t4) + 7: $t7 := read_ref($t1) 8: $t8 := 5 - 9: $t6 := ==($t1, $t8) + 9: $t6 := ==($t7, $t8) 10: return () } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp index 7b29ebb34129d..94ae377297be2 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/conditional.exp @@ -3,28 +3,14 @@ [variant baseline] fun m::test($t0: bool): u64 { var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: u64 - var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 - 0: $t3 := 2 - 1: $t2 := infer($t3) - 2: if ($t0) goto 3 else goto 8 - 3: label L0 - 4: $t5 := 3 - 5: $t4 := infer($t5) - 6: $t1 := infer($t4) - 7: goto 13 - 8: label L1 - 9: $t8 := 1 - 10: $t7 := +($t2, $t8) - 11: $t6 := infer($t7) - 12: $t1 := infer($t6) - 13: label L2 - 14: return $t1 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t1 := 3 + 3: goto 6 + 4: label L1 + 5: $t1 := 3 + 6: label L2 + 7: return $t1 } ============ after LiveVarAnalysisProcessor: ================ @@ -32,70 +18,35 @@ fun m::test($t0: bool): u64 { [variant baseline] fun m::test($t0: bool): u64 { var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: u64 - var $t5: u64 - var $t6: u64 - var $t7: u64 - var $t8: u64 # live vars: $t0 - 0: $t3 := 2 - # live vars: $t0, $t3 - 1: $t2 := infer($t3) - # live vars: $t0, $t2 - 2: if ($t0) goto 3 else goto 8 - # live vars: $t2 - 3: label L0 + 0: if ($t0) goto 1 else goto 4 # live vars: - 4: $t5 := 3 - # live vars: $t5 - 5: $t4 := infer($t5) - # live vars: $t4 - 6: $t1 := infer($t4) + 1: label L0 + # live vars: + 2: $t1 := 3 # live vars: $t1 - 7: goto 13 - # live vars: $t2 - 8: label L1 - # live vars: $t2 - 9: $t8 := 1 - # live vars: $t2, $t8 - 10: $t7 := +($t2, $t8) - # live vars: $t7 - 11: $t6 := infer($t7) - # live vars: $t6 - 12: $t1 := infer($t6) + 3: goto 6 + # live vars: + 4: label L1 + # live vars: + 5: $t1 := 3 # live vars: $t1 - 13: label L2 + 6: label L2 # live vars: $t1 - 14: return $t1 + 7: return $t1 } ============ after VariableCoalescing: ================ [variant baseline] fun m::test($t0: bool): u64 { - var $t1: u64 [unused] - var $t2: u64 [unused] - var $t3: u64 - var $t4: u64 [unused] - var $t5: u64 - var $t6: u64 [unused] - var $t7: u64 [unused] - var $t8: u64 - 0: $t3 := 2 - 1: $t3 := infer($t3) - 2: if ($t0) goto 3 else goto 8 - 3: label L0 - 4: $t5 := 3 - 5: $t5 := infer($t5) - 6: $t5 := infer($t5) - 7: goto 13 - 8: label L1 - 9: $t8 := 1 - 10: $t3 := +($t3, $t8) - 11: $t3 := infer($t3) - 12: $t5 := infer($t3) - 13: label L2 - 14: return $t5 + var $t1: u64 + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t1 := 3 + 3: goto 6 + 4: label L1 + 5: $t1 := 3 + 6: label L2 + 7: return $t1 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp index ccf948da99a9a..eec345b1c2e77 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/overlapping_vars.exp @@ -3,22 +3,8 @@ [variant baseline] fun m::test(): u64 { var $t0: u64 - var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: u64 - var $t5: u64 - var $t6: u64 - var $t7: u64 - 0: $t2 := 1 - 1: $t1 := infer($t2) - 2: $t4 := 2 - 3: $t3 := infer($t4) - 4: $t6 := 3 - 5: $t5 := infer($t6) - 6: $t7 := +($t1, $t3) - 7: $t0 := +($t7, $t5) - 8: return $t0 + 0: $t0 := 6 + 1: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -26,52 +12,17 @@ fun m::test(): u64 { [variant baseline] fun m::test(): u64 { var $t0: u64 - var $t1: u64 - var $t2: u64 - var $t3: u64 - var $t4: u64 - var $t5: u64 - var $t6: u64 - var $t7: u64 # live vars: - 0: $t2 := 1 - # live vars: $t2 - 1: $t1 := infer($t2) - # live vars: $t1 - 2: $t4 := 2 - # live vars: $t1, $t4 - 3: $t3 := infer($t4) - # live vars: $t1, $t3 - 4: $t6 := 3 - # live vars: $t1, $t3, $t6 - 5: $t5 := infer($t6) - # live vars: $t1, $t3, $t5 - 6: $t7 := +($t1, $t3) - # live vars: $t5, $t7 - 7: $t0 := +($t7, $t5) + 0: $t0 := 6 # live vars: $t0 - 8: return $t0 + 1: return $t0 } ============ after VariableCoalescing: ================ [variant baseline] fun m::test(): u64 { - var $t0: u64 [unused] - var $t1: u64 [unused] - var $t2: u64 - var $t3: u64 [unused] - var $t4: u64 - var $t5: u64 [unused] - var $t6: u64 - var $t7: u64 [unused] - 0: $t2 := 1 - 1: $t2 := infer($t2) - 2: $t4 := 2 - 3: $t4 := infer($t4) - 4: $t6 := 3 - 5: $t6 := infer($t6) - 6: $t2 := +($t2, $t4) - 7: $t2 := +($t2, $t6) - 8: return $t2 + var $t0: u64 + 0: $t0 := 6 + 1: return $t0 } diff --git a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp index 2eb4c17193cb2..a17b522b9f047 100644 --- a/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp +++ b/third_party/move/move-compiler-v2/tests/variable-coalescing/reassigned_var.exp @@ -7,15 +7,13 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 - var $t5: u64 0: $t2 := 1 1: $t1 := infer($t2) - 2: $t4 := 2 - 3: $t3 := infer($t4) - 4: $t5 := 9 - 5: $t1 := infer($t5) - 6: $t0 := +($t1, $t3) - 7: return $t0 + 2: $t3 := 9 + 3: $t1 := infer($t3) + 4: $t4 := 2 + 5: $t0 := +($t1, $t4) + 6: return $t0 } ============ after LiveVarAnalysisProcessor: ================ @@ -27,23 +25,20 @@ fun m::test(): u64 { var $t2: u64 var $t3: u64 var $t4: u64 - var $t5: u64 # live vars: 0: $t2 := 1 # live vars: $t2 1: $t1 := infer($t2) # live vars: - 2: $t4 := 2 - # live vars: $t4 - 3: $t3 := infer($t4) + 2: $t3 := 9 # live vars: $t3 - 4: $t5 := 9 - # live vars: $t3, $t5 - 5: $t1 := infer($t5) - # live vars: $t1, $t3 - 6: $t0 := +($t1, $t3) + 3: $t1 := infer($t3) + # live vars: $t1 + 4: $t4 := 2 + # live vars: $t1, $t4 + 5: $t0 := +($t1, $t4) # live vars: $t0 - 7: return $t0 + 6: return $t0 } ============ after VariableCoalescing: ================ @@ -54,14 +49,12 @@ fun m::test(): u64 { var $t1: u64 [unused] var $t2: u64 var $t3: u64 [unused] - var $t4: u64 [unused] - var $t5: u64 + var $t4: u64 0: $t2 := 1 - 1: $t5 := infer($t2) - 2: $t2 := 2 + 1: $t2 := infer($t2) + 2: $t2 := 9 3: $t2 := infer($t2) - 4: $t5 := 9 - 5: $t5 := infer($t5) - 6: $t2 := +($t5, $t2) - 7: return $t2 + 4: $t4 := 2 + 5: $t2 := +($t2, $t4) + 6: return $t2 } diff --git a/third_party/move/move-model/bytecode-test-utils/Cargo.toml b/third_party/move/move-model/bytecode-test-utils/Cargo.toml index 5a8064fbaf96d..fed87a1d9ca17 100644 --- a/third_party/move/move-model/bytecode-test-utils/Cargo.toml +++ b/third_party/move/move-model/bytecode-test-utils/Cargo.toml @@ -14,6 +14,7 @@ anyhow = "1.0.52" codespan-reporting = { version = "0.11.1", features = ["serde", "serialization"] } move-command-line-common = { path = "../../move-command-line-common" } move-compiler = { path = "../../move-compiler" } +move-compiler-v2 = { path = "../../move-compiler-v2" } move-model = { path = ".." } move-prover-test-utils = { path = "../../move-prover/test-utils" } move-stackless-bytecode = { path = "../bytecode" } diff --git a/third_party/move/move-model/bytecode-test-utils/src/lib.rs b/third_party/move/move-model/bytecode-test-utils/src/lib.rs index 05d53a785f46d..3350d520130f2 100644 --- a/third_party/move/move-model/bytecode-test-utils/src/lib.rs +++ b/third_party/move/move-model/bytecode-test-utils/src/lib.rs @@ -6,6 +6,10 @@ use anyhow::anyhow; use codespan_reporting::{diagnostic::Severity, term::termcolor::Buffer}; use move_command_line_common::testing::EXP_EXT; use move_compiler::shared::{known_attributes::KnownAttribute, PackagePaths}; +use move_compiler_v2::{ + self, + env_pipeline::{rewrite_target::RewritingScope, spec_rewriter}, +}; use move_model::{model::GlobalEnv, options::ModelBuilderOptions, run_model_builder_with_options}; use move_prover_test_utils::{baseline_test::verify_or_update_baseline, extract_test_directives}; use move_stackless_bytecode::{ @@ -28,7 +32,7 @@ pub fn test_runner( ) -> anyhow::Result<()> { let mut sources = extract_test_directives(path, "// dep:")?; sources.push(path.to_string_lossy().to_string()); - let env: GlobalEnv = run_model_builder_with_options( + let mut env: GlobalEnv = run_model_builder_with_options( vec![PackagePaths { name: None, paths: sources, @@ -39,6 +43,15 @@ pub fn test_runner( false, KnownAttribute::get_all_attribute_names(), )?; + let compiler_options = move_compiler_v2::Options::default(); + let mut pipeline = move_compiler_v2::check_and_rewrite_pipeline( + &compiler_options, + true, + RewritingScope::Everything, + ); + pipeline.add("specification rewriter", spec_rewriter::run_spec_rewriter); + env.set_extension(compiler_options); + pipeline.run(&mut env); let out = if env.has_errors() { let mut error_writer = Buffer::no_color(); env.report_diag(&mut error_writer, Severity::Error); diff --git a/third_party/move/move-model/src/ast.rs b/third_party/move/move-model/src/ast.rs index 0d83471be2764..9a31feefbf904 100644 --- a/third_party/move/move-model/src/ast.rs +++ b/third_party/move/move-model/src/ast.rs @@ -57,7 +57,7 @@ pub struct SpecFunDecl { pub is_move_fun: bool, pub is_native: bool, pub body: Option, - pub callees: BTreeSet>, + pub callees: BTreeSet>, pub is_recursive: RefCell>, } @@ -307,6 +307,13 @@ impl Spec { !self.conditions.is_empty() } + pub fn is_empty(&self) -> bool { + self.conditions.is_empty() + && self.on_impl.is_empty() + && self.properties.is_empty() + && self.update_map.is_empty() + } + pub fn filter

(&self, pred: P) -> impl Iterator where P: FnMut(&&Condition) -> bool, @@ -332,6 +339,19 @@ impl Spec { pub fn any_kind(&self, kind: ConditionKind) -> bool { self.any(move |c| c.kind == kind) } + + pub fn called_funs_with_callsites(&self) -> BTreeMap, BTreeSet> { + let mut result = BTreeMap::new(); + for cond in self.conditions.iter().chain(self.update_map.values()) { + for exp in cond.all_exps() { + result.append(&mut exp.called_funs_with_callsites()) + } + } + for on_impl in self.on_impl.values() { + result.append(&mut on_impl.called_funs_with_callsites()) + } + result + } } /// Information about a specification block in the source. This is used for documentation @@ -351,11 +371,18 @@ pub struct SpecBlockInfo { /// Describes the target of a spec block. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum SpecBlockTarget { - Module, + /// The block is associated with the current module. + Module(ModuleId), + /// The block is associated with the structure. Struct(ModuleId, StructId), + /// The block is associated with the function. Function(ModuleId, FunId), + /// The block is associated with bytecode of the given function at given code offset. FunctionCode(ModuleId, FunId, usize), + /// The block is associated with a specification schema. Schema(ModuleId, SchemaId, Vec), + /// The block is inline in an expression. + Inline, } /// Describes a global invariant. @@ -809,6 +836,26 @@ impl ExpData { result } + /// Returns the directly used memory of this expression, without label. + pub fn directly_used_memory(&self, env: &GlobalEnv) -> BTreeSet> { + let mut result = BTreeSet::new(); + let mut visitor = |e: &ExpData| { + use ExpData::*; + use Operation::*; + match e { + Call(id, Exists(_), _) | Call(id, Global(_), _) => { + let inst = &env.get_node_instantiation(*id); + let (mid, sid, sinst) = inst[0].require_struct(); + result.insert(mid.qualified_inst(sid, sinst.to_owned())); + }, + _ => {}, + } + true // keep going + }; + self.visit_post_order(&mut visitor); + result + } + /// Returns the temporaries used in this expression. Result is ordered by occurrence. pub fn used_temporaries(&self, env: &GlobalEnv) -> Vec<(TempIndex, Type)> { let mut temps = vec![]; @@ -841,6 +888,24 @@ impl ExpData { called } + /// Returns the specification functions called by this expression + pub fn called_spec_funs(&self, env: &GlobalEnv) -> BTreeSet> { + let mut called = BTreeSet::new(); + let mut visitor = |e: &ExpData| { + #[allow(clippy::single_match)] // may need to extend match in the future + match e { + ExpData::Call(id, Operation::SpecFunction(mid, fid, _), _) => { + let inst = env.get_node_instantiation(*id); + called.insert(mid.qualified_inst(*fid, inst)); + }, + _ => {}, + } + true // keep going + }; + self.visit_post_order(&mut visitor); + called + } + /// Returns the Move functions called by this expression, along with nodes of call sites. pub fn called_funs_with_callsites(&self) -> BTreeMap, BTreeSet> { let mut called: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); @@ -944,6 +1009,20 @@ impl ExpData { }); } + /// Visits all inline specification blocks in the expression. + pub fn visit_inline_specs(&self, visitor: &mut F) + where + F: FnMut(&Spec) -> bool, + { + self.visit_pre_order(&mut |e| { + if let ExpData::SpecBlock(_, spec) = e { + visitor(spec) + } else { + true + } + }); + } + pub fn any

(&self, predicate: &mut P) -> bool where P: FnMut(&ExpData) -> bool, @@ -2990,6 +3069,9 @@ impl<'a> fmt::Display for EnvDisplay<'a, Spec> { writeln!(f, " {}", self.env.display(cond))? } writeln!(f, "}}")?; + for (code_offset, spec) in &self.val.on_impl { + writeln!(f, "{} -> {}", code_offset, self.env.display(spec))? + } Ok(()) } } diff --git a/third_party/move/move-model/src/builder/builtins.rs b/third_party/move/move-model/src/builder/builtins.rs index 7dd06d7a83e89..4e53fc59d0594 100644 --- a/third_party/move/move-model/src/builder/builtins.rs +++ b/third_party/move/move-model/src/builder/builtins.rs @@ -10,6 +10,7 @@ use crate::{ model::{Parameter, TypeParameter}, ty::{Constraint, PrimitiveType, ReferenceKind, Type}, }; +use move_binary_format::file_format::Ability; use move_compiler::parser::ast::{self as PA}; use move_core_types::u256::U256; use num::BigInt; @@ -521,13 +522,16 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { ); // Resources. + let param_key_constraint: BTreeMap<_, _> = [(0, Constraint::HasAbility(Ability::Key))] + .into_iter() + .collect(); trans.define_spec_or_builtin_fun( trans.builtin_qualified_symbol("global"), SpecOrBuiltinFunEntry { loc: loc.clone(), oper: Operation::Global(None), type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![mk_param(trans, 1, address_t.clone())], result_type: param_t.clone(), visibility: Spec, @@ -541,10 +545,10 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { loc: loc.clone(), oper: Operation::BorrowGlobal(ReferenceKind::Immutable), type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![mk_param(trans, 1, address_t.clone())], result_type: ref_param_t.clone(), - visibility: SpecAndImpl, // Visible in specs also for translate_fun_as_spec mode + visibility: SpecAndImpl, // Visible in specs also for better error messages }, ); trans.define_spec_or_builtin_fun( @@ -553,10 +557,10 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { loc: loc.clone(), oper: Operation::BorrowGlobal(ReferenceKind::Mutable), type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![mk_param(trans, 1, address_t.clone())], result_type: mut_ref_param_t.clone(), - visibility: SpecAndImpl, // Visible in specs also for translate_fun_as_spec mode + visibility: SpecAndImpl, // Visible in specs also for better error messages }, ); trans.define_spec_or_builtin_fun( @@ -578,7 +582,7 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { loc: loc.clone(), oper: Operation::MoveTo, type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![ mk_param( trans, @@ -600,7 +604,7 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { loc: loc.clone(), oper: Operation::MoveFrom, type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![mk_param(trans, 1, address_t.clone())], result_type: param_t.clone(), visibility: Impl, @@ -613,7 +617,7 @@ pub(crate) fn declare_builtins(trans: &mut ModelBuilder) { loc: loc.clone(), oper: Operation::Exists(None), type_params: vec![param_t_decl.clone()], - type_param_constraints: BTreeMap::default(), + type_param_constraints: param_key_constraint.clone(), params: vec![mk_param(trans, 1, address_t.clone())], result_type: bool_t.clone(), visibility: SpecAndImpl, diff --git a/third_party/move/move-model/src/builder/exp_builder.rs b/third_party/move/move-model/src/builder/exp_builder.rs index 4448e1f90719d..1c41223cc3209 100644 --- a/third_party/move/move-model/src/builder/exp_builder.rs +++ b/third_party/move/move-model/src/builder/exp_builder.rs @@ -105,9 +105,6 @@ pub(crate) enum ExpTranslationMode { Spec, /// Translate the implementation language fragment Impl, - /// Special mode attempting to translate implementation code into specification language. - /// If successful, allows to call implementation functions from specs. - TryImplAsSpec, } #[derive(Debug, PartialEq)] @@ -128,7 +125,10 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo for id in parent.parent.get_struct_ids() { struct_cache.insert( id, - parent.parent.lookup_struct_fields(id.instantiate(vec![])), + ( + parent.parent.lookup_struct_fields(id.instantiate(vec![])), + parent.parent.lookup_struct_abilities(id), + ), ); } Self { @@ -187,15 +187,8 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo self.mode = ExpTranslationMode::Impl; } - pub fn set_translate_fun_as_spec_fun(&mut self) { - self.mode = ExpTranslationMode::TryImplAsSpec; - } - pub fn is_spec_mode(&self) -> bool { - matches!( - self.mode, - ExpTranslationMode::Spec | ExpTranslationMode::TryImplAsSpec - ) + matches!(self.mode, ExpTranslationMode::Spec) } pub fn type_variance(&self) -> Variance { @@ -215,10 +208,7 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo (self.mode, visibility), (_, EntryVisibility::SpecAndImpl) | (ExpTranslationMode::Impl, EntryVisibility::Impl) - | ( - ExpTranslationMode::Spec | ExpTranslationMode::TryImplAsSpec, - EntryVisibility::Spec, - ) + | (ExpTranslationMode::Spec, EntryVisibility::Spec,) ) } @@ -262,17 +252,13 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo /// Shortcut for reporting an error. pub fn error_with_notes(&mut self, loc: &Loc, msg: &str, notes: Vec) { self.had_errors = true; - if self.mode != ExpTranslationMode::TryImplAsSpec { - self.parent.parent.error_with_notes(loc, msg, notes); - } + self.parent.parent.error_with_notes(loc, msg, notes); } /// Shortcut for reporting an error. pub fn error_with_labels(&mut self, loc: &Loc, msg: &str, labels: Vec<(Loc, String)>) { self.had_errors = true; - if self.mode != ExpTranslationMode::TryImplAsSpec { - self.env().error_with_labels(loc, msg, labels); - } + self.env().error_with_labels(loc, msg, labels); } /// Shortcut for reporting a bug @@ -1444,12 +1430,6 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo let id = self.new_node_id_with_type_loc(&result_ty, &loc); ExpData::Mutate(id, lhs.into_exp(), rhs.into_exp()) }, - EA::Exp_::Dereference(exp) | EA::Exp_::Borrow(_, exp) - if self.mode == ExpTranslationMode::TryImplAsSpec => - { - // Skip reference operators when interpreting as specification expression. - self.translate_exp(exp, expected_type) - }, EA::Exp_::Dereference(exp) => { self.require_impl_language(&loc); let var = self.fresh_type_var_constr( @@ -2104,32 +2084,20 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo module_name: self.parent.module_name.clone(), symbol: remapped_sym, }; - let spec_fun_entry = match self.parent.parent.spec_fun_table.get(&spec_fun_sym) - { + let fun_entry = match self.parent.parent.fun_table.get(&spec_fun_sym) { None => { self.error( loc, &format!( - "Unable to find spec function from lifted lambda: {}", - remapped_sym.display(self.symbol_pool()) + "Unable to find function from lifted \ + lambda: {} (for parameter {})", + remapped_sym.display(self.symbol_pool()), + sym.display(self.symbol_pool()) ), ); return Some(self.new_error_exp()); }, - Some(entries) => { - if entries.len() != 1 { - self.error( - loc, - &format!( - "Expect a unique spec function from lifted lambda: {}, found {}", - remapped_sym.display(self.symbol_pool()), - entries.len() - ), - ); - return Some(self.new_error_exp()); - } - entries.last().unwrap().clone() - }, + Some(entry) => entry.clone(), }; // the preset arguments always appears in front @@ -2158,10 +2126,10 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo // type checking let return_type_error = - self.check_type(loc, &spec_fun_entry.result_type, expected_type, context) + self.check_type(loc, &fun_entry.result_type, expected_type, context) == Type::Error; - if full_arg_types.len() != spec_fun_entry.params.len() { + if full_arg_types.len() != fun_entry.params.len() { self.error( loc, &format!( @@ -2173,7 +2141,7 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo } let param_type_error = full_arg_types .iter() - .zip(spec_fun_entry.params.iter().map(|p| &p.1)) + .zip(fun_entry.params.iter().map(|p| &p.1)) .any(|(actual_ty, expected_ty)| { self.check_type( loc, @@ -2187,32 +2155,10 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo } // construct the call - match &spec_fun_entry.oper { - Operation::SpecFunction(module_id, spec_fun_id, None) => { - if self.mode != ExpTranslationMode::TryImplAsSpec { - // Record the usage of spec function in specs, used later in spec - // translator. - self.parent - .parent - .add_used_spec_fun(module_id.qualified(*spec_fun_id)); - } - self.called_spec_funs.insert((*module_id, *spec_fun_id)); - }, - _ => { - self.error( - loc, - &format!( - "Invalid spec function entry for {}", - remapped_sym.display(self.symbol_pool()) - ), - ); - return Some(self.new_error_exp()); - }, - } let call_exp_id = self.new_node_id_with_type_loc(expected_type, loc); return Some(ExpData::Call( call_exp_id, - spec_fun_entry.oper.clone(), + Operation::MoveFunction(fun_entry.module_id, fun_entry.fun_id), full_arg_exprs, )); } @@ -2316,16 +2262,9 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo self.exit_scope(); self.new_bind_exp(loc, pat, binding, rest.into_exp()) }, - Seq(exp) - if self.mode != ExpTranslationMode::Impl - && matches!(exp.value, EA::Exp_::Spec(..)) => - { - // Skip specification blocks if we are not in Impl translation mode. - // This is specifically relevant for the TryImplAsSpec mode where the spec - // blocks must be ignored. - self.translate_seq_recursively(loc, &items[1..], expected_type, context) - }, Seq(exp) if items.len() > 1 => { + // This is an actual impl language sequence `s;rest`. + self.require_impl_language(loc); // There is an item after this one, so the value can be dropped. The default // type of the expression is `()`. let exp_loc = self.to_loc(&exp.loc); @@ -2346,32 +2285,17 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo ) .expect("success on fresh var"); } - - if self.mode == ExpTranslationMode::TryImplAsSpec - && matches!(exp, ExpData::Call(_, Operation::NoOp, _)) - { - // Skip assert! statements (marked via NoOp) when translating move functions - // as spec functions - self.translate_seq_recursively(loc, &items[1..], expected_type, context) - } else { - // This is an actual impl language sequence `s;rest`. - self.require_impl_language(loc); - let rest = self.translate_seq_recursively( - loc, - &items[1..], - expected_type, - context, - ); - let id = self.new_node_id_with_type_loc(expected_type, loc); - let exps = match exp { - ExpData::Sequence(_, mut exps) => { - exps.push(rest.into_exp()); - exps - }, - _ => vec![exp.into_exp(), rest.into_exp()], - }; - ExpData::Sequence(id, exps) - } + let rest = + self.translate_seq_recursively(loc, &items[1..], expected_type, context); + let id = self.new_node_id_with_type_loc(expected_type, loc); + let exps = match exp { + ExpData::Sequence(_, mut exps) => { + exps.push(rest.into_exp()); + exps + }, + _ => vec![exp.into_exp(), rest.into_exp()], + }; + ExpData::Sequence(id, exps) }, Seq(exp) => self.translate_exp_in_context(exp, expected_type, context), } @@ -2541,12 +2465,7 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo let id = self.new_node_id_with_type_loc(&ty, loc); if let Some(oper) = oper_opt { Some(ExpData::Call(id, oper, vec![])) - } else if let Some(index) = - index_opt.filter(|_| self.mode != ExpTranslationMode::TryImplAsSpec) - { - // Only create a temporary if we are not currently translating a move function as - // a spec function, or a let. In this case, the LocalVarEntry has a bytecode index, but - // we do not want to use this if interpreted as a spec fun. + } else if let Some(index) = index_opt { Some(ExpData::Temporary(id, index)) } else { Some(ExpData::LocalVar(id, sym)) @@ -2746,11 +2665,9 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo } })) } - if self.mode == ExpTranslationMode::Impl { - // Add user function. - if let Some(entry) = self.parent.parent.fun_table.get(&full_name) { - cands.push(entry.clone().into()) - } + // Add user function. + if let Some(entry) = self.parent.parent.fun_table.get(&full_name) { + cands.push(entry.clone().into()) } } if cands.is_empty() { @@ -2901,51 +2818,11 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo }; if let Operation::SpecFunction(module_id, spec_fun_id, None) = oper { - if self.mode != ExpTranslationMode::TryImplAsSpec { - // Record the usage of spec function in specs, used later - // in spec translator. - self.parent - .parent - .add_used_spec_fun(module_id.qualified(spec_fun_id)); - } - let module_name = match module { - Some(m) => m, - _ => &self.parent.module_name, - } - .clone(); - let qsym = QualifiedSymbol { - module_name, - symbol: name, - }; - // If the spec function called is from a Move function, - // error if it is not pure. - if let Some(entry) = self.parent.parent.fun_table.get(&qsym) { - if !entry.is_pure { - if self.mode == ExpTranslationMode::TryImplAsSpec { - // The Move function is calling another impure Move function, - // so it should be considered impure. - if module_id.to_usize() < self.parent.module_id.to_usize() { - self.error(loc, "Move function calls impure Move function"); - return self.new_error_exp(); - } - } else { - let display = self.display_call_target(module, name); - let notes = vec![format!( - "impure function `{}`", - self.display_call_cand(module, name, cand), - )]; - self.env().error_with_notes( - loc, - &format!( - "calling impure function `{}` is not allowed", - display - ), - notes, - ); - return self.new_error_exp(); - } - } - } + // Record the usage of spec function in specs, used later + // in spec translator. + self.parent + .parent + .add_used_spec_fun(module_id.qualified(spec_fun_id)); self.called_spec_funs.insert((module_id, spec_fun_id)); } self.add_conversions(cand, &instantiation, &mut translated_args); @@ -3717,30 +3594,13 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo type_args: &Option>, args: &Spanned>, expected_type: &Type, - context: &ErrorMessageContext, + _context: &ErrorMessageContext, ) -> ExpData { let loc = &self.to_loc(&maccess.loc); if type_args.is_some() { self.error(loc, "macro invocation cannot have type arguments"); self.new_error_exp() } else if let EA::ModuleAccess_::Name(name) = &maccess.value { - let name_sym = self.symbol_pool().make(name.value.as_str()); - if self.mode == ExpTranslationMode::TryImplAsSpec - && name_sym == self.parent.parent.assert_symbol() - { - // In specification expressions, ignore assert! macro. The assert macro does not - // influence the semantics of the specification function. This allows us to - // interpret (some) implementation functions as spec functions. - // TODO: we should rework this in the process of integration spec/impl functions in - // one unique concept, with `FunctionKind::Spec` a new function kind. - let loc = self.to_loc(&maccess.loc); - let ty = self.check_type(&loc, &Type::unit(), expected_type, context); - return ExpData::Call( - self.new_node_id_with_type_loc(&ty, &self.to_loc(&maccess.loc)), - Operation::NoOp, - vec![], - ); - } let expansion = self .parent .parent diff --git a/third_party/move/move-model/src/builder/model_builder.rs b/third_party/move/move-model/src/builder/model_builder.rs index 61da370e162cf..f094028884639 100644 --- a/third_party/move/move-model/src/builder/model_builder.rs +++ b/third_party/move/move-model/src/builder/model_builder.rs @@ -55,8 +55,6 @@ pub(crate) struct ModelBuilder<'env> { pub fun_table: BTreeMap, /// A symbol table for constants. pub const_table: BTreeMap, - /// A call graph mapping callers to callees that are Move functions. - pub move_fun_call_graph: BTreeMap, BTreeSet>>, /// A list of intrinsic declarations pub intrinsics: Vec, /// A module lookup table from names to their ids. @@ -138,7 +136,6 @@ pub(crate) struct FunEntry { pub type_params: Vec, pub params: Vec, pub result_type: Type, - pub is_pure: bool, pub attributes: Vec, pub inline_specs: BTreeMap, } @@ -208,7 +205,6 @@ impl<'env> ModelBuilder<'env> { reverse_struct_table: BTreeMap::new(), fun_table: BTreeMap::new(), const_table: BTreeMap::new(), - move_fun_call_graph: BTreeMap::new(), intrinsics: Vec::new(), module_table: BTreeMap::new(), }; @@ -242,6 +238,15 @@ impl<'env> ModelBuilder<'env> { name: QualifiedSymbol, entry: SpecOrBuiltinFunEntry, ) { + if self.fun_table.contains_key(&name) { + self.env.error( + &entry.loc, + &format!( + "name clash between specification and Move function `{}`", + name.symbol.display(self.env.symbol_pool()) + ), + ); + } // TODO: check whether overloads are distinguishable self.spec_fun_table.entry(name).or_default().push(entry); } @@ -384,6 +389,13 @@ impl<'env> ModelBuilder<'env> { .unwrap_or_default() } + /// Looks up the abilities of a struct. + /// TODO(#12437): get rid of this once we have new UnificationContext + pub fn lookup_struct_abilities(&self, id: QualifiedId) -> AbilitySet { + let entry = self.lookup_struct_entry(id); + entry.abilities + } + /// Get all the structs which have been build so far. pub fn get_struct_ids(&self) -> impl Iterator> + '_ { self.struct_table @@ -507,11 +519,6 @@ impl<'env> ModelBuilder<'env> { self.env.symbol_pool().make("old") } - /// Returns the symbol for the builtin Move function `assert`. - pub fn assert_symbol(&self) -> Symbol { - self.env.symbol_pool().make("assert") - } - /// Returns the name for the pseudo builtin module. pub fn builtin_module(&self) -> ModuleName { ModuleName::new( @@ -523,34 +530,6 @@ impl<'env> ModelBuilder<'env> { /// Adds a spec function to used_spec_funs set. pub fn add_used_spec_fun(&mut self, qid: QualifiedId) { self.env.used_spec_funs.insert(qid); - self.propagate_move_fun_usage(qid); - } - - /// Adds an edge from the caller to the callee to the Move fun call graph. The callee is - /// is instantiated in dependency of the type parameters of the caller. - pub fn add_edge_to_move_fun_call_graph( - &mut self, - caller: QualifiedId, - callee: QualifiedId, - ) { - self.move_fun_call_graph - .entry(caller) - .or_default() - .insert(callee); - } - - /// Runs DFS to propagate the usage of Move functions from callers - /// to callees on the call graph. - pub fn propagate_move_fun_usage(&mut self, qid: QualifiedId) { - if let Some(neighbors) = self.move_fun_call_graph.get(&qid) { - neighbors.clone().iter().for_each(|n| { - if self.env.used_spec_funs.insert(*n) { - // If the callee's usage has not been recorded, recursively - // propagate the usage to the callee's callees, and so on. - self.propagate_move_fun_usage(*n); - } - }); - } } /// Pass model-level information to the global env diff --git a/third_party/move/move-model/src/builder/module_builder.rs b/third_party/move/move-model/src/builder/module_builder.rs index 97fe74286fe97..fd859c116ac18 100644 --- a/third_party/move/move-model/src/builder/module_builder.rs +++ b/third_party/move/move-model/src/builder/module_builder.rs @@ -5,9 +5,8 @@ use crate::{ ast::{ AccessSpecifier, Address, Attribute, AttributeValue, Condition, ConditionKind, Exp, - ExpData, FriendDecl, GlobalInvariant, ModuleName, Operation, PropertyBag, PropertyValue, - QualifiedSymbol, Spec, SpecBlockInfo, SpecBlockTarget, SpecFunDecl, SpecVarDecl, TempIndex, - UseDecl, Value, + ExpData, FriendDecl, ModuleName, Operation, PropertyBag, PropertyValue, QualifiedSymbol, + Spec, SpecBlockInfo, SpecBlockTarget, SpecFunDecl, SpecVarDecl, TempIndex, UseDecl, Value, }, builder::{ exp_builder::ExpTranslator, @@ -21,9 +20,8 @@ use crate::{ intrinsics::process_intrinsic_declaration, model::{ EqIgnoringLoc, FieldData, FieldId, FunId, FunctionData, FunctionKind, Loc, ModuleId, - MoveIrLoc, NamedConstantData, NamedConstantId, NodeId, Parameter, QualifiedId, - QualifiedInstId, SchemaId, SpecFunId, SpecVarId, StructData, StructId, TypeParameter, - TypeParameterKind, + MoveIrLoc, NamedConstantData, NamedConstantId, NodeId, Parameter, SchemaId, SpecFunId, + SpecVarId, StructData, StructId, TypeParameter, TypeParameterKind, }, options::ModelBuilderOptions, pragmas::{ @@ -45,7 +43,7 @@ use move_bytecode_source_map::source_map::SourceMap; use move_compiler::{ compiled_unit::{FunctionInfo, SpecInfo}, expansion::ast as EA, - parser::{ast as PA, ast::FunctionName}, + parser::ast as PA, shared::{unique_map::UniqueMap, Identifier, Name}, }; use move_ir_types::{ast::ConstantName, location::Spanned}; @@ -92,10 +90,6 @@ pub(crate) struct ModuleBuilder<'env, 'translator> { /// Let bindings for the current spec block, characterized by a boolean indicating whether /// post state is active and the node id of the original expression of the let. pub spec_block_lets: BTreeMap, - /// Whether during model building, we actually compile the full Move source. If this is not - /// set, we assume a compiled bytecode module as input. We still need the AST of the spec - /// language part. - pub compile_move: bool, } /// Represents information about a module already compiled into bytecode by the legacy @@ -144,11 +138,6 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { module_id: ModuleId, module_name: ModuleName, ) -> Self { - let compile_move = parent - .env - .get_extension::() - .map(|o| o.compile_via_model) - .unwrap_or_default(); Self { parent, module_id, @@ -166,7 +155,6 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { module_spec: Spec::default(), spec_block_infos: Default::default(), spec_block_lets: BTreeMap::new(), - compile_move, } } @@ -520,45 +508,9 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { type_params: type_params.clone(), params: params.clone(), result_type: result_type.clone(), - is_pure: false, attributes, inline_specs: def.specs.clone(), }); - - // Add function as a spec fun entry as well. - let spec_fun_id = SpecFunId::new(self.spec_funs.len()); - self.parent - .define_spec_or_builtin_fun(qsym, SpecOrBuiltinFunEntry { - loc: def_loc.clone(), - oper: Operation::SpecFunction(self.module_id, spec_fun_id, None), - type_params: type_params.clone(), - type_param_constraints: BTreeMap::default(), - params: params.clone(), - result_type: result_type.clone(), - visibility: EntryVisibility::Spec, - }); - - // Add $ to the name so the spec version does not name clash with the Move version. - let spec_fun_name = self.symbol_pool().make(&format!("${}", name.0.value)); - let mut fun_decl = SpecFunDecl { - loc: def_loc, - name: spec_fun_name, - type_params, - params, - context_params: None, - result_type, - used_memory: BTreeSet::new(), - uninterpreted: false, - is_move_fun: true, - is_native: false, - body: None, - callees: Default::default(), - is_recursive: Default::default(), - }; - if let EA::FunctionBody_::Native = def.body.value { - fun_decl.is_native = true; - } - self.spec_funs.push(fun_decl); } fn decl_ana_use_decl(&mut self, use_decl: &PA::UseDecl) { @@ -859,35 +811,6 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { self.def_ana_constant(&name, def, compiled_module); } - // Need to run def_ana_fun twice. - // In the first time we need to analyze all functions in the spec mode - // then we can check whether the function is pure or not - for (idx, (name, fun_def)) in module_def.functions.key_cloned_iter().enumerate() { - self.def_ana_fun(&name, fun_def, idx, true); - } - - // Propagate the impurity of functions: a Move function which calls an - // impure Move function is also considered impure. - let mut visited = BTreeMap::new(); - for (idx, (name, _)) in module_def.functions.key_cloned_iter().enumerate() { - let is_pure = self.propagate_function_impurity(&mut visited, SpecFunId::new(idx)); - if is_pure { - // Modify the types of parameters, return values and expressions - // of pure Move functions so they no longer have references. - self.deref_move_fun_types(name, idx); - } - self.parent - .fun_table - .entry(self.qualified_by_module_from_name(&name.0)) - .and_modify(|e| e.is_pure = is_pure); - } - - // Run def_ana_fun the second time in the move function mode - // Inline spec will be checked in this pass - for (idx, (name, fun_def)) in module_def.functions.key_cloned_iter().enumerate() { - self.def_ana_fun(&name, fun_def, idx, false); - } - // Analyze all schemas. This must be done before other things because schemas need to be // ready for inclusion. We also must do this recursively, so use a visited set to detect // cycles. @@ -917,6 +840,11 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { } } + // Analyze all function definitions. + for (name, fun_def) in module_def.functions.key_cloned_iter() { + self.def_ana_fun(&name, fun_def); + } + // TODO: we should re-visit this decision once we have high-order function ready on // the compiled bytecode (i.e., file format) level. Before that, the rule is: // - an inline function can have in-body spec blocks @@ -985,12 +913,6 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { self.def_ana_code_specs(module_def, compiled_module); } - // Perform post analyzes of state usage in spec functions. - self.compute_state_usage(); - - // Perform post reduction of module invariants. - self.process_module_invariants(); - // Apply tweaks after all specs are analyzed self.apply_tweaks(module_def); } @@ -1321,17 +1243,8 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { impl<'env, 'translator> ModuleBuilder<'env, 'translator> { /// Definition analysis for Move functions. - /// When as_spec_fun is true, the function is translated into a spec function. - /// When as_spec_fun is false, the function is translated as a move function. - /// If the function is pure, we translate its body. /// If we are operating as a Move compiler, we also translate its body. - fn def_ana_fun( - &mut self, - name: &PA::FunctionName, - def: &EA::Function, - fun_idx: usize, - as_spec_fun: bool, - ) { + fn def_ana_fun(&mut self, name: &PA::FunctionName, def: &EA::Function) { let body = &def.body; if let EA::FunctionBody_::Defined(seq) = &body.value { let full_name = self.qualified_by_module_from_name(&name.0); @@ -1345,173 +1258,31 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { let result_type = entry.result_type.clone(); let spec_block_map = entry.inline_specs.clone(); - let body_translator = |et: &mut ExpTranslator, as_spec_fun: bool| { - if as_spec_fun { - et.set_translate_fun_as_spec_fun() - } else { - et.set_translate_move_fun() - } - let loc = et.to_loc(&body.loc); - for (pos, TypeParameter(name, _, loc)) in type_params.iter().enumerate() { - et.define_type_param(loc, *name, Type::new_param(pos), false); - } - et.enter_scope(); - for (idx, Parameter(n, ty, loc)) in params.iter().enumerate() { - et.define_local(loc, *n, ty.clone(), None, Some(idx)); - } - let access_specifiers = if !as_spec_fun { - // Translate access specifiers - et.translate_access_specifiers(&def.access_specifiers) - } else { - None - }; - let mut result = - et.translate_seq(&loc, seq, &result_type, &ErrorMessageContext::Return); - et.finalize_types(); - result = et.post_process_body(result.into_exp()).into(); - (result, access_specifiers) - }; - - // Attempt to translate as specification function - if as_spec_fun { - let mut et = ExpTranslator::new(self); - let (translated, _) = body_translator(&mut et, true); - if !et.had_errors { - // Rewrite all type annotations in expressions to skip references. - for node_id in translated.node_ids() { - let ty = et.get_node_type(node_id); - et.update_node_type(node_id, ty.skip_reference().clone()); - } - et.called_spec_funs.iter().for_each(|(mid, fid)| { - self.parent.add_edge_to_move_fun_call_graph( - self.module_id.qualified(SpecFunId::new(fun_idx)), - mid.qualified(*fid), - ); - }); - self.spec_funs[self.spec_fun_index].body = Some(translated.into_exp()); - } - } else if self.compile_move { - // Also translate as regular Move function - let mut et = ExpTranslator::new(self); - et.set_spec_block_map(spec_block_map); - et.set_result_type(result_type.clone()); - et.set_fun_name(full_name.clone()); - let (translated, access_specifiers) = body_translator(&mut et, false); + let mut et = ExpTranslator::new(self); + et.set_spec_block_map(spec_block_map); + et.set_result_type(result_type.clone()); + et.set_fun_name(full_name.clone()); + et.set_translate_move_fun(); + let loc = et.to_loc(&body.loc); + for (pos, TypeParameter(name, _, loc)) in type_params.iter().enumerate() { + et.define_type_param(loc, *name, Type::new_param(pos), false); + } + et.enter_scope(); + for (idx, Parameter(n, ty, loc)) in params.iter().enumerate() { + et.define_local(loc, *n, ty.clone(), None, Some(idx)); + } + let access_specifiers = et.translate_access_specifiers(&def.access_specifiers); + let result = et.translate_seq(&loc, seq, &result_type, &ErrorMessageContext::Return); + et.finalize_types(); + let translated = et.post_process_body(result.into_exp()); + assert!(self.fun_defs.insert(full_name.symbol, translated).is_none()); + if let Some(specifiers) = access_specifiers { assert!(self - .fun_defs - .insert(full_name.symbol, translated.into_exp()) + .fun_access_specifiers + .insert(full_name.symbol, specifiers) .is_none()); - if let Some(specifiers) = access_specifiers { - assert!(self - .fun_access_specifiers - .insert(full_name.symbol, specifiers) - .is_none()); - } } } - if as_spec_fun { - self.spec_fun_index += 1; // TODO: why is this at the end? Document or move close to use - } - } - - /// Propagate the impurity of Move functions from callees to callers so - /// that we can detect pure-looking Move functions which calls impure - /// Move functions. - fn propagate_function_impurity( - &mut self, - visited: &mut BTreeMap, - spec_fun_id: SpecFunId, - ) -> bool { - if let Some(is_pure) = visited.get(&spec_fun_id) { - return *is_pure; - } - let spec_fun_idx = spec_fun_id.as_usize(); - let body = if self.spec_funs[spec_fun_idx].body.is_some() { - self.spec_funs[spec_fun_idx].body.take().unwrap() - } else { - // If the function is native and contains no mutable references - // as parameters, consider it pure. - // Otherwise the function is non-native, its body cannot be parsed - // so we consider it impure. - // TODO(emmazzz) right now all the native Move functions without - // parameters of type mutable references are considered pure. - // In the future we might want to only allow a certain subset of the - // native Move functions, through something similar to an allow list or - // a pragma. - let no_mut_ref_param = self.spec_funs[spec_fun_idx] - .params - .iter() - .map(|Parameter(_, ty, _)| !ty.is_mutable_reference()) - .all(|b| b); // `no_mut_ref_param` if none of the types are mut refs. - return self.spec_funs[spec_fun_idx].is_native && no_mut_ref_param; - }; - let mut is_pure = true; - body.visit_pre_order(&mut |e: &ExpData| { - if let ExpData::Call(_, Operation::SpecFunction(mid, fid, _), _) = e { - if mid.to_usize() < self.module_id.to_usize() { - // This is calling a function from another module we already have - // translated. In this case, the impurity has already been propagated - // in translate_call. - true - } else { - // This is calling a function from the module we are currently translating. - // Need to recursively ensure we have propagated impurity because of - // arbitrary call graphs, including cyclic. - if !self.propagate_function_impurity(visited, *fid) { - is_pure = false; - false // Short-circuit the visit; this function is not pure - } else { - true - } - } - } else { - true - } - }); - if is_pure { - // Restore the function body if the Move function is pure. - self.spec_funs[spec_fun_idx].body = Some(body); - } - visited.insert(spec_fun_id, is_pure); - is_pure - } - - fn deref_move_fun_types(&mut self, name: FunctionName, spec_fun_idx: usize) { - if let Some(entry) = self - .parent - .spec_fun_table - .get_mut(&self.qualified_by_module_from_name(&name.0)) - { - if entry.len() != 1 { - let error_msg = if entry.is_empty() { - "missing" - } else { - "duplicate" - }; - self.parent.error( - &self.parent.to_loc(&name.loc()), - &format!("{} declaration of `{}`", error_msg, name.value()), - ); - } else { - let e = &mut entry[0]; - e.params = e - .params - .iter() - .map(|Parameter(n, ty, loc)| { - Parameter(*n, ty.skip_reference().clone(), loc.clone()) - }) - .collect_vec(); - e.result_type = e.result_type.skip_reference().clone(); - } - }; - - let spec_fun_decl = &mut self.spec_funs[spec_fun_idx]; - spec_fun_decl.params = spec_fun_decl - .params - .iter() - .map(|Parameter(s, ty, loc)| Parameter(*s, ty.skip_reference().clone(), loc.clone())) - .collect_vec(); - spec_fun_decl.result_type = spec_fun_decl.result_type.skip_reference().clone(); } } @@ -2320,6 +2091,11 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { }, }; et.finalize_types(); + let translated = et.post_process_body(translated); + let translated_additional = translated_additional + .into_iter() + .map(|e| et.post_process_body(e)) + .collect(); self.add_conditions_to_context( context, loc, @@ -3397,168 +3173,6 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { } } -/// ## Spec Var Usage Analysis - -impl<'env, 'translator> ModuleBuilder<'env, 'translator> { - /// Compute state usage of spec funs. - fn compute_state_usage(&mut self) { - let mut visited = BTreeSet::new(); - for idx in 0..self.spec_funs.len() { - self.compute_state_usage_and_callees_for_fun(&mut visited, idx); - } - // Check for purity requirements. All data invariants must be pure expressions and - // not depend on global state. - let check_uses_no_memory = |mid: ModuleId, fid: SpecFunId| { - if mid.to_usize() < self.parent.env.get_module_count() { - // This is calling a function from another module we already have - // translated. - let module_env = self.parent.env.get_module(mid); - let fun_decl = module_env.get_spec_fun(fid); - fun_decl.used_memory.is_empty() - } else { - // This is calling a function from the module we are currently translating. - let fun_decl = &self.spec_funs[fid.as_usize()]; - fun_decl.used_memory.is_empty() - } - }; - - for struct_spec in self.struct_specs.values() { - for cond in &struct_spec.conditions { - if matches!(cond.kind, ConditionKind::StructInvariant) - && !cond.exp.uses_no_memory(&check_uses_no_memory) - { - self.parent.error( - &cond.loc, - "data invariants cannot depend on global state \ - (directly or indirectly uses a global spec var or resource storage).", - ); - } - } - } - } - - /// Compute state usage for a given spec fun, defined via its index into the spec_funs - /// vector of the currently translated module. This recursively computes the values for - /// functions called from this one; the visited set is there to break cycles. - fn compute_state_usage_and_callees_for_fun( - &mut self, - visited: &mut BTreeSet, - fun_idx: usize, - ) { - if !visited.insert(fun_idx) { - return; - } - - // Detach the current SpecFunDecl body so we can traverse it while at the same time mutating - // the full self. Rust requires us to do so (at least the author doesn't know better yet), - // but moving it should be not too expensive. - let body = if self.spec_funs[fun_idx].body.is_some() { - self.spec_funs[fun_idx].body.take().unwrap() - } else { - // No body: assume it is pure. - return; - }; - - let (used_memory, callees) = - self.compute_state_usage_and_callees_for_exp(Some(visited), &body); - let fun_decl = &mut self.spec_funs[fun_idx]; - fun_decl.body = Some(body); - fun_decl.used_memory = used_memory; - fun_decl.callees = callees; - } - - /// Computes state usage and called functions for an expression. If the visited_opt is - /// available, this recurses to compute the usage for any functions called. Otherwise - /// it assumes this information is already computed. - fn compute_state_usage_and_callees_for_exp( - &mut self, - mut visited_opt: Option<&mut BTreeSet>, - exp: &ExpData, - ) -> ( - BTreeSet>, - BTreeSet>, - ) { - let mut used_memory = BTreeSet::new(); - let mut callees = BTreeSet::new(); - exp.visit_post_order(&mut |e: &ExpData| { - match e { - ExpData::Call(id, Operation::SpecFunction(mid, fid, _), _) => { - callees.insert(mid.qualified(*fid)); - let inst = self.parent.env.get_node_instantiation(*id); - // Extend used memory with that of called functions, after applying type - // instantiation of this call. - if mid.to_usize() < self.parent.env.get_module_count() { - // This is calling a function from another module we already have - // translated. - let module_env = self.parent.env.get_module(*mid); - let fun_decl = module_env.get_spec_fun(*fid); - used_memory.extend( - fun_decl - .used_memory - .iter() - .map(|id| id.instantiate_ref(&inst)), - ); - } else { - // This is calling a function from the module we are currently translating. - // Need to recursively ensure we have computed used_spec_vars because of - // arbitrary call graphs, including cyclic. If visted_opt is not set, - // we know we already computed this. - if let Some(visited) = &mut visited_opt { - self.compute_state_usage_and_callees_for_fun(visited, fid.as_usize()); - } - let fun_decl = &self.spec_funs[fid.as_usize()]; - used_memory.extend( - fun_decl - .used_memory - .iter() - .map(|id| id.instantiate_ref(&inst)), - ); - } - }, - ExpData::Call(node_id, Operation::Global(_), _) - | ExpData::Call(node_id, Operation::Exists(_), _) => { - if !self.parent.env.has_errors() { - let ty = &self.parent.env.get_node_instantiation(*node_id)[0]; - if let Type::Struct(mid, sid, inst) = ty { - used_memory.insert(mid.qualified_inst(*sid, inst.to_owned())); - } - } - }, - _ => {}, - } - true // continue visit, note all problematic subexprs - }); - (used_memory, callees) - } -} - -/// ## Module Invariants - -impl<'env, 'translator> ModuleBuilder<'env, 'translator> { - /// Process module invariants, attaching them to the global env. - fn process_module_invariants(&mut self) { - for cond in self.module_spec.conditions.iter().cloned().collect_vec() { - if matches!( - cond.kind, - ConditionKind::GlobalInvariant(..) | ConditionKind::GlobalInvariantUpdate(..) - ) { - let (mem_usage, _) = self.compute_state_usage_and_callees_for_exp(None, &cond.exp); - let id = self.parent.env.new_global_id(); - let Condition { loc, exp, .. } = cond; - self.parent.env.add_global_invariant(GlobalInvariant { - id, - loc, - kind: cond.kind, - mem_usage, - declaring_module: self.module_id, - cond: exp, - properties: cond.properties.clone(), - }); - } - } - } -} - /// # Spec Block Infos impl<'env, 'translator> ModuleBuilder<'env, 'translator> { @@ -3574,7 +3188,7 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { .map(|m| self.parent.to_loc(&m.loc)) .collect_vec(); let target = match self.get_spec_block_context(&block.value.target) { - Some(SpecBlockContext::Module) => SpecBlockTarget::Module, + Some(SpecBlockContext::Module) => SpecBlockTarget::Module(self.module_id), Some(SpecBlockContext::Function(qsym)) => { SpecBlockTarget::Function(self.module_id, FunId::new(qsym.symbol)) }, @@ -3605,7 +3219,7 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { }, None => { // This has been reported as an error. Choose a dummy target. - SpecBlockTarget::Module + SpecBlockTarget::Inline }, }; self.spec_block_infos.push(SpecBlockInfo { @@ -3741,7 +3355,7 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { abilities: entry.abilities, spec_var_opt: None, field_data, - spec, + spec: RefCell::new(spec), }; struct_data.insert(StructId::new(name.symbol), data); } @@ -3760,6 +3374,7 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { // New function let spec = self.fun_specs.remove(&name.symbol).unwrap_or_default(); let def = self.fun_defs.remove(&name.symbol); + let called_funs = Some(def.as_ref().map(|e| e.called_funs()).unwrap_or_default()); let access_specifiers = self.fun_access_specifiers.remove(&name.symbol); let data = FunctionData { name: name.symbol, @@ -3777,7 +3392,7 @@ impl<'env, 'translator> ModuleBuilder<'env, 'translator> { access_specifiers, spec: spec.into(), def, - called_funs: None, + called_funs, calling_funs: RefCell::default(), transitive_closure_of_called_funs: RefCell::default(), }; diff --git a/third_party/move/move-model/src/exp_rewriter.rs b/third_party/move/move-model/src/exp_rewriter.rs index fb686c1b0d9e8..9c7c5c417dc8e 100644 --- a/third_party/move/move-model/src/exp_rewriter.rs +++ b/third_party/move/move-model/src/exp_rewriter.rs @@ -3,7 +3,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - ast::{Condition, Exp, ExpData, MemoryLabel, Operation, Pattern, Spec, TempIndex, Value}, + ast::{ + Condition, Exp, ExpData, MemoryLabel, Operation, Pattern, Spec, SpecBlockTarget, TempIndex, + Value, + }, model::{GlobalEnv, ModuleId, NodeId, SpecVarId}, symbol::Symbol, ty::Type, @@ -248,7 +251,14 @@ pub trait ExpRewriterFunctions { fn rewrite_sequence(&mut self, id: NodeId, seq: &[Exp]) -> Option { None } - fn rewrite_spec(&mut self, id: NodeId, spec: &Spec) -> Option { + fn rewrite_spec(&mut self, target: &SpecBlockTarget, spec: &Spec) -> Option { + None + } + fn rewrite_condition( + &mut self, + target: &SpecBlockTarget, + cond: &Condition, + ) -> Option { None } // Might only be useful with V1-compiled code @@ -512,7 +522,8 @@ pub trait ExpRewriterFunctions { }, SpecBlock(id, spec) => { let (id_changed, new_id) = self.internal_rewrite_id(*id); - let (spec_changed, new_spec) = self.internal_rewrite_spec(new_id, spec.clone()); + let (spec_changed, new_spec) = + self.rewrite_spec_descent(&SpecBlockTarget::Inline, spec); if id_changed || spec_changed { SpecBlock(new_id, new_spec).into_exp() } else { @@ -656,24 +667,77 @@ pub trait ExpRewriterFunctions { } } - fn internal_rewrite_spec(&mut self, id: NodeId, spec: Spec) -> (bool, Spec) { - let (conditions_changed, new_conditions) = - self.internal_rewrite_spec_conditions(spec.conditions); - let (on_impl_changed, new_on_impl) = self.internal_rewrite_spec_on_impl(spec.on_impl); - let (update_map_changed, new_update_map) = self.rewrite_spec_update_map(spec.update_map); - let newspec = Spec { - conditions: new_conditions, - on_impl: new_on_impl, - update_map: new_update_map, - ..spec + fn rewrite_spec_descent(&mut self, target: &SpecBlockTarget, spec: &Spec) -> (bool, Spec) { + let mut changed = false; + let mut conditions = vec![]; + + // First go over all top-level conditions in this block. + for cond in &spec.conditions { + let (this_changed, new_cond) = self.internal_rewrite_condition(target, cond); + conditions.push(new_cond); + changed |= this_changed; + } + let mut update_map = BTreeMap::new(); + for (node_id, cond) in &spec.update_map { + let (this_changed, new_cond) = self.internal_rewrite_condition(target, cond); + update_map.insert(*node_id, new_cond); + changed |= this_changed + } + + // Next go over any sub-blocks for implementation + let mut on_impl = BTreeMap::new(); + for (code_offs, impl_spec) in &spec.on_impl { + // We expect the target to be a function if implementation specs are present + let SpecBlockTarget::Function(mid, fid) = target else { + panic!("expected function target") + }; + let (this_changed, new_spec) = self.rewrite_spec_descent( + &SpecBlockTarget::FunctionCode(*mid, *fid, *code_offs as usize), + impl_spec, + ); + on_impl.insert(*code_offs, new_spec); + changed |= this_changed + } + + let new_spec = Spec { + loc: spec.loc.clone(), + conditions, + properties: spec.properties.clone(), + on_impl, + update_map, }; - if let Some(newer_spec) = self.rewrite_spec(id, &newspec) { - (true, newer_spec) + + if let Some(new_spec) = self.rewrite_spec(target, &new_spec) { + (true, new_spec) } else { - ( - conditions_changed || on_impl_changed || update_map_changed, - newspec, - ) + (changed, new_spec) + } + } + + fn internal_rewrite_condition( + &mut self, + target: &SpecBlockTarget, + cond: &Condition, + ) -> (bool, Condition) { + let (mut changed, exp) = self.internal_rewrite_exp(&cond.exp); + let additional_exps = + if let Some(additional_exps) = self.internal_rewrite_vec(&cond.additional_exps) { + changed = true; + additional_exps + } else { + cond.additional_exps.clone() + }; + let cond = Condition { + loc: cond.loc.clone(), + kind: cond.kind.clone(), + properties: cond.properties.clone(), + exp, + additional_exps, + }; + if let Some(new_cond) = self.rewrite_condition(target, &cond) { + (true, new_cond) + } else { + (changed, cond) } } diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index fbca4039901dc..4f81c5285cdbc 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -56,6 +56,7 @@ pub mod intrinsics; pub mod model; pub mod options; pub mod pragmas; +pub mod pureness_checker; pub mod spec_translator; pub mod symbol; pub mod ty; @@ -387,18 +388,6 @@ fn run_move_checker(env: &mut GlobalEnv, program: E::Program) { } // Perform any remaining friend-declaration checks and update friend module id information. check_and_update_friend_info(builder); - // Compute information derived from AST (currently callgraph) - for module in env.module_data.iter_mut() { - for fun_data in module.function_data.values_mut() { - fun_data.called_funs = Some( - fun_data - .def - .as_ref() - .map(|e| e.called_funs()) - .unwrap_or_default(), - ) - } - } } /// Checks if any friend declarations are invalid because: diff --git a/third_party/move/move-model/src/model.rs b/third_party/move/move-model/src/model.rs index 961186f5ef1c9..3a4fcbeb238f0 100644 --- a/third_party/move/move-model/src/model.rs +++ b/third_party/move/move-model/src/model.rs @@ -19,7 +19,7 @@ use crate::{ ast::{ AccessSpecifier, Address, AddressSpecifier, Attribute, ConditionKind, Exp, ExpData, FriendDecl, GlobalInvariant, ModuleName, PropertyBag, PropertyValue, ResourceSpecifier, - Spec, SpecBlockInfo, SpecFunDecl, SpecVarDecl, UseDecl, Value, + Spec, SpecBlockInfo, SpecBlockTarget, SpecFunDecl, SpecVarDecl, UseDecl, Value, }, code_writer::CodeWriter, emit, emitln, @@ -1255,6 +1255,11 @@ impl GlobalEnv { self.used_spec_funs.contains(&id) } + /// Marks a spec fun to be used + pub fn add_used_spec_fun(&mut self, id: QualifiedId) { + self.used_spec_funs.insert(id); + } + /// Determines whether the given spec fun is recursive. pub fn is_spec_fun_recursive(&self, id: QualifiedId) -> bool { fn is_caller( @@ -1268,11 +1273,10 @@ impl GlobalEnv { } let module = env.get_module(caller.module_id); let decl = module.get_spec_fun(caller.id); - decl.callees.contains(&fun) - || decl - .callees - .iter() - .any(|trans_caller| is_caller(env, visited, *trans_caller, fun)) + decl.callees.iter().any(|c| c.to_qualified_id() == fun) + || decl.callees.iter().any(|trans_caller| { + is_caller(env, visited, trans_caller.to_qualified_id(), fun) + }) } let module = self.get_module(id.module_id); let is_recursive = *module.get_spec_fun(id.id).is_recursive.borrow(); @@ -1366,7 +1370,7 @@ impl GlobalEnv { function_idx_to_id: Default::default(), spec_vars, spec_funs, - module_spec, + module_spec: RefCell::new(module_spec), loc, attributes, use_decls, @@ -1452,7 +1456,6 @@ impl GlobalEnv { panic!("attaching mismatching bytecode module") } } - let used_modules = self.get_used_modules_from_bytecode(&module); let friend_modules = self.get_friend_modules_from_bytecode(&module); let mod_data = &mut self.module_data[module_id.0 as usize]; @@ -1492,6 +1495,7 @@ impl GlobalEnv { called_funs } + #[allow(unused)] fn get_used_modules_from_bytecode( &self, compiled_module: &CompiledModule, @@ -1505,6 +1509,7 @@ impl GlobalEnv { .collect() } + #[allow(unused)] fn get_friend_modules_from_bytecode( &self, compiled_module: &CompiledModule, @@ -1554,7 +1559,7 @@ impl GlobalEnv { abilities: AbilitySet::ALL, spec_var_opt: Some(var_id), field_data, - spec: Spec::default(), + spec: RefCell::new(Spec::default()), } } @@ -1717,6 +1722,94 @@ impl GlobalEnv { .is_none()) } + /// Returns a reference to the declaration of a spec fun. + pub fn get_spec_fun(&self, fun: QualifiedId) -> &SpecFunDecl { + self.module_data + .get(fun.module_id.to_usize()) + .unwrap() + .spec_funs + .get(&fun.id) + .unwrap() + } + + /// Returns a mutable reference to the declaration of a spec fun. + pub fn get_spec_fun_mut(&mut self, fun: QualifiedId) -> &mut SpecFunDecl { + self.module_data + .get_mut(fun.module_id.to_usize()) + .unwrap() + .spec_funs + .get_mut(&fun.id) + .unwrap() + } + + /// Adds a new specification function and returns id of it. + pub fn add_spec_function_def( + &mut self, + module_id: ModuleId, + decl: SpecFunDecl, + ) -> QualifiedId { + let spec_funs = &mut self + .module_data + .get_mut(module_id.to_usize()) + .unwrap() + .spec_funs; + let id = SpecFunId::new(spec_funs.len()); + assert!(spec_funs.insert(id, decl).is_none()); + module_id.qualified(id) + } + + /// Gets the spec block associated with the spec block target. Only + /// module, struct, and function specs are supported. + pub fn get_spec_block(&self, target: &SpecBlockTarget) -> Ref { + use SpecBlockTarget::*; + match target { + Module(mid) => self.module_data[mid.to_usize()].module_spec.borrow(), + Struct(mid, sid) => self.module_data[mid.to_usize()] + .struct_data + .get(sid) + .unwrap() + .spec + .borrow(), + Function(mid, fid) => self.module_data[mid.to_usize()] + .function_data + .get(fid) + .unwrap() + .spec + .borrow(), + FunctionCode(..) | Schema(_, _, _) | Inline => { + // Schemas are expanded, inline spec blocks are part of the AST, + // and function code is nested inside of a function spec block + panic!("spec not available for schema or inline blocks") + }, + } + } + + /// Gets the spec block associated with the spec block target. Only + /// module, struct, and function specs are supported. + pub fn get_spec_block_mut(&self, target: &SpecBlockTarget) -> RefMut { + use SpecBlockTarget::*; + match target { + Module(mid) => self.module_data[mid.to_usize()].module_spec.borrow_mut(), + Struct(mid, sid) => self.module_data[mid.to_usize()] + .struct_data + .get(sid) + .unwrap() + .spec + .borrow_mut(), + Function(mid, fid) => self.module_data[mid.to_usize()] + .function_data + .get(fid) + .unwrap() + .spec + .borrow_mut(), + FunctionCode(..) | Schema(_, _, _) | Inline => { + // Schemas are expanded, inline spec blocks are part of the AST, + // and function code is nested inside of a function spec block + panic!("spec not available for schema or inline blocks") + }, + } + } + /// Return the `StructEnv` for `str` pub fn get_struct(&self, str: QualifiedId) -> StructEnv<'_> { self.get_module(str.module_id).into_struct(str.id) @@ -2003,7 +2096,7 @@ impl GlobalEnv { .unwrap_or_else(|_| { panic!("Expect one and only one module for {:?}", mid); }); - module_data.module_spec = spec; + *module_data.module_spec.borrow_mut() = spec; } /// Override the specification for a given function @@ -2083,16 +2176,16 @@ impl GlobalEnv { let module_id = module_data.id; module_data .function_data - .retain(|fun_id, _| !predicate(&module_id.qualified(*fun_id))); + .retain(|fun_id, _| predicate(&module_id.qualified(*fun_id))); module_data .function_idx_to_id - .retain(|_, fun_id| !predicate(&module_id.qualified(*fun_id))); + .retain(|_, fun_id| predicate(&module_id.qualified(*fun_id))); module_data.function_data.values_mut().for_each(|fun_data| { if let Some(called_funs) = fun_data.called_funs.as_mut() { - called_funs.retain(|qfun_id| !predicate(qfun_id)) + called_funs.retain(|qfun_id| predicate(qfun_id)) } if let Some(calling_funs) = &mut *fun_data.calling_funs.borrow_mut() { - calling_funs.retain(|qfun_id| !predicate(qfun_id)) + calling_funs.retain(|qfun_id| predicate(qfun_id)) } }); } @@ -2107,11 +2200,19 @@ impl Default for GlobalEnv { impl GlobalEnv { pub fn dump_env(&self) -> String { + self.internal_dump_env(false) + } + + pub fn dump_env_all(&self) -> String { + self.internal_dump_env(true) + } + + pub fn internal_dump_env(&self, all: bool) -> String { let spool = self.symbol_pool(); let tctx = &self.get_type_display_ctx(); let writer = CodeWriter::new(self.internal_loc()); for module in self.get_modules() { - if !module.is_target() { + if !all && !module.is_target() { continue; } emitln!(writer, "module {} {{", module.get_full_name_str()); @@ -2157,6 +2258,10 @@ impl GlobalEnv { }, ) } + let module_spec = module.get_spec(); + if !module_spec.is_empty() { + emitln!(writer, "{}", self.display(&*module_spec)); + } for str in module.get_structs() { emitln!(writer, "struct {} {{", str.get_name().display(spool)); writer.indent(); @@ -2171,8 +2276,8 @@ impl GlobalEnv { writer.unindent(); emitln!(writer, "}"); let spec = str.get_spec(); - if !spec.conditions.is_empty() { - emitln!(writer, "{}", self.display(spec)) + if !spec.is_empty() { + emitln!(writer, "{}", self.display(&*spec)) } } for fun in module.get_functions() { @@ -2269,7 +2374,7 @@ impl GlobalEnv { emitln!(writer, ";"); } let spec = fun.get_spec(); - if !spec.conditions.is_empty() { + if !spec.is_empty() { emitln!(writer, "{}", self.display(&*spec)) } } @@ -2357,7 +2462,7 @@ pub struct ModuleData { pub(crate) spec_funs: BTreeMap, /// Module level specification. - pub(crate) module_spec: Spec, + pub(crate) module_spec: RefCell, /// The location of this module. pub(crate) loc: Loc, @@ -2519,9 +2624,9 @@ impl<'env> ModuleEnv<'env> { add_usage_of_exp(usage, &cond.exp); } }; - add_usage_of_spec(&mut usage, self.get_spec()); + add_usage_of_spec(&mut usage, &self.get_spec()); for struct_env in self.get_structs() { - add_usage_of_spec(&mut usage, struct_env.get_spec()) + add_usage_of_spec(&mut usage, &struct_env.get_spec()) } for func_env in self.get_functions() { add_usage_of_spec(&mut usage, &func_env.get_spec()) @@ -2926,8 +3031,8 @@ impl<'env> ModuleEnv<'env> { } /// Gets module specification. - pub fn get_spec(&self) -> &Spec { - &self.data.module_spec + pub fn get_spec(&self) -> Ref { + self.data.module_spec.borrow() } /// Returns whether a spec fun is ever called or not. @@ -3057,7 +3162,7 @@ pub struct StructData { pub(crate) field_data: BTreeMap, /// Associated specification. - pub(crate) spec: Spec, + pub(crate) spec: RefCell, } #[derive(Debug, Clone)] @@ -3077,11 +3182,22 @@ impl<'env> StructEnv<'env> { /// Gets full name as string. pub fn get_full_name_str(&self) -> String { - format!( - "{}::{}", - self.module_env.get_name().display(self.module_env.env), - self.get_name().display(self.symbol_pool()) - ) + let module_name = self.module_env.get_name().display(self.module_env.env); + if self.is_ghost_memory() { + let spec_var = self.get_ghost_memory_spec_var().expect("spec var"); + let spec_var_name = self.module_env.get_spec_var(spec_var.id); + format!( + "{}::{}", + module_name, + spec_var_name.name.display(self.symbol_pool()) + ) + } else { + format!( + "{}::{}", + module_name, + self.get_name().display(self.symbol_pool()) + ) + } } /// Gets full name with module address as string. @@ -3140,8 +3256,8 @@ impl<'env> StructEnv<'env> { } /// Returns properties from pragmas. - pub fn get_properties(&self) -> &PropertyBag { - &self.data.spec.properties + pub fn get_properties(&self) -> PropertyBag { + self.data.spec.borrow().properties.clone() } /// Gets the id associated with this struct. @@ -3260,12 +3376,12 @@ impl<'env> StructEnv<'env> { /// Returns true if this struct has specification conditions. pub fn has_conditions(&self) -> bool { - !self.data.spec.conditions.is_empty() + !self.data.spec.borrow().conditions.is_empty() } /// Returns the data invariants associated with this struct. - pub fn get_spec(&'env self) -> &'env Spec { - &self.data.spec + pub fn get_spec(&self) -> Ref { + self.data.spec.borrow() } /// Returns the value of a boolean pragma for this struct. This first looks up a @@ -4210,12 +4326,11 @@ impl<'env> FunctionEnv<'env> { } /// Get the transitive closure of the called functions. This requires that all functions - /// in the closure have `get_called_functions` available; if one of them not, None is returned. - pub fn get_transitive_closure_of_called_functions( - &self, - ) -> Option>> { + /// in the closure have `get_called_functions` available; if one of them not, this + /// function panics. + pub fn get_transitive_closure_of_called_functions(&self) -> BTreeSet> { if let Some(trans_called) = &*self.data.transitive_closure_of_called_funs.borrow() { - return Some(trans_called.clone()); + return trans_called.clone(); } let mut set = BTreeSet::new(); @@ -4225,21 +4340,16 @@ impl<'env> FunctionEnv<'env> { // BFS in reachable_funcs to collect all reachable functions while !reachable_funcs.is_empty() { let fnc = reachable_funcs.pop_front().unwrap(); - if let Some(callees) = fnc.get_called_functions() { - for callee in callees { - let f = self.module_env.env.get_function(*callee); - let qualified_id = f.get_qualified_id(); - if !set.contains(&qualified_id) { - set.insert(qualified_id); - reachable_funcs.push_back(f.clone()); - } + for callee in fnc.get_called_functions().expect("call info available") { + let f = self.module_env.env.get_function(*callee); + let qualified_id = f.get_qualified_id(); + if set.insert(qualified_id) { + reachable_funcs.push_back(f.clone()); } - } else { - return None; } } *self.data.transitive_closure_of_called_funs.borrow_mut() = Some(set.clone()); - Some(set) + set } /// Returns the function name excluding the address and the module name diff --git a/third_party/move/move-model/src/pureness_checker.rs b/third_party/move/move-model/src/pureness_checker.rs new file mode 100644 index 0000000000000..402090f9da8fc --- /dev/null +++ b/third_party/move/move-model/src/pureness_checker.rs @@ -0,0 +1,179 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! Checks pureness (absence of side-effects) of expressions. +//! An expression is pure if +//! +//! - It does not use borrow_global_mut or `&mut e`. +//! - It does not use Mutate +//! - It does not call another impure function. +//! +//! In specification checking mode, in addition the following constructs are disallowed +//! +//! - No use of Assign +//! - Not use of Return +//! - No use of uninitialized let bindings +//! +//! The checker does a DFS search to figure whether transitive call chains are pure or not. + +use crate::{ + ast::{Exp, ExpData, Operation, Spec}, + model::{FunId, GlobalEnv, NodeId, Parameter, QualifiedId}, + ty::ReferenceKind, +}; +use std::{collections::BTreeMap, mem}; + +#[derive(Debug, PartialEq, Eq)] +pub enum FunctionPurenessCheckerMode { + /// General checking mode, determining semantic impureness + General, + /// In addition to the general rules, specification specific rules + Specification, +} + +/// Pureness checker for expressions. +#[derive(Debug)] +pub struct FunctionPurenessChecker +where + F: FnMut(NodeId, &str, &[(QualifiedId, NodeId)]), +{ + /// The checking mode + mode: FunctionPurenessCheckerMode, + /// An action which is invoked if impurity is detected. The first argument is + /// the node where the issue was found, the 2nd a message explaining the issue, + /// and the 3rd a stack of calls to functions which are currently analyzed, with + /// the first element in the vector the most outer call. + impure_action: F, + /// Map from functions to their known pureness status + pureness: BTreeMap, bool>, + /// Stack of functions currently visiting + visiting: Vec<(QualifiedId, NodeId)>, + /// Whether the expression visited so far is impure + is_impure: bool, +} + +impl FunctionPurenessChecker +where + F: FnMut(NodeId, &str, &[(QualifiedId, NodeId)]), +{ + /// Creates a new checker. The given function is invoke with diagnostic information + /// if impurity is detected. It is up to this function whether an actual error is + /// reported. + pub fn new(mode: FunctionPurenessCheckerMode, impure_action: F) -> Self { + Self { + mode, + impure_action, + pureness: BTreeMap::default(), + visiting: vec![], + is_impure: false, + } + } + + /// Consumes the checker and returns a map from qualified function + /// names to a boolean indicating whether they are pure (= true). + pub fn into_map(self) -> BTreeMap, bool> { + self.pureness + } + + /// Checks whether the given expression is pure and returns true if so. + pub fn check_exp(&mut self, env: &GlobalEnv, exp: &Exp) -> bool { + // Reset before start of traversal + self.is_impure = false; + exp.visit_post_order(&mut |e| { + use ExpData::*; + use Operation::*; + match e { + Assign(id, ..) if self.mode == FunctionPurenessCheckerMode::Specification => { + (self.impure_action)(*id, "assigns variable", &self.visiting); + self.is_impure = true + }, + Mutate(id, ..) => { + (self.impure_action)(*id, "mutates reference", &self.visiting); + self.is_impure = true; + }, + Return(id, ..) if self.mode == FunctionPurenessCheckerMode::Specification => { + (self.impure_action)( + *id, + "return not allowed in specifications", + &self.visiting, + ); + }, + Block(id, _, None, _) + if self.mode == FunctionPurenessCheckerMode::Specification => + { + (self.impure_action)( + *id, + "uninitialized let not allowed in specifications", + &self.visiting, + ); + }, + Call(id, Borrow(ReferenceKind::Mutable), ..) => { + (self.impure_action)(*id, "mutably borrows value", &self.visiting); + self.is_impure = true; + }, + Call(id, BorrowGlobal(ReferenceKind::Mutable), ..) => { + (self.impure_action)( + *id, + "mutably borrows from global storage", + &self.visiting, + ); + self.is_impure = true; + }, + Call(id, MoveFunction(mid, sid), ..) => { + let qid = mid.qualified(*sid); + // false positive: can't use entry because of borrow conflict + #[allow(clippy::map_entry)] + if !self.pureness.contains_key(&qid) { + self.visiting.push((qid, *id)); + let old_impure = mem::take(&mut self.is_impure); + self.check_function(env, qid); + self.pureness.insert(qid, !self.is_impure); + self.visiting.pop(); + self.is_impure |= old_impure; + } + if !self.pureness.get(&qid).unwrap() { + (self.impure_action)( + *id, + "calls a function which modifies state", + &self.visiting, + ); + self.is_impure = true + } + }, + _ => {}, + } + // Stop traversal if we have shown the expression is impure + !self.is_impure + }); + !self.is_impure + } + + /// Checks all the expressions in a spec block. + pub fn check_spec(&mut self, env: &GlobalEnv, spec: &Spec) { + // We map this to checking an expression, leveraging the existing + // SpecBlock visitor logic. + let spec_exp = ExpData::SpecBlock(env.new_node_id(), spec.clone()); + self.check_exp(env, &spec_exp.into_exp()); + } + + fn check_function(&mut self, env: &GlobalEnv, qid: QualifiedId) { + let fun = env.get_function(qid); + if let Some(def) = fun.get_def() { + // For breaking cycles, assume initially function is pure + self.pureness.insert(qid, true); + // Continue recursively + self.check_exp(env, def); + } else { + // We consider a native as pure if it does not take or deliver a mutable reference. + self.is_impure = fun + .get_parameters() + .iter() + .any(|Parameter(_, ty, _)| ty.is_mutable_reference()) + || fun + .get_result_type() + .flatten() + .iter() + .any(|ty| ty.is_mutable_reference()); + } + } +} diff --git a/third_party/move/move-model/src/ty.rs b/third_party/move/move-model/src/ty.rs index cd9d81e45bc64..1004e1ab8582c 100644 --- a/third_party/move/move-model/src/ty.rs +++ b/third_party/move/move-model/src/ty.rs @@ -119,6 +119,8 @@ pub enum Constraint { /// The type variable must be instantiated with a struct which has the given fields with /// types. SomeStruct(BTreeMap), + /// The type variable must be instantiated with a type which has the given ability + HasAbility(Ability), /// The type variable defaults to the given type if no other binding is found. This is /// a pseudo constraint which never fails, but used to generate a default for /// inference. @@ -149,7 +151,7 @@ impl Constraint { } /// Joins the two constraints. If they are incompatible, produces a type unification error. - /// Otherwise returns true if `self` absorbs the `other` constraint (and waives the `other`). + /// Otherwise, returns true if `self` absorbs the `other` constraint (and waives the `other`). pub fn join( &mut self, context: &impl UnificationContext, @@ -190,6 +192,7 @@ impl Constraint { } Ok(true) }, + (Constraint::HasAbility(_), _) | (_, Constraint::HasAbility(_)) => Ok(false), (Constraint::WithDefault(_), _) | (_, Constraint::WithDefault(_)) => Ok(false), (_, _) => Err(TypeUnificationError::ConstraintsIncompatible( loc.clone(), @@ -226,6 +229,9 @@ impl Constraint { .join(",") ) }, + Constraint::HasAbility(ability) => { + format!("{}", ability) + }, Constraint::WithDefault(_ty) => "".to_owned(), } } @@ -961,6 +967,9 @@ impl WideningOrder { pub trait UnificationContext { /// Get the field map for a struct, with field types instantiated. fn get_struct_field_map(&self, id: &QualifiedInstId) -> BTreeMap; + + /// Get the abilities of the type. + fn get_type_abilities(&self, ty: &Type) -> AbilitySet; } /// A struct representing an empty unification context. @@ -970,17 +979,23 @@ impl UnificationContext for NoUnificationContext { fn get_struct_field_map(&self, _id: &QualifiedInstId) -> BTreeMap { BTreeMap::new() } + + fn get_type_abilities(&self, _ty: &Type) -> AbilitySet { + AbilitySet::ALL + } } /// A struct representing a cached unification context. #[derive(Debug)] -pub struct CachedUnificationContext(pub BTreeMap, BTreeMap>); +pub struct CachedUnificationContext( + pub BTreeMap, (BTreeMap, AbilitySet)>, +); impl UnificationContext for CachedUnificationContext { fn get_struct_field_map(&self, id: &QualifiedInstId) -> BTreeMap { self.0 .get(&id.to_qualified_id()) - .map(|field_map| { + .map(|(field_map, _)| { field_map .iter() .map(|(n, ty)| (*n, ty.instantiate(&id.inst))) @@ -988,6 +1003,20 @@ impl UnificationContext for CachedUnificationContext { }) .unwrap_or_default() } + + fn get_type_abilities(&self, ty: &Type) -> AbilitySet { + // TODO(#12437): this currently does not do ability inference, which should be fixed + // once the new type unification context lands. + match ty { + Type::Struct(mid, sid, _) => self + .0 + .get(&mid.qualified(*sid)) + .map(|(_, abilities)| *abilities) + .unwrap_or_else(|| AbilitySet::ALL), + Type::TypeParameter(_) => AbilitySet::ALL, + _ => AbilitySet::PRIMITIVES, + } + } } impl Substitution { @@ -1157,6 +1186,13 @@ impl Substitution { } Ok(()) }, + (Constraint::HasAbility(ability), ty) => { + if context.get_type_abilities(ty).has_ability(*ability) { + Ok(()) + } else { + constraint_unsatisfied_error() + } + }, (Constraint::WithDefault(_), _) => Ok(()), _ => constraint_unsatisfied_error(), } @@ -1942,6 +1978,11 @@ impl TypeUnificationError { Constraint::SomeStruct(field_map) => { Self::message_for_struct(unification_context, display_context, field_map, ty) }, + Constraint::HasAbility(ability) => format!( + "type `{}` does not have expected ability `{}`", + ty.display(display_context), + ability + ), Constraint::WithDefault(_) => unreachable!("default constraint in error message"), }, TypeUnificationError::ConstraintsIncompatible(_, c1, c2) => { @@ -2468,7 +2509,12 @@ pub fn gen_get_ty_param_kinds( if let Some(tp) = ty_params.get(i as usize) { tp.1.clone() } else { - panic!("ICE unbound type parameter") + // TODO(12437): bring this panic back + //panic!("ICE unbound type parameter") + TypeParameterKind { + abilities: AbilitySet::PRIMITIVES, + is_phantom: false, + } } } } diff --git a/third_party/move/move-model/src/well_known.rs b/third_party/move/move-model/src/well_known.rs index 7ce1b4b2e3359..06dc1ff673a5c 100644 --- a/third_party/move/move-model/src/well_known.rs +++ b/third_party/move/move-model/src/well_known.rs @@ -6,7 +6,6 @@ //! //! This currently only contains those declarations used somewhere, not all well-known //! declarations. It can be extended on the go. -//! /// Function identifying the name of an attribute which declares an /// item to be part of test. @@ -29,10 +28,9 @@ pub const TYPE_INFO_MOVE: &str = "type_info::type_of"; pub const TYPE_INFO_SPEC: &str = "type_info::$type_of"; pub const TYPE_SPEC_IS_STRUCT: &str = "type_info::spec_is_struct"; +/// NOTE: `type_info::type_name` and `type_name::get` are very similar. +/// The main difference (from a prover's perspective) include: +/// - formatting of an address (part of the struct name), and +/// - whether it is in `stdlib` or `extlib`. pub const TYPE_NAME_GET_MOVE: &str = "type_name::get"; pub const TYPE_NAME_GET_SPEC: &str = "type_name::$get"; - -// NOTE: `type_info::type_name` and `type_name::get` are very similar. -// The main difference (from a prover's perspective) include: -// - formatting of an address (part of the struct name), and -// - whether it is in `stdlib` or `extlib`. diff --git a/third_party/move/move-model/tests/sources/invariants_err.exp b/third_party/move/move-model/tests/sources/invariants_err.exp index fdf28724eb62d..79bdac1d34d4c 100644 --- a/third_party/move/move-model/tests/sources/invariants_err.exp +++ b/third_party/move/move-model/tests/sources/invariants_err.exp @@ -19,20 +19,8 @@ error: invalid reference to post state │ │ expression referring to post state │ not allowed to refer to post state -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/sources/invariants_err.move:13:5 +error: undeclared `spec_var` + ┌─ tests/sources/invariants_err.move:19:11 │ -13 │ invariant exists(@0x0); - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/sources/invariants_err.move:14:5 - │ -14 │ invariant global(@0x0).x == x; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: data invariants cannot depend on global state (directly or indirectly uses a global spec var or resource storage). - ┌─ tests/sources/invariants_err.move:15:5 - │ -15 │ invariant spec_var > 0; - │ ^^^^^^^^^^^^^^^^^^^^^^^ +19 │ spec_var > 0 + │ ^^^^^^^^ diff --git a/third_party/move/move-model/tests/sources/invariants_err.move b/third_party/move/move-model/tests/sources/invariants_err.move index 9c37c34404fd6..2e2e68aee92bd 100644 --- a/third_party/move/move-model/tests/sources/invariants_err.move +++ b/third_party/move/move-model/tests/sources/invariants_err.move @@ -9,17 +9,9 @@ module 0x42::M { invariant x + 1; // Old expression in data invariant invariant old(x) > 0; - // Direct dependency from global state - invariant exists(@0x0); - invariant global(@0x0).x == x; - invariant spec_var > 0; - // Indirect dependency from global state via function call. - invariant rec_fun(true); } spec module { - global spec_var: num; - fun rec_fun(c: bool): bool { if (c) { rec_fun2(c) @@ -32,7 +24,5 @@ module 0x42::M { } } - // Type instantiation for global memory operations is not a struct type - invariant exists(@0x0); invariant global(@0x1) == global(@0x2); } diff --git a/third_party/move/move-prover/Cargo.toml b/third_party/move/move-prover/Cargo.toml index 4f69f90b6ad95..605c405a14f17 100644 --- a/third_party/move/move-prover/Cargo.toml +++ b/third_party/move/move-prover/Cargo.toml @@ -12,6 +12,7 @@ move-abigen = { path = "move-abigen" } move-binary-format = { path = "../move-binary-format" } move-command-line-common = { path = "../move-command-line-common" } move-compiler = { path = "../move-compiler" } +move-compiler-v2 = { path = "../move-compiler-v2" } move-core-types = { path = "../move-core/types" } move-docgen = { path = "move-docgen" } move-errmapgen = { path = "move-errmapgen" } diff --git a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs index 320962d971442..ae20464a9cd1b 100644 --- a/third_party/move/move-prover/boogie-backend/src/spec_translator.rs +++ b/third_party/move/move-prover/boogie-backend/src/spec_translator.rs @@ -768,23 +768,39 @@ impl<'env> SpecTranslator<'env> { } fn translate_block(&self, pat: &Pattern, binding: &Option, scope: &Exp) { - match (pat, binding) { - (Pattern::Var(_, name), Some(exp)) => { - let name_str = self.env.symbol_pool().string(*name); - emit!(self.writer, "(var {} := ", name_str); - self.translate_exp(exp); - emit!(self.writer, "; "); - self.translate_exp(scope); - emit!(self.writer, ")"); - }, - (_, Some(_)) => { + let binding = binding.as_ref().expect("valid specification binding"); + let pats = pat.clone().flatten(); + let bindings = if let ExpData::Call(_, Operation::Tuple, args) = binding.as_ref() { + args.clone() + } else { + vec![binding.clone()] + }; + assert_eq!(pats.len(), bindings.len(), "valid specification binding"); + let mut vars = vec![]; + for pat in pats { + if let Pattern::Var(_, sym) = pat { + vars.push(sym.display(self.env.symbol_pool()).to_string()) + } else { self.error( &self.env.get_node_loc(pat.node_id()), "patterns not supported in specification language", ); - }, - _ => panic!("unexpected missing binding in specification block"), + return; + } } + emit!(self.writer, "(var {} := ", vars.into_iter().join(",")); + let mut first = true; + for binding in bindings { + if first { + first = false + } else { + emit!(self.writer, ", ") + } + self.translate_exp(&binding); + } + emit!(self.writer, "; "); + self.translate_exp(scope); + emit!(self.writer, ")"); } fn translate_call(&self, node_id: NodeId, oper: &Operation, args: &[Exp]) { @@ -810,6 +826,7 @@ impl<'env> SpecTranslator<'env> { self.translate_spec_fun_call(node_id, *module_id, *fun_id, args, memory_labels) }, Operation::Pack(mid, sid) => self.translate_pack(node_id, *mid, *sid, args), + Operation::Tuple if args.len() == 1 => self.translate_exp(&args[0]), Operation::Tuple => self.error(&loc, "Tuple not yet supported"), Operation::Select(module_id, struct_id, field_id) => { self.translate_select(node_id, *module_id, *struct_id, *field_id, args) diff --git a/third_party/move/move-prover/bytecode-pipeline/src/number_operation.rs b/third_party/move/move-prover/bytecode-pipeline/src/number_operation.rs index 7c50796cd6526..3efd6b1595f6c 100644 --- a/third_party/move/move-prover/bytecode-pipeline/src/number_operation.rs +++ b/third_party/move/move-prover/bytecode-pipeline/src/number_operation.rs @@ -268,7 +268,8 @@ impl GlobalNumberOperationState { // Obtain positions that are marked as Bitwise by analyzing the pragma let para_sym = &struct_env.module_env.env.symbol_pool().make(BV_PARAM_PROP); - let bv_struct_opt = struct_env.get_spec().properties.get(para_sym); + let struct_spec = struct_env.get_spec(); + let bv_struct_opt = struct_spec.properties.get(para_sym); let field_idx_vec = Self::extract_bv_vars(bv_struct_opt); let mid = struct_env.module_env.get_id(); diff --git a/third_party/move/move-prover/bytecode-pipeline/tests/spec_instrumentation/modifies.exp b/third_party/move/move-prover/bytecode-pipeline/tests/spec_instrumentation/modifies.exp index 78232cc8e1c65..3dcb45393ee96 100644 --- a/third_party/move/move-prover/bytecode-pipeline/tests/spec_instrumentation/modifies.exp +++ b/third_party/move/move-prover/bytecode-pipeline/tests/spec_instrumentation/modifies.exp @@ -488,50 +488,89 @@ fun B::move_from_test_incorrect[baseline] spec { modifies global($t1); } +9 -> spec { + assert Eq($t3, $t4); +} + fun B::move_from_test_incorrect[verification] spec { modifies global($t1); } +9 -> spec { + assert Eq($t3, $t4); +} + fun B::move_to_test_incorrect[baseline] spec { modifies global($t1); } +10 -> spec { + assert Eq($t2, $t3); +} + fun B::move_to_test_incorrect[verification] spec { modifies global($t1); } +10 -> spec { + assert Eq($t2, $t3); +} + fun B::mutate_S_test1_incorrect[baseline] spec { requires Neq

($t0, $t1); modifies global($t1); } +8 -> spec { + assert Eq($t2, $t3); +} + fun B::mutate_S_test1_incorrect[verification] spec { requires Neq
($t0, $t1); modifies global($t1); } +8 -> spec { + assert Eq($t2, $t3); +} + fun B::mutate_S_test2_incorrect[baseline] spec { modifies global($t0); } +8 -> spec { + assert Eq($t1, $t2); +} + fun B::mutate_S_test2_incorrect[verification] spec { modifies global($t0); } +8 -> spec { + assert Eq($t1, $t2); +} + fun B::mutate_at_test_incorrect[baseline] spec { modifies global($t1); } +13 -> spec { + assert Eq($t3, $t4); +} + fun B::mutate_at_test_incorrect[verification] spec { modifies global($t1); } +13 -> spec { + assert Eq($t3, $t4); +} diff --git a/third_party/move/move-prover/move-docgen/src/docgen.rs b/third_party/move/move-prover/move-docgen/src/docgen.rs index 318075cd6bb3d..5f3532e688dd7 100644 --- a/third_party/move/move-prover/move-docgen/src/docgen.rs +++ b/third_party/move/move-prover/move-docgen/src/docgen.rs @@ -697,14 +697,19 @@ impl<'env> Docgen<'env> { if !self.options.specs_inlined { self.gen_spec_section(module_env, &spec_block_map); } else { - match spec_block_map.get(&SpecBlockTarget::Module) { + match spec_block_map.get(&SpecBlockTarget::Module(module_env.get_id())) { Some(blocks) if !blocks.is_empty() => { self.section_header( "Module Specification", &self.label_for_section("Module Specification"), ); self.increment_section_nest(); - self.gen_spec_blocks(module_env, "", &SpecBlockTarget::Module, &spec_block_map); + self.gen_spec_blocks( + module_env, + "", + &SpecBlockTarget::Module(module_env.get_id()), + &spec_block_map, + ); self.decrement_section_nest(); }, _ => {}, @@ -1445,12 +1450,12 @@ impl<'env> Docgen<'env> { /// are associated with the context they appear in. fn organize_spec_blocks(&self, module_env: &'env ModuleEnv<'env>) -> SpecBlockMap<'env> { let mut result = BTreeMap::new(); - let mut current_target = SpecBlockTarget::Module; + let mut current_target = SpecBlockTarget::Module(module_env.get_id()); let mut last_block_end: Option = None; for block in module_env.get_spec_block_infos() { let may_merge_with_current = match &block.target { SpecBlockTarget::Schema(..) => true, - SpecBlockTarget::Module + SpecBlockTarget::Module(_) if !block.member_locs.is_empty() || !self.is_single_liner(&block.loc) => { // This is a bit of a hack: if spec module is on a single line, @@ -1511,7 +1516,12 @@ impl<'env> Docgen<'env> { let section_label = self.label_for_section("Specification"); self.section_header("Specification", §ion_label); self.increment_section_nest(); - self.gen_spec_blocks(module_env, "", &SpecBlockTarget::Module, spec_block_map); + self.gen_spec_blocks( + module_env, + "", + &SpecBlockTarget::Module(module_env.get_id()), + spec_block_map, + ); for struct_env in module_env .get_structs() .filter(|s| !s.is_test_only()) diff --git a/third_party/move/move-prover/src/cli.rs b/third_party/move/move-prover/src/cli.rs index 6f1012860e194..5b829fc0f2dca 100644 --- a/third_party/move/move-prover/src/cli.rs +++ b/third_party/move/move-prover/src/cli.rs @@ -15,7 +15,7 @@ use move_compiler::{command_line::SKIP_ATTRIBUTE_CHECKS, shared::NumericalAddres use move_docgen::DocgenOptions; use move_errmapgen::ErrmapOptions; use move_model::{model::VerificationScope, options::ModelBuilderOptions}; -use move_prover_boogie_backend::options::{BoogieOptions, VectorTheory}; +use move_prover_boogie_backend::options::{BoogieOptions, CustomNativeOptions, VectorTheory}; use move_prover_bytecode_pipeline::options::{AutoTraceLevel, ProverOptions}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; @@ -157,6 +157,12 @@ impl Options { .action(SetTrue) .help("prints the effective toml configuration, then exits") ) + .arg( + Arg::new("aptos") + .long("aptos") + .action(SetTrue) + .help("configures the prover to use Aptos natives") + ) .arg( Arg::new("output") .short('o') @@ -763,6 +769,23 @@ impl Options { options.prover.ban_int_2_bv = true; } + if matches.get_flag("aptos") { + options.backend.custom_natives = Some(CustomNativeOptions { + template_bytes: include_bytes!( + "../../../../aptos-move/framework/src/aptos-natives.bpl" + ) + .to_vec(), + module_instance_names: vec![( + "0x1::object".to_string(), + "object_instances".to_string(), + true, + )], + }); + options + .move_named_address_values + .push("Extensions=0x1".to_string()) + } + options.backend.derive_options(); if matches.get_flag("print-config") { diff --git a/third_party/move/move-prover/src/lib.rs b/third_party/move/move-prover/src/lib.rs index 13306e1fcbf15..a1298abae70d3 100644 --- a/third_party/move/move-prover/src/lib.rs +++ b/third_party/move/move-prover/src/lib.rs @@ -11,6 +11,7 @@ use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColo use log::{debug, info, warn}; use move_abigen::Abigen; use move_compiler::shared::{known_attributes::KnownAttribute, PackagePaths}; +use move_compiler_v2::env_pipeline::{rewrite_target::RewritingScope, spec_rewriter}; use move_docgen::Docgen; use move_errmapgen::ErrmapGen; use move_model::{ @@ -47,7 +48,7 @@ pub fn run_move_prover( let now = Instant::now(); // Run the model builder. let addrs = parse_addresses_from_options(options.move_named_address_values.clone())?; - let env = run_model_builder_with_options( + let mut env = run_model_builder_with_options( vec![PackagePaths { name: None, paths: options.move_sources.clone(), @@ -62,7 +63,7 @@ pub fn run_move_prover( options.skip_attribute_checks, KnownAttribute::get_all_attribute_names(), )?; - run_move_prover_with_model(&env, error_writer, options, Some(now)) + run_move_prover_with_model(&mut env, error_writer, options, Some(now)) } /// Create the initial number operation state for each function and struct @@ -82,13 +83,26 @@ pub fn create_init_num_operation_state(env: &GlobalEnv) { } pub fn run_move_prover_with_model( - env: &GlobalEnv, + env: &mut GlobalEnv, error_writer: &mut W, options: Options, timer: Option, ) -> anyhow::Result<()> { let now = timer.unwrap_or_else(Instant::now); + // Run the compiler v2 checking and rewriting pipeline + let compiler_options = move_compiler_v2::Options::default(); + env.set_extension(compiler_options.clone()); + let mut pipeline = move_compiler_v2::check_and_rewrite_pipeline( + &compiler_options, + true, + RewritingScope::Everything, + ); + pipeline.add("specification rewriter", spec_rewriter::run_spec_rewriter); + pipeline.run(env); + + debug!("global env before prover run:\n{}", env.dump_env_all()); + let build_duration = now.elapsed(); check_errors( env, diff --git a/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.exp b/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.exp index 50581e19a4acd..adbfb5fe2ac21 100644 --- a/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.exp +++ b/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.exp @@ -1,6 +1,8 @@ Move prover returns: exiting with model building errors -error: duplicate declaration of `double` - ┌─ tests/sources/functional/duplicate_function_declarations.move:11:9 - │ -11 │ fun double(x: u8): u8 { - │ ^^^^^^ +error: name clash between specification and Move function `double` + ┌─ tests/sources/functional/duplicate_function_declarations.move:5:9 + │ +5 │ ╭ fun double(x: u8): u8 { +6 │ │ x * 2 +7 │ │ } + │ ╰─────────^ diff --git a/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.move b/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.move index 5518711d66af0..41f7fb9bac9d9 100644 --- a/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.move +++ b/third_party/move/move-prover/tests/sources/functional/duplicate_function_declarations.move @@ -9,7 +9,8 @@ module 0x42::DuplicateFunction { } fun double(x: u8): u8 { - x * 2 + x } + spec double (x: u8) : u8 {} } diff --git a/third_party/move/move-prover/tests/sources/functional/inline-lambda.exp b/third_party/move/move-prover/tests/sources/functional/inline-lambda.exp index 8f2fa7211605a..5d4d51a47b7c5 100644 --- a/third_party/move/move-prover/tests/sources/functional/inline-lambda.exp +++ b/third_party/move/move-prover/tests/sources/functional/inline-lambda.exp @@ -9,18 +9,18 @@ error: unknown assertion failed = a1 = = a2 = = at tests/sources/functional/inline-lambda.move:11: test_apply - = at tests/sources/functional/inline-lambda.move:2: apply + = at tests/sources/functional/inline-lambda.move:2 = v#0 = - = at tests/sources/functional/inline-lambda.move:4: apply - = at tests/sources/functional/inline-lambda.move:5: apply + = at tests/sources/functional/inline-lambda.move:4 + = at tests/sources/functional/inline-lambda.move:5 = at tests/sources/functional/inline-lambda.move:11: test_apply = r1 = = at tests/sources/functional/inline-lambda.move:13: test_apply = at tests/sources/functional/inline-lambda.move:16: test_apply - = at tests/sources/functional/inline-lambda.move:2: apply + = at tests/sources/functional/inline-lambda.move:2 = v#3 = - = at tests/sources/functional/inline-lambda.move:4: apply - = at tests/sources/functional/inline-lambda.move:5: apply + = at tests/sources/functional/inline-lambda.move:4 + = at tests/sources/functional/inline-lambda.move:5 error: unknown assertion failed ┌─ tests/sources/functional/inline-lambda.move:18:13 @@ -32,18 +32,18 @@ error: unknown assertion failed = a1 = = a2 = = at tests/sources/functional/inline-lambda.move:11: test_apply - = at tests/sources/functional/inline-lambda.move:2: apply + = at tests/sources/functional/inline-lambda.move:2 = v#0 = - = at tests/sources/functional/inline-lambda.move:4: apply - = at tests/sources/functional/inline-lambda.move:5: apply + = at tests/sources/functional/inline-lambda.move:4 + = at tests/sources/functional/inline-lambda.move:5 = at tests/sources/functional/inline-lambda.move:11: test_apply = r1 = = at tests/sources/functional/inline-lambda.move:13: test_apply = at tests/sources/functional/inline-lambda.move:16: test_apply - = at tests/sources/functional/inline-lambda.move:2: apply + = at tests/sources/functional/inline-lambda.move:2 = v#3 = - = at tests/sources/functional/inline-lambda.move:4: apply - = at tests/sources/functional/inline-lambda.move:5: apply + = at tests/sources/functional/inline-lambda.move:4 + = at tests/sources/functional/inline-lambda.move:5 = at tests/sources/functional/inline-lambda.move:16: test_apply = r2 = = at tests/sources/functional/inline-lambda.move:18: test_apply diff --git a/third_party/move/move-prover/tests/sources/functional/inline_fun_simple.exp b/third_party/move/move-prover/tests/sources/functional/inline_fun_simple.exp index 4b124294327eb..b1cc3b5cfa3f3 100644 --- a/third_party/move/move-prover/tests/sources/functional/inline_fun_simple.exp +++ b/third_party/move/move-prover/tests/sources/functional/inline_fun_simple.exp @@ -6,13 +6,13 @@ error: unknown assertion failed │ ^^^^^^^^^^^^^^^ │ = at tests/sources/functional/inline_fun_simple.move:22: test_apply_error - = at tests/sources/functional/inline_fun_simple.move:2: apply + = at tests/sources/functional/inline_fun_simple.move:2 = v#6 = - = at tests/sources/functional/inline_fun_simple.move:4: apply + = at tests/sources/functional/inline_fun_simple.move:4 = at tests/sources/functional/inline_fun_simple.move:22: test_apply_error = r1 = = at tests/sources/functional/inline_fun_simple.move:24: test_apply_error = at tests/sources/functional/inline_fun_simple.move:27: test_apply_error - = at tests/sources/functional/inline_fun_simple.move:2: apply + = at tests/sources/functional/inline_fun_simple.move:2 = v#9 = - = at tests/sources/functional/inline_fun_simple.move:4: apply + = at tests/sources/functional/inline_fun_simple.move:4 diff --git a/third_party/move/move-prover/tests/sources/functional/invariants.exp b/third_party/move/move-prover/tests/sources/functional/invariants.exp index 438301c03723d..eba0575d97923 100644 --- a/third_party/move/move-prover/tests/sources/functional/invariants.exp +++ b/third_party/move/move-prover/tests/sources/functional/invariants.exp @@ -1,28 +1,28 @@ Move prover returns: exiting with verification errors error: data invariant does not hold - ┌─ tests/sources/functional/invariants.move:16:9 + ┌─ tests/sources/functional/invariants.move:15:9 │ -16 │ invariant greater_one(x); +15 │ invariant greater_one(x); │ ^^^^^^^^^^^^^^^^^^^^^^^^^ │ - = at tests/sources/functional/invariants.move:43: invalid_R_pack - = at tests/sources/functional/invariants.move:16 + = at tests/sources/functional/invariants.move:42: invalid_R_pack + = at tests/sources/functional/invariants.move:15 error: data invariant does not hold - ┌─ tests/sources/functional/invariants.move:16:9 + ┌─ tests/sources/functional/invariants.move:15:9 │ -16 │ invariant greater_one(x); +15 │ invariant greater_one(x); │ ^^^^^^^^^^^^^^^^^^^^^^^^^ │ = at tests/sources/functional/invariants.move:113: lifetime_invalid_R - = at tests/sources/functional/invariants.move:16 + = at tests/sources/functional/invariants.move:15 = at tests/sources/functional/invariants.move:113: lifetime_invalid_R = r = = at tests/sources/functional/invariants.move:114: lifetime_invalid_R = at tests/sources/functional/invariants.move:115: lifetime_invalid_R = x_ref = = at tests/sources/functional/invariants.move:116: lifetime_invalid_R - = at tests/sources/functional/invariants.move:16 + = at tests/sources/functional/invariants.move:15 error: data invariant does not hold ┌─ tests/sources/functional/invariants.move:150:9 diff --git a/third_party/move/move-prover/tests/sources/functional/invariants.move b/third_party/move/move-prover/tests/sources/functional/invariants.move index 15737b2b240ef..86f0f65339f9e 100644 --- a/third_party/move/move-prover/tests/sources/functional/invariants.move +++ b/third_party/move/move-prover/tests/sources/functional/invariants.move @@ -1,5 +1,4 @@ module 0x42::TestInvariants { - spec module { pragma verify = true; } @@ -7,7 +6,7 @@ module 0x42::TestInvariants { // General invariant checking. - struct R has copy, drop { + struct R has key, copy, drop { x: u64 } @@ -24,7 +23,7 @@ module 0x42::TestInvariants { fun greater_one(x: num): bool { x > 1 } // Impure function to be used in update invariants. - fun tautology() : bool { global(@0x5551212) == R {x: 2} || global(@0x5551212) != R {x: 2} } + fun tautology(): bool { global(@0x5551212) == R { x: 2 } || global(@0x5551212) != R { x: 2 } } } @@ -33,14 +32,14 @@ module 0x42::TestInvariants { // ---------- fun valid_R_pack(): R { - R {x: 2} + R { x: 2 } } spec valid_R_pack { ensures result.x == 2; } fun invalid_R_pack(): R { - R {x: 1} + R { x: 1 } } spec invalid_R_pack { ensures result.x == 1; @@ -52,9 +51,9 @@ module 0x42::TestInvariants { // ------------ fun valid_R_update(): R { - let t = R {x: 3}; + let t = R { x: 3 }; let r = &mut t; - *r = R {x: 2}; + *r = R { x: 2 }; t } spec valid_R_update { @@ -62,9 +61,9 @@ module 0x42::TestInvariants { } fun invalid_R_update(): R { - let t = R {x: 3}; + let t = R { x: 3 }; let r = &mut t; - *r = R {x: 4}; + *r = R { x: 4 }; t } spec invalid_R_update { @@ -72,7 +71,7 @@ module 0x42::TestInvariants { } fun invalid_R_update_ref(): R { - let t = R{x:3}; + let t = R { x: 3 }; let r = &mut t.x; *r = 4; t @@ -82,17 +81,18 @@ module 0x42::TestInvariants { } fun invalid_R_update_indirectly(): R { - let t = R{x:3}; + let t = R { x: 3 }; update_helper(&mut t.x); t } + fun update_helper(r: &mut u64) { *r = 4; } fun invalid_R_update_branching(b: bool): R { - let t1 = R {x: 5}; - let t2 = R {x: 3}; + let t1 = R { x: 5 }; + let t2 = R { x: 3 }; let r: &mut R; if (b) { // this branch is fine because we can go from x = 5 to x = 4 @@ -101,7 +101,7 @@ module 0x42::TestInvariants { // this branch leads to update invariant violation as we cannot go from x = 3 to x = 4 r = &mut t2 }; - *r = R {x: 4}; + *r = R { x: 4 }; *r } @@ -109,8 +109,8 @@ module 0x42::TestInvariants { // Lifetime analysis tests // ----------------------- - fun lifetime_invalid_R() : R { - let r = R {x: 3}; + fun lifetime_invalid_R(): R { + let r = R { x: 3 }; let r_ref = &mut r; let x_ref = &mut r_ref.x; *x_ref = 0; // r_ref goes out of scope here @@ -122,8 +122,8 @@ module 0x42::TestInvariants { r } - fun lifetime_invalid_R_2() : R { - let r = R {x: 4}; + fun lifetime_invalid_R_2(): R { + let r = R { x: 4 }; let r_ref = &mut r; let x_ref = &mut r_ref.x; *x_ref = 0; @@ -151,18 +151,18 @@ module 0x42::TestInvariants { } fun lifetime_invalid_S_branching(cond: bool): (T, S) { - let a = T {x: 3}; - let b = S {y: 4}; - let a_ref = &mut a; - let b_ref = &mut b; - let x_ref = if (cond) { &mut a_ref.x } else { &mut b_ref.y }; - - if (cond) { - *x_ref = 2; - } else { - *x_ref = 0; // only S's invariant should fail - }; - - (a, b) + let a = T { x: 3 }; + let b = S { y: 4 }; + let a_ref = &mut a; + let b_ref = &mut b; + let x_ref = if (cond) { &mut a_ref.x } else { &mut b_ref.y }; + + if (cond) { + *x_ref = 2; + } else { + *x_ref = 0; // only S's invariant should fail + }; + + (a, b) } } diff --git a/third_party/move/move-prover/tests/sources/functional/pure_function_call_incorrect.exp b/third_party/move/move-prover/tests/sources/functional/pure_function_call_incorrect.exp index 1ab1384f42548..08be7b01d0abd 100644 --- a/third_party/move/move-prover/tests/sources/functional/pure_function_call_incorrect.exp +++ b/third_party/move/move-prover/tests/sources/functional/pure_function_call_incorrect.exp @@ -1,24 +1,15 @@ Move prover returns: exiting with model building errors -error: calling impure function `TestPureFun::init` is not allowed +error: specification expression cannot call impure Move function `init` ┌─ tests/sources/functional/pure_function_call_incorrect.move:32:20 │ +11 │ return true + │ ----------- in `init`: return not allowed in specifications + · 32 │ aborts_if !init(account); - │ ^^^^^^^^^^^^^ - │ - = impure function `TestPureFun::init(&signer): bool` + │ ^^^^^^^^^^^^^ called here -error: calling impure function `vector::pop_back` is not allowed +error: specification expression cannot use impure construct ┌─ tests/sources/functional/pure_function_call_incorrect.move:56:27 │ 56 │ ensures result == vector::pop_back(old(v)); - │ ^^^^^^^^^^^^^^^^^^^^^^^^ - │ - = impure function `vector::pop_back(&mut vector): Element` - -error: calling impure function `TestPureFun::impure_f_2` is not allowed - ┌─ tests/sources/functional/pure_function_call_incorrect.move:62:13 - │ -62 │ impure_f_2() - │ ^^^^^^^^^^^^ - │ - = impure function `TestPureFun::impure_f_2(): u64` + │ ^^^^^^^^^^^^^^^^^^^^^^^^ calls a function which modifies state diff --git a/third_party/move/move-stdlib/docs/option.md b/third_party/move/move-stdlib/docs/option.md index 698df505bcc56..25386fd17fd2b 100644 --- a/third_party/move/move-stdlib/docs/option.md +++ b/third_party/move/move-stdlib/docs/option.md @@ -25,12 +25,6 @@ This module defines the Option type and its methods to represent and handle an o - [Function `destroy_some`](#0x1_option_destroy_some) - [Function `destroy_none`](#0x1_option_destroy_none) - [Function `to_vec`](#0x1_option_to_vec) -- [Function `for_each`](#0x1_option_for_each) -- [Function `for_each_ref`](#0x1_option_for_each_ref) -- [Function `for_each_mut`](#0x1_option_for_each_mut) -- [Function `fold`](#0x1_option_fold) -- [Function `map`](#0x1_option_map) -- [Function `filter`](#0x1_option_filter) - [Module Specification](#@Module_Specification_1) - [Helper Schema](#@Helper_Schema_2) @@ -851,182 +845,6 @@ and an empty vector otherwise - - - - -## Function `for_each` - -Apply the function to the optional element, consuming it. - - -
public fun for_each<Element>(o: option::Option<Element>, f: |Element|)
-
- - - -
-Implementation - - -
public inline fun for_each<Element>(o: Option<Element>, f: |Element|) {
-    if (is_some(&o)) {
-        f(destroy_some(o))
-    } else {
-        destroy_none(o)
-    }
-}
-
- - - -
- - - -## Function `for_each_ref` - -Apply the function to the optional element reference. - - -
public fun for_each_ref<Element>(o: &option::Option<Element>, f: |&Element|)
-
- - - -
-Implementation - - -
public inline fun for_each_ref<Element>(o: &Option<Element>, f: |&Element|) {
-    if (is_some(o)) {
-        f(borrow(o))
-    }
-}
-
- - - -
- - - -## Function `for_each_mut` - -Apply the function to the optional element reference. - - -
public fun for_each_mut<Element>(o: &mut option::Option<Element>, f: |&mut Element|)
-
- - - -
-Implementation - - -
public inline fun for_each_mut<Element>(o: &mut Option<Element>, f: |&mut Element|) {
-    if (is_some(o)) {
-        f(borrow_mut(o))
-    }
-}
-
- - - -
- - - -## Function `fold` - -Folds the function over the optional element. - - -
public fun fold<Accumulator, Element>(o: option::Option<Element>, init: Accumulator, f: |(Accumulator, Element)|Accumulator): Accumulator
-
- - - -
-Implementation - - -
public inline fun fold<Accumulator, Element>(
-    o: Option<Element>,
-    init: Accumulator,
-    f: |Accumulator,Element|Accumulator
-): Accumulator {
-    if (is_some(&o)) {
-        f(init, destroy_some(o))
-    } else {
-        destroy_none(o);
-        init
-    }
-}
-
- - - -
- - - -## Function `map` - -Maps the content of an option - - -
public fun map<Element, OtherElement>(o: option::Option<Element>, f: |Element|OtherElement): option::Option<OtherElement>
-
- - - -
-Implementation - - -
public inline fun map<Element, OtherElement>(o: Option<Element>, f: |Element|OtherElement): Option<OtherElement> {
-    if (is_some(&o)) {
-        some(f(destroy_some(o)))
-    } else {
-        destroy_none(o);
-        none()
-    }
-}
-
- - - -
- - - -## Function `filter` - -Filters the content of an option - - -
public fun filter<Element: drop>(o: option::Option<Element>, f: |&Element|bool): option::Option<Element>
-
- - - -
-Implementation - - -
public inline fun filter<Element:drop>(o: Option<Element>, f: |&Element|bool): Option<Element> {
-    if (is_some(&o) && f(borrow(&o))) {
-        o
-    } else {
-        none()
-    }
-}
-
- - -
diff --git a/third_party/move/move-stdlib/docs/vector.md b/third_party/move/move-stdlib/docs/vector.md index c50a8c59f3a17..ffc2f4a9615cb 100644 --- a/third_party/move/move-stdlib/docs/vector.md +++ b/third_party/move/move-stdlib/docs/vector.md @@ -32,12 +32,6 @@ the return on investment didn't seem worth it for these simple functions. - [Function `index_of`](#0x1_vector_index_of) - [Function `remove`](#0x1_vector_remove) - [Function `swap_remove`](#0x1_vector_swap_remove) -- [Function `for_each`](#0x1_vector_for_each) -- [Function `for_each_ref`](#0x1_vector_for_each_ref) -- [Function `for_each_mut`](#0x1_vector_for_each_mut) -- [Function `fold`](#0x1_vector_fold) -- [Function `map`](#0x1_vector_map) -- [Function `filter`](#0x1_vector_filter) - [Module Specification](#@Module_Specification_1) - [Helper Functions](#@Helper_Functions_2) @@ -593,187 +587,6 @@ Aborts if i is out of bounds. - - - - -## Function `for_each` - -Apply the function to each element in the vector, consuming it. - - -
public fun for_each<Element>(v: vector<Element>, f: |Element|)
-
- - - -
-Implementation - - -
public inline fun for_each<Element>(v: vector<Element>, f: |Element|) {
-    reverse(&mut v); // We need to reverse the vector to consume it efficiently
-    while (!is_empty(&v)) {
-        let e = pop_back(&mut v);
-        f(e);
-    };
-}
-
- - - -
- - - -## Function `for_each_ref` - -Apply the function to a reference of each element in the vector. - - -
public fun for_each_ref<Element>(v: &vector<Element>, f: |&Element|)
-
- - - -
-Implementation - - -
public inline fun for_each_ref<Element>(v: &vector<Element>, f: |&Element|) {
-    let i = 0;
-    while (i < length(v)) {
-        f(borrow(v, i));
-        i = i + 1
-    }
-}
-
- - - -
- - - -## Function `for_each_mut` - -Apply the function to a mutable reference to each element in the vector. - - -
public fun for_each_mut<Element>(v: &mut vector<Element>, f: |&mut Element|)
-
- - - -
-Implementation - - -
public inline fun for_each_mut<Element>(v: &mut vector<Element>, f: |&mut Element|) {
-    let i = 0;
-    while (i < length(v)) {
-        f(borrow_mut(v, i));
-        i = i + 1
-    }
-}
-
- - - -
- - - -## Function `fold` - -Fold the function over the elements. For example, fold(vector[1,2,3], 0, f) will execute -f(f(f(0, 1), 2), 3) - - -
public fun fold<Accumulator, Element>(v: vector<Element>, init: Accumulator, f: |(Accumulator, Element)|Accumulator): Accumulator
-
- - - -
-Implementation - - -
public inline fun fold<Accumulator, Element>(
-    v: vector<Element>,
-    init: Accumulator,
-    f: |Accumulator,Element|Accumulator
-): Accumulator {
-    let accu = init;
-    for_each(v, |elem| accu = f(accu, elem));
-    accu
-}
-
- - - -
- - - -## Function `map` - -Map the function over the elements of the vector, producing a new vector. - - -
public fun map<Element, NewElement>(v: vector<Element>, f: |Element|NewElement): vector<NewElement>
-
- - - -
-Implementation - - -
public inline fun map<Element, NewElement>(
-    v: vector<Element>,
-    f: |Element|NewElement
-): vector<NewElement> {
-    let result = vector<NewElement>[];
-    for_each(v, |elem| push_back(&mut result, f(elem)));
-    result
-}
-
- - - -
- - - -## Function `filter` - -Filter the vector using the boolean function, removing all elements for which p(e) is not true. - - -
public fun filter<Element: drop>(v: vector<Element>, p: |&Element|bool): vector<Element>
-
- - - -
-Implementation - - -
public inline fun filter<Element:drop>(
-    v: vector<Element>,
-    p: |&Element|bool
-): vector<Element> {
-    let result = vector<Element>[];
-    for_each(v, |elem| {
-        if (p(&elem)) push_back(&mut result, elem);
-    });
-    result
-}
-
- - -
diff --git a/third_party/move/scripts/move_pr.sh b/third_party/move/scripts/move_pr.sh index f58fc42ca0521..62f4d0ce4cfde 100755 --- a/third_party/move/scripts/move_pr.sh +++ b/third_party/move/scripts/move_pr.sh @@ -104,37 +104,17 @@ INTEGRATION_TEST_CRATES="\ -p aptos-framework\ " -if [ ! -z "$TEST" ]; then - echo "*************** [move-pr] Running tests" - ( - # It is important to run all tests from one cargo command to keep cargo features - # stable. - cd $BASE - cargo nextest run --cargo-profile $MOVE_PR_PROFILE \ - $MOVE_CRATES - ) -fi - -if [ ! -z "$INTEGRATION_TEST" ]; then - echo "*************** [move-pr] Running extended tests" - ( - cd $BASE - cargo nextest run --cargo-profile $MOVE_PR_PROFILE \ - $MOVE_CRATES $INTEGRATION_TEST_CRATES - ) -fi - - if [ ! -z "$CHECK" ]; then echo "*************** [move-pr] Running checks" ( cd $BASE cargo xclippy cargo +nightly fmt - cargo sort --grouped --workspace + cargo sort --grouped --workspace ) fi +# Artifact generation needs to be run before testing as tests may depend on its result if [ ! -z "$GEN_ARTIFACTS" ]; then for dir in $ARTIFACT_CRATE_PATHS; do echo "*************** [move-pr] Generating artifacts for crate $dir" @@ -150,6 +130,29 @@ if [ ! -z "$GEN_ARTIFACTS" ]; then ) fi + + +if [ ! -z "$TEST" ]; then + echo "*************** [move-pr] Running tests" + ( + # It is important to run all tests from one cargo command to keep cargo features + # stable. + cd $BASE + cargo nextest run --cargo-profile $MOVE_PR_PROFILE \ + $MOVE_CRATES + ) +fi + +if [ ! -z "$INTEGRATION_TEST" ]; then + echo "*************** [move-pr] Running extended tests" + ( + cd $BASE + cargo nextest run --cargo-profile $MOVE_PR_PROFILE \ + $MOVE_CRATES $INTEGRATION_TEST_CRATES + ) +fi + + if [ ! -z "$GIT_CHECKS" ]; then echo "*************** [move-pr] Running git checks" $BASE/scripts/git-checks.sh diff --git a/third_party/move/tools/move-cli/src/base/prove.rs b/third_party/move/tools/move-cli/src/base/prove.rs index 5fc405a96272d..14703957b4d57 100644 --- a/third_party/move/tools/move-cli/src/base/prove.rs +++ b/third_party/move/tools/move-cli/src/base/prove.rs @@ -190,7 +190,7 @@ pub fn run_move_prover( options.set_quiet(); } let now = Instant::now(); - let model = config.move_model_for_package(path, ModelConfig { + let mut model = config.move_model_for_package(path, ModelConfig { all_files_as_targets: false, target_filter: target_filter.clone(), })?; @@ -208,7 +208,7 @@ pub fn run_move_prover( } else { None }; - let res = run_move_prover_with_model(&model, &mut error_writer, options, Some(now)); + let res = run_move_prover_with_model(&mut model, &mut error_writer, options, Some(now)); if for_test { let basedir = path .file_name()