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()