From 29cb03e5b0a605a9acd9209629ceb34747939c5e Mon Sep 17 00:00:00 2001 From: Todd Nowacki Date: Tue, 29 Oct 2024 16:03:38 -0700 Subject: [PATCH] [move-compiler] Remove WarningFiltersScope from CompilationEnv (#20065) ## Description - To make the compiler more parallel friendly, the warning filter scope needs to be local to the environment it is in - Conceptually, CompilationEnv was always the wrong place for this, and trying to add parallelism just exposed this - Added a RwLock around Diagnostics to help with linters. It was a bit hard to tie the knot without doing this as a part of this PR ## Test plan - Ran tests --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] REST API: --- .../src/analysis/typing_analysis.rs | 2 +- .../move/crates/move-analyzer/src/symbols.rs | 8 +- .../move/crates/move-cli/src/base/test.rs | 2 +- .../move-compiler/src/cfgir/borrows/mod.rs | 17 +- .../move-compiler/src/cfgir/liveness/mod.rs | 28 +- .../move-compiler/src/cfgir/locals/mod.rs | 62 ++-- .../crates/move-compiler/src/cfgir/mod.rs | 29 +- .../move-compiler/src/cfgir/optimize/mod.rs | 2 +- .../move-compiler/src/cfgir/translate.rs | 98 ++++-- .../crates/move-compiler/src/cfgir/visitor.rs | 62 ++-- .../src/command_line/compiler.rs | 37 +-- .../move-compiler/src/diagnostics/mod.rs | 6 +- .../crates/move-compiler/src/editions/mod.rs | 4 +- .../src/expansion/name_validation.rs | 48 ++- .../src/expansion/path_expander.rs | 89 +++-- .../src/expansion/primitive_definers.rs | 38 ++- .../move-compiler/src/expansion/translate.rs | 266 ++++++++------- .../src/hlir/detect_dead_code.rs | 79 +++-- .../src/hlir/match_compilation.rs | 4 +- .../move-compiler/src/hlir/translate.rs | 121 ++++--- .../src/linters/abort_constant.rs | 30 +- .../move-compiler/src/naming/fake_natives.rs | 6 +- .../src/naming/resolve_use_funs.rs | 59 ++-- .../src/naming/syntax_methods.rs | 52 ++- .../move-compiler/src/naming/translate.rs | 308 ++++++++++-------- .../crates/move-compiler/src/parser/lexer.rs | 8 +- .../crates/move-compiler/src/parser/mod.rs | 9 +- .../crates/move-compiler/src/parser/syntax.rs | 49 ++- .../parser/verification_attribute_filter.rs | 13 +- .../move-compiler/src/shared/matching.rs | 4 +- .../crates/move-compiler/src/shared/mod.rs | 231 +++++++------ .../move-compiler/src/sui_mode/id_leak.rs | 5 +- .../crates/move-compiler/src/sui_mode/info.rs | 2 +- .../sui_mode/linters/custom_state_change.rs | 3 +- .../src/sui_mode/linters/freeze_wrapped.rs | 22 +- .../src/sui_mode/linters/self_transfer.rs | 2 - .../src/sui_mode/linters/share_owned.rs | 3 +- .../move-compiler/src/sui_mode/typing.rs | 77 +++-- .../move-compiler/src/to_bytecode/context.rs | 4 +- .../src/to_bytecode/translate.rs | 8 +- .../crates/move-compiler/src/typing/ast.rs | 22 +- .../crates/move-compiler/src/typing/core.rs | 91 ++++-- .../src/typing/dependency_ordering.rs | 12 +- .../src/typing/deprecation_warnings.rs | 23 +- .../crates/move-compiler/src/typing/expand.rs | 14 +- .../src/typing/infinite_instantiations.rs | 6 +- .../move-compiler/src/typing/macro_expand.rs | 15 +- .../src/typing/match_analysis.rs | 38 +-- .../src/typing/match_compilation.rs | 4 +- .../src/typing/recursive_datatypes.rs | 6 +- .../src/typing/syntax_methods.rs | 18 +- .../move-compiler/src/typing/translate.rs | 189 ++++------- .../move-compiler/src/typing/visitor.rs | 53 +-- .../src/unit_test/filter_test_members.rs | 10 +- .../src/unit_test/plan_builder.rs | 100 +++--- .../move/crates/move-unit-test/src/lib.rs | 2 +- 56 files changed, 1297 insertions(+), 1203 deletions(-) diff --git a/external-crates/move/crates/move-analyzer/src/analysis/typing_analysis.rs b/external-crates/move/crates/move-analyzer/src/analysis/typing_analysis.rs index 1c97aed29d7e8..8116d87d4396d 100644 --- a/external-crates/move/crates/move-analyzer/src/analysis/typing_analysis.rs +++ b/external-crates/move/crates/move-analyzer/src/analysis/typing_analysis.rs @@ -661,7 +661,7 @@ impl TypingAnalysisContext<'_> { impl<'a> TypingVisitorContext for TypingAnalysisContext<'a> { // Nothing to do -- we're not producing errors. - fn add_warning_filter_scope(&mut self, _filter: diag::WarningFilters) {} + fn push_warning_filter_scope(&mut self, _filter: diag::WarningFilters) {} // Nothing to do -- we're not producing errors. fn pop_warning_filter_scope(&mut self) {} diff --git a/external-crates/move/crates/move-analyzer/src/symbols.rs b/external-crates/move/crates/move-analyzer/src/symbols.rs index 6113b85f19b41..fd9fa72c781dd 100644 --- a/external-crates/move/crates/move-analyzer/src/symbols.rs +++ b/external-crates/move/crates/move-analyzer/src/symbols.rs @@ -1875,7 +1875,7 @@ pub fn get_compiled_pkg( eprintln!("compiled to parsed AST"); let (compiler, parsed_program) = compiler.into_ast(); parsed_ast = Some(parsed_program.clone()); - mapped_files.extend_with_duplicates(compiler.compilation_env_ref().mapped_files().clone()); + mapped_files.extend_with_duplicates(compiler.compilation_env().mapped_files().clone()); // extract typed AST let compilation_result = compiler.at_parser(parsed_program).run::(); @@ -1890,17 +1890,17 @@ pub fn get_compiled_pkg( } }; eprintln!("compiled to typed AST"); - let (mut compiler, typed_program) = compiler.into_ast(); + let (compiler, typed_program) = compiler.into_ast(); typed_ast = Some(typed_program.clone()); compiler_info = Some(CompilerInfo::from( - compiler.compilation_env().ide_information.clone(), + compiler.compilation_env().ide_information().clone(), )); edition = Some(compiler.compilation_env().edition(Some(root_pkg_name))); // compile to CFGIR for accurate diags eprintln!("compiling to CFGIR"); let compilation_result = compiler.at_typing(typed_program).run::(); - let mut compiler = match compilation_result { + let compiler = match compilation_result { Ok(v) => v, Err((_pass, diags)) => { let failure = false; diff --git a/external-crates/move/crates/move-cli/src/base/test.rs b/external-crates/move/crates/move-cli/src/base/test.rs index e37309a8e9b1a..3133b799a9b10 100644 --- a/external-crates/move/crates/move-cli/src/base/test.rs +++ b/external-crates/move/crates/move-cli/src/base/test.rs @@ -196,7 +196,7 @@ pub fn run_move_unit_tests( let (files, comments_and_compiler_res) = compiler.run::().unwrap(); let (_, compiler) = diagnostics::unwrap_or_report_pass_diagnostics(&files, comments_and_compiler_res); - let (mut compiler, cfgir) = compiler.into_ast(); + let (compiler, cfgir) = compiler.into_ast(); let compilation_env = compiler.compilation_env(); let built_test_plan = construct_test_plan(compilation_env, Some(root_package), &cfgir); let mapped_files = compilation_env.mapped_files().clone(); diff --git a/external-crates/move/crates/move-compiler/src/cfgir/borrows/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/borrows/mod.rs index 59e44f130a78b..3952c47e44f32 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/borrows/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/borrows/mod.rs @@ -13,7 +13,7 @@ use crate::{ translate::{display_var, DisplayVar}, }, parser::ast::BinOp_, - shared::{unique_map::UniqueMap, CompilationEnv}, + shared::unique_map::UniqueMap, }; use move_proc_macros::growing_stack; @@ -90,7 +90,6 @@ impl TransferFunctions for BorrowSafety { impl AbstractInterpreter for BorrowSafety {} pub fn verify( - compilation_env: &mut CompilationEnv, context: &super::CFGContext, cfg: &super::cfg::MutForwardCFG, ) -> BTreeMap { @@ -100,21 +99,17 @@ pub fn verify( let mut safety = BorrowSafety::new(locals); // check for existing errors - let has_errors = compilation_env.has_errors(); + let has_errors = context.env.has_errors(); let mut initial_state = BorrowState::initial(locals, safety.mutably_used.clone(), has_errors); initial_state.bind_arguments(&signature.parameters); initial_state.canonicalize_locals(&safety.local_numbers); let (final_state, ds) = safety.analyze_function(cfg, initial_state); - compilation_env.add_diags(ds); - unused_mut_borrows(compilation_env, context, safety.mutably_used); + context.add_diags(ds); + unused_mut_borrows(context, safety.mutably_used); final_state } -fn unused_mut_borrows( - compilation_env: &mut CompilationEnv, - context: &super::CFGContext, - mutably_used: RefExpInfoMap, -) { +fn unused_mut_borrows(context: &super::CFGContext, mutably_used: RefExpInfoMap) { const MSG: &str = "Mutable reference is never used mutably, \ consider switching to an immutable reference '&' instead"; @@ -143,7 +138,7 @@ fn unused_mut_borrows( } else { diag!(UnusedItem::MutReference, (*loc, MSG)) }; - compilation_env.add_diag(diag) + context.add_diag(diag) } } } diff --git a/external-crates/move/crates/move-compiler/src/cfgir/liveness/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/liveness/mod.rs index fd32f21714754..f5aa20f2619b3 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/liveness/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/liveness/mod.rs @@ -13,7 +13,7 @@ use crate::{ diagnostics::Diagnostics, expansion::ast::Mutability, hlir::ast::{self as H, *}, - shared::{unique_map::UniqueMap, CompilationEnv}, + shared::unique_map::UniqueMap, }; use move_ir_types::location::*; use move_proc_macros::growing_stack; @@ -168,11 +168,7 @@ fn exp(state: &mut LivenessState, parent_e: &Exp) { /// - Reports an error if an assignment/let was not used /// Switches it to an `Ignore` if it has the drop ability (helps with error messages for borrows) -pub fn last_usage( - compilation_env: &mut CompilationEnv, - context: &super::CFGContext, - cfg: &mut MutForwardCFG, -) { +pub fn last_usage(context: &super::CFGContext, cfg: &mut MutForwardCFG) { let super::CFGContext { infinite_loop_starts, .. @@ -183,7 +179,7 @@ pub fn last_usage( .get(lbl) .unwrap_or_else(|| panic!("ICE no liveness states for {}", lbl)); let command_states = per_command_states.get(lbl).unwrap(); - last_usage::block(compilation_env, final_invariant, command_states, block) + last_usage::block(context, final_invariant, command_states, block) } } @@ -191,30 +187,29 @@ mod last_usage { use move_proc_macros::growing_stack; use crate::{ - cfgir::liveness::state::LivenessState, + cfgir::{liveness::state::LivenessState, CFGContext}, diag, hlir::{ ast::*, translate::{display_var, DisplayVar}, }, - shared::*, }; use std::collections::{BTreeSet, VecDeque}; struct Context<'a, 'b> { - env: &'a mut CompilationEnv, + outer: &'a CFGContext<'a>, next_live: &'b BTreeSet, dropped_live: BTreeSet, } impl<'a, 'b> Context<'a, 'b> { fn new( - env: &'a mut CompilationEnv, + outer: &'a CFGContext<'a>, next_live: &'b BTreeSet, dropped_live: BTreeSet, ) -> Self { Context { - env, + outer, next_live, dropped_live, } @@ -222,7 +217,7 @@ mod last_usage { } pub fn block( - compilation_env: &mut CompilationEnv, + context: &CFGContext, final_invariant: &LivenessState, command_states: &VecDeque, block: &mut BasicBlock, @@ -245,10 +240,7 @@ mod last_usage { .difference(next_data) .cloned() .collect::>(); - command( - &mut Context::new(compilation_env, next_data, dropped_live), - cmd, - ) + command(&mut Context::new(context, next_data, dropped_live), cmd) } } @@ -300,7 +292,7 @@ mod last_usage { '_{vstr}')", ); context - .env + .outer .add_diag(diag!(UnusedItem::Assignment, (l.loc, msg))); } *unused_assignment = true; diff --git a/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs index 1793e58dc9139..31a302ece25e1 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/locals/mod.rs @@ -6,6 +6,7 @@ pub mod state; use super::absint::*; use crate::{ + cfgir::CFGContext, diag, diagnostics::{Diagnostic, Diagnostics}, editions::Edition, @@ -16,15 +17,10 @@ use crate::{ }, naming::ast::{self as N, TParam}, parser::ast::{Ability_, DatatypeName}, - shared::{ - program_info::{DatatypeKind, TypingProgramInfo}, - unique_map::UniqueMap, - *, - }, + shared::{program_info::DatatypeKind, unique_map::UniqueMap}, }; use move_ir_types::location::*; use move_proc_macros::growing_stack; -use move_symbol_pool::Symbol; use state::*; use std::collections::BTreeMap; @@ -33,9 +29,7 @@ use std::collections::BTreeMap; //************************************************************************************************** struct LocalsSafety<'a> { - env: &'a CompilationEnv, - info: &'a TypingProgramInfo, - package: Option, + context: &'a CFGContext<'a>, local_types: &'a UniqueMap, signature: &'a FunctionSignature, unused_mut: BTreeMap, @@ -43,9 +37,7 @@ struct LocalsSafety<'a> { impl<'a> LocalsSafety<'a> { fn new( - env: &'a CompilationEnv, - info: &'a TypingProgramInfo, - package: Option, + context: &'a CFGContext<'a>, local_types: &'a UniqueMap, signature: &'a FunctionSignature, ) -> Self { @@ -60,9 +52,7 @@ impl<'a> LocalsSafety<'a> { }) .collect(); Self { - env, - info, - package, + context, local_types, signature, unused_mut, @@ -71,9 +61,7 @@ impl<'a> LocalsSafety<'a> { } struct Context<'a, 'b> { - env: &'a CompilationEnv, - info: &'a TypingProgramInfo, - package: Option, + outer: &'a CFGContext<'a>, local_types: &'a UniqueMap, unused_mut: &'a mut BTreeMap, local_states: &'b mut LocalStates, @@ -83,15 +71,12 @@ struct Context<'a, 'b> { impl<'a, 'b> Context<'a, 'b> { fn new(locals_safety: &'a mut LocalsSafety, local_states: &'b mut LocalStates) -> Self { - let env = locals_safety.env; - let info = locals_safety.info; + let outer = locals_safety.context; let local_types = locals_safety.local_types; let signature = locals_safety.signature; let unused_mut = &mut locals_safety.unused_mut; Self { - env, - info, - package: locals_safety.package, + outer, local_types, unused_mut, local_states, @@ -154,18 +139,18 @@ impl<'a, 'b> Context<'a, 'b> { // .unwrap(); fn datatype_decl_loc(&self, m: &ModuleIdent, n: &DatatypeName) -> Loc { - let kind = self.info.datatype_kind(m, n); + let kind = self.outer.info.datatype_kind(m, n); match kind { - DatatypeKind::Struct => self.info.struct_declared_loc(m, n), - DatatypeKind::Enum => self.info.enum_declared_loc(m, n), + DatatypeKind::Struct => self.outer.info.struct_declared_loc(m, n), + DatatypeKind::Enum => self.outer.info.enum_declared_loc(m, n), } } fn datatype_declared_abilities(&self, m: &ModuleIdent, n: &DatatypeName) -> &'a AbilitySet { - let kind = self.info.datatype_kind(m, n); + let kind = self.outer.info.datatype_kind(m, n); match kind { - DatatypeKind::Struct => self.info.struct_declared_abilities(m, n), - DatatypeKind::Enum => self.info.enum_declared_abilities(m, n), + DatatypeKind::Struct => self.outer.info.struct_declared_abilities(m, n), + DatatypeKind::Enum => self.outer.info.enum_declared_abilities(m, n), } } } @@ -189,7 +174,6 @@ impl<'a> TransferFunctions for LocalsSafety<'a> { impl<'a> AbstractInterpreter for LocalsSafety<'a> {} pub fn verify( - compilation_env: &mut CompilationEnv, context: &super::CFGContext, cfg: &super::cfg::MutForwardCFG, ) -> BTreeMap { @@ -197,22 +181,16 @@ pub fn verify( signature, locals, .. } = context; let initial_state = LocalStates::initial(&signature.parameters, locals); - let mut locals_safety = LocalsSafety::new( - compilation_env, - context.info, - context.package, - locals, - signature, - ); + let mut locals_safety = LocalsSafety::new(context, locals, signature); let (final_state, ds) = locals_safety.analyze_function(cfg, initial_state); - unused_let_muts(compilation_env, locals, locals_safety.unused_mut); - compilation_env.add_diags(ds); + unused_let_muts(context, locals, locals_safety.unused_mut); + context.add_diags(ds); final_state } /// Generates warnings for unused mut declarations fn unused_let_muts( - env: &mut CompilationEnv, + context: &CFGContext, locals: &UniqueMap, unused_mut_locals: BTreeMap, ) { @@ -226,7 +204,7 @@ fn unused_let_muts( let decl_loc = *locals.get_loc(&v).unwrap(); let decl_msg = format!("The variable '{vstr}' is never used mutably"); let mut_msg = "Consider removing the 'mut' declaration here"; - env.add_diag(diag!( + context.add_diag(diag!( UnusedItem::MutModifier, (decl_loc, decl_msg), (mut_loc, mut_msg) @@ -524,7 +502,7 @@ fn check_mutability( let usage_msg = format!("Invalid {usage} of immutable variable '{vstr}'"); let decl_msg = format!("To use the variable mutably, it must be declared 'mut', e.g. 'mut {vstr}'"); - if context.env.edition(context.package) == Edition::E2024_MIGRATION { + if context.outer.env.edition(context.outer.package) == Edition::E2024_MIGRATION { context.add_diag(diag!(Migration::NeedsLetMut, (decl_loc, decl_msg.clone()))) } else { let mut diag = diag!( diff --git a/external-crates/move/crates/move-compiler/src/cfgir/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/mod.rs index 958e2a3abb3fc..5acfa3e811f9f 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/mod.rs @@ -17,7 +17,10 @@ mod optimize; use crate::{ expansion::ast::{Attributes, ModuleIdent, Mutability}, hlir::ast::{FunctionSignature, Label, SingleType, Var, Visibility}, - shared::{program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv, Name}, + shared::{ + program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv, Name, + WarningFiltersScope, + }, }; use cfg::*; use move_ir_types::location::Loc; @@ -26,6 +29,8 @@ use optimize::optimize; use std::collections::BTreeSet; pub struct CFGContext<'a> { + pub env: &'a CompilationEnv, + pub warning_filters_scope: WarningFiltersScope, pub info: &'a TypingProgramInfo, pub package: Option, pub module: ModuleIdent, @@ -43,16 +48,22 @@ pub enum MemberName { Function(Name), } -pub fn refine_inference_and_verify( - env: &mut CompilationEnv, - context: &CFGContext, - cfg: &mut MutForwardCFG, -) { - liveness::last_usage(env, context, cfg); - let locals_states = locals::verify(env, context, cfg); +pub fn refine_inference_and_verify(context: &CFGContext, cfg: &mut MutForwardCFG) { + liveness::last_usage(context, cfg); + let locals_states = locals::verify(context, cfg); liveness::release_dead_refs(context, &locals_states, cfg); - borrows::verify(env, context, cfg); + borrows::verify(context, cfg); +} + +impl CFGContext<'_> { + fn add_diag(&self, diag: crate::diagnostics::Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + fn add_diags(&self, diags: crate::diagnostics::Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } } impl MemberName { diff --git a/external-crates/move/crates/move-compiler/src/cfgir/optimize/mod.rs b/external-crates/move/crates/move-compiler/src/cfgir/optimize/mod.rs index db73ab7f19c72..72cd2c0e72ffc 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/optimize/mod.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/optimize/mod.rs @@ -43,7 +43,7 @@ const MOVE_2024_OPTIMIZATIONS: &[Optimization] = &[ #[growing_stack] pub fn optimize( - env: &mut CompilationEnv, + env: &CompilationEnv, package: Option, signature: &FunctionSignature, locals: &UniqueMap, diff --git a/external-crates/move/crates/move-compiler/src/cfgir/translate.rs b/external-crates/move/crates/move-compiler/src/cfgir/translate.rs index 93ec88edf4396..44e1da2b6811d 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/translate.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/translate.rs @@ -10,11 +10,14 @@ use crate::{ visitor::{CFGIRVisitor, CFGIRVisitorConstructor, CFGIRVisitorContext}, }, diag, - diagnostics::Diagnostics, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, expansion::ast::{Attributes, ModuleIdent, Mutability}, hlir::ast::{self as H, BlockLabel, Label, Value, Value_, Var}, + ice_assert, parser::ast::{ConstantName, FunctionName}, - shared::{program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv}, + shared::{ + program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv, WarningFiltersScope, + }, FullyCompiledProgram, }; use cfgir::ast::LoopInfo; @@ -42,8 +45,9 @@ enum NamedBlockType { } struct Context<'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, info: &'env TypingProgramInfo, + warning_filters_scope: WarningFiltersScope, current_package: Option, label_count: usize, named_blocks: UniqueMap, @@ -52,9 +56,11 @@ struct Context<'env> { } impl<'env> Context<'env> { - pub fn new(env: &'env mut CompilationEnv, info: &'env TypingProgramInfo) -> Self { + pub fn new(env: &'env CompilationEnv, info: &'env TypingProgramInfo) -> Self { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, info, current_package: None, label_count: 0, @@ -63,6 +69,22 @@ impl<'env> Context<'env> { } } + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } + fn new_label(&mut self) -> Label { let count = self.label_count; self.label_count += 1; @@ -121,7 +143,7 @@ impl<'env> Context<'env> { //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, _pre_compiled_lib: Option>, prog: H::Program, ) -> G::Program { @@ -170,10 +192,10 @@ fn module( constants: hconstants, } = mdef; context.current_package = package_name; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let constants = constants(context, module_ident, hconstants); let functions = hfunctions.map(|name, f| function(context, module_ident, name, f)); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); context.current_package = None; ( module_ident, @@ -238,7 +260,7 @@ fn constants( "Cyclic constant defined here", )); } - context.env.add_diag(diag); + context.add_diag(diag); cycle_nodes.append(&mut scc.into_iter().collect()); } } @@ -251,7 +273,7 @@ fn constants( .filter(|node| !cycle_nodes.contains(node) && graph.contains_node(*node)) .collect(); for node in neighbors { - context.env.add_diag(diag!( + context.add_diag(diag!( BytecodeGeneration::UnfoldableConstant, ( *consts.get_loc(&node).unwrap(), @@ -402,7 +424,7 @@ fn constant( value: (locals, block), } = c; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let final_value = constant_( context, constant_values, @@ -427,7 +449,7 @@ fn constant( _ => None, }; - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); G::Constant { warning_filter, index, @@ -471,6 +493,8 @@ fn constant_( }; let fake_infinite_loop_starts = BTreeSet::new(); let function_context = super::CFGContext { + env: context.env, + warning_filters_scope: context.warning_filters_scope.clone(), info: context.info, package: context.current_package, module, @@ -482,9 +506,11 @@ fn constant_( locals: &locals, infinite_loop_starts: &fake_infinite_loop_starts, }; - cfgir::refine_inference_and_verify(context.env, &function_context, &mut cfg); - assert!( + cfgir::refine_inference_and_verify(&function_context, &mut cfg); + ice_assert!( + context.env, num_previous_errors == context.env.count_diags(), + full_loc, "{}", ICE_MSG ); @@ -498,7 +524,7 @@ fn constant_( ); if blocks.len() != 1 { - context.env.add_diag(diag!( + context.add_diag(diag!( BytecodeGeneration::UnfoldableConstant, (full_loc, CANNOT_FOLD) )); @@ -510,7 +536,7 @@ fn constant_( let e = match cmd_ { C::IgnoreAndPop { exp, .. } => exp, _ => { - context.env.add_diag(diag!( + context.add_diag(diag!( BytecodeGeneration::UnfoldableConstant, (*cloc, CANNOT_FOLD) )); @@ -532,7 +558,7 @@ fn check_constant_value(context: &mut Context, e: &H::Exp) { use H::UnannotatedExp_ as E; match &e.exp.value { E::Value(_) => (), - _ => context.env.add_diag(diag!( + _ => context.add_diag(diag!( BytecodeGeneration::UnfoldableConstant, (e.exp.loc, CANNOT_FOLD) )), @@ -579,7 +605,7 @@ fn function( signature, body, } = f; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let body = function_body( context, module, @@ -590,7 +616,7 @@ fn function( &signature, body, ); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); G::Function { warning_filter, index, @@ -627,9 +653,11 @@ fn function_body( let (mut cfg, infinite_loop_starts, diags) = MutForwardCFG::new(start, &mut blocks, binfo); - context.env.add_diags(diags); + context.add_diags(diags); let function_context = super::CFGContext { + env: context.env, + warning_filters_scope: context.warning_filters_scope.clone(), info: context.info, package: context.current_package, module, @@ -641,7 +669,7 @@ fn function_body( locals: &locals, infinite_loop_starts: &infinite_loop_starts, }; - cfgir::refine_inference_and_verify(context.env, &function_context, &mut cfg); + cfgir::refine_inference_and_verify(&function_context, &mut cfg); // do not optimize if there are errors, warnings are okay if !context.env.has_errors() { cfgir::optimize( @@ -977,7 +1005,8 @@ fn visit_program(context: &mut Context, prog: &mut G::Program) { struct AbsintVisitor; struct AbsintVisitorContext<'a> { - env: &'a mut CompilationEnv, + env: &'a CompilationEnv, + warning_filters_scope: WarningFiltersScope, info: Arc, current_package: Option, } @@ -985,22 +1014,35 @@ struct AbsintVisitorContext<'a> { impl CFGIRVisitorConstructor for AbsintVisitor { type Context<'a> = AbsintVisitorContext<'a>; - fn context<'a>(env: &'a mut CompilationEnv, program: &G::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a CompilationEnv, program: &G::Program) -> Self::Context<'a> { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); AbsintVisitorContext { env, + warning_filters_scope, info: program.info.clone(), current_package: None, } } } +impl AbsintVisitorContext<'_> { + #[allow(unused)] + fn add_diag(&self, diag: crate::diagnostics::Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + fn add_diags(&self, diags: crate::diagnostics::Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } +} + impl<'a> CFGIRVisitorContext for AbsintVisitorContext<'a> { - fn add_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { - self.env.add_warning_filter_scope(filter) + fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } fn visit_module_custom(&mut self, _ident: ModuleIdent, mdef: &G::ModuleDefinition) -> bool { @@ -1035,6 +1077,8 @@ impl<'a> CFGIRVisitorContext for AbsintVisitorContext<'a> { }; let (cfg, infinite_loop_starts) = ImmForwardCFG::new(*start, blocks, block_info.iter()); let function_context = super::CFGContext { + env: self.env, + warning_filters_scope: self.warning_filters_scope.clone(), info: &self.info, package: self.current_package, module: mident, @@ -1048,9 +1092,9 @@ impl<'a> CFGIRVisitorContext for AbsintVisitorContext<'a> { }; let mut ds = Diagnostics::new(); for v in &self.env.visitors().abs_int { - ds.extend(v.verify(self.env, &function_context, &cfg)); + ds.extend(v.verify(&function_context, &cfg)); } - self.env.add_diags(ds); + self.add_diags(ds); true } } diff --git a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs index d3fbe72d438a0..4482e1c924d26 100644 --- a/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/cfgir/visitor.rs @@ -24,7 +24,7 @@ pub type AbsIntVisitorObj = Box; pub type CFGIRVisitorObj = Box; pub trait CFGIRVisitor: Send + Sync { - fn visit(&self, env: &mut CompilationEnv, program: &G::Program); + fn visit(&self, env: &CompilationEnv, program: &G::Program); fn visitor(self) -> Visitor where @@ -35,12 +35,7 @@ pub trait CFGIRVisitor: Send + Sync { } pub trait AbstractInterpreterVisitor: Send + Sync { - fn verify( - &self, - env: &CompilationEnv, - context: &CFGContext, - cfg: &ImmForwardCFG, - ) -> Diagnostics; + fn verify(&self, context: &CFGContext, cfg: &ImmForwardCFG) -> Diagnostics; fn visitor(self) -> Visitor where @@ -57,16 +52,16 @@ pub trait AbstractInterpreterVisitor: Send + Sync { pub trait CFGIRVisitorConstructor: Send { type Context<'a>: Sized + CFGIRVisitorContext; - fn context<'a>(env: &'a mut CompilationEnv, program: &G::Program) -> Self::Context<'a>; + fn context<'a>(env: &'a CompilationEnv, program: &G::Program) -> Self::Context<'a>; - fn visit(env: &mut CompilationEnv, program: &G::Program) { + fn visit(env: &CompilationEnv, program: &G::Program) { let mut context = Self::context(env, program); context.visit(program); } } pub trait CFGIRVisitorContext { - fn add_warning_filter_scope(&mut self, filters: WarningFilters); + fn push_warning_filter_scope(&mut self, filters: WarningFilters); fn pop_warning_filter_scope(&mut self); fn visit_module_custom(&mut self, _ident: ModuleIdent, _mdef: &G::ModuleDefinition) -> bool { @@ -78,7 +73,7 @@ pub trait CFGIRVisitorContext { /// required. fn visit(&mut self, program: &G::Program) { for (mident, mdef) in program.modules.key_cloned_iter() { - self.add_warning_filter_scope(mdef.warning_filter.clone()); + self.push_warning_filter_scope(mdef.warning_filter.clone()); if self.visit_module_custom(mident, mdef) { self.pop_warning_filter_scope(); continue; @@ -117,7 +112,7 @@ pub trait CFGIRVisitorContext { struct_name: DatatypeName, sdef: &H::StructDefinition, ) { - self.add_warning_filter_scope(sdef.warning_filter.clone()); + self.push_warning_filter_scope(sdef.warning_filter.clone()); if self.visit_struct_custom(module, struct_name, sdef) { self.pop_warning_filter_scope(); return; @@ -139,7 +134,7 @@ pub trait CFGIRVisitorContext { enum_name: DatatypeName, edef: &H::EnumDefinition, ) { - self.add_warning_filter_scope(edef.warning_filter.clone()); + self.push_warning_filter_scope(edef.warning_filter.clone()); if self.visit_enum_custom(module, enum_name, edef) { self.pop_warning_filter_scope(); return; @@ -161,7 +156,7 @@ pub trait CFGIRVisitorContext { constant_name: ConstantName, cdef: &G::Constant, ) { - self.add_warning_filter_scope(cdef.warning_filter.clone()); + self.push_warning_filter_scope(cdef.warning_filter.clone()); if self.visit_constant_custom(module, constant_name, cdef) { self.pop_warning_filter_scope(); return; @@ -183,7 +178,7 @@ pub trait CFGIRVisitorContext { function_name: FunctionName, fdef: &G::Function, ) { - self.add_warning_filter_scope(fdef.warning_filter.clone()); + self.push_warning_filter_scope(fdef.warning_filter.clone()); if self.visit_function_custom(module, function_name, fdef) { self.pop_warning_filter_scope(); return; @@ -322,7 +317,7 @@ impl From for CFGIRVisitorObj { } impl CFGIRVisitor for V { - fn visit(&self, env: &mut CompilationEnv, program: &G::Program) { + fn visit(&self, env: &CompilationEnv, program: &G::Program) { Self::visit(env, program) } } @@ -332,38 +327,41 @@ macro_rules! simple_visitor { pub struct $visitor; pub struct Context<'a> { - env: &'a mut crate::shared::CompilationEnv, + env: &'a crate::shared::CompilationEnv, + warning_filters_scope: crate::shared::WarningFiltersScope, } impl crate::cfgir::visitor::CFGIRVisitorConstructor for $visitor { type Context<'a> = Context<'a>; - fn context<'a>(env: &'a mut crate::shared::CompilationEnv, _program: &crate::cfgir::ast::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a crate::shared::CompilationEnv, _program: &crate::cfgir::ast::Program) -> Self::Context<'a> { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, } } } impl Context<'_> { #[allow(unused)] - fn add_diag(&mut self, diag: crate::diagnostics::Diagnostic) { - self.env.add_diag(diag); + fn add_diag(&self, diag: crate::diagnostics::Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); } #[allow(unused)] - fn add_diags(&mut self, diags: crate::diagnostics::Diagnostics) { - self.env.add_diags(diags); + fn add_diags(&self, diags: crate::diagnostics::Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); } } impl crate::cfgir::visitor::CFGIRVisitorContext for Context<'_> { - fn add_warning_filter_scope(&mut self, filters: crate::diagnostics::WarningFilters) { - self.env.add_warning_filter_scope(filters) + fn push_warning_filter_scope(&mut self, filters: crate::diagnostics::WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } $($overrides)* @@ -493,13 +491,12 @@ pub trait SimpleAbsIntConstructor: Sized { /// Given the initial state/domain, construct a new abstract interpreter. /// Return None if it should not be run given this context fn new<'a>( - env: &CompilationEnv, context: &'a CFGContext<'a>, cfg: &ImmForwardCFG, init_state: &mut as SimpleAbsInt>::State, ) -> Option>; - fn verify(env: &CompilationEnv, context: &CFGContext, cfg: &ImmForwardCFG) -> Diagnostics { + fn verify(context: &CFGContext, cfg: &ImmForwardCFG) -> Diagnostics { let mut locals = context .locals .key_cloned_iter() @@ -518,7 +515,7 @@ pub trait SimpleAbsIntConstructor: Sized { ); } let mut init_state = as SimpleAbsInt>::State::new(context, locals); - let Some(mut ai) = Self::new(env, context, cfg, &mut init_state) else { + let Some(mut ai) = Self::new(context, cfg, &mut init_state) else { return Diagnostics::new(); }; let (final_state, ds) = ai.analyze_function(cfg, init_state); @@ -805,13 +802,8 @@ impl From for AbsIntVisitorObj { } impl AbstractInterpreterVisitor for V { - fn verify( - &self, - env: &CompilationEnv, - context: &CFGContext, - cfg: &ImmForwardCFG, - ) -> Diagnostics { - ::verify(env, context, cfg) + fn verify(&self, context: &CFGContext, cfg: &ImmForwardCFG) -> Diagnostics { + ::verify(context, cfg) } } diff --git a/external-crates/move/crates/move-compiler/src/command_line/compiler.rs b/external-crates/move/crates/move-compiler/src/command_line/compiler.rs index 5ab1794628a81..795fdb940a99f 100644 --- a/external-crates/move/crates/move-compiler/src/command_line/compiler.rs +++ b/external-crates/move/crates/move-compiler/src/command_line/compiler.rs @@ -376,17 +376,19 @@ impl Compiler { interface_files_dir_opt, &compiled_module_named_address_mapping, )?; - let mut compilation_env = - CompilationEnv::new(flags, visitors, save_hooks, package_configs, default_config); - if let Some(filter) = warning_filter { - compilation_env.add_warning_filter_scope(filter); - } + let mut compilation_env = CompilationEnv::new( + flags, + visitors, + save_hooks, + warning_filter, + package_configs, + default_config, + ); for (prefix, filters) in known_warning_filters { compilation_env.add_custom_known_filters(prefix, filters)?; } - let (source_text, pprog, comments) = - parse_program(&mut compilation_env, maps, targets, deps)?; + let (source_text, pprog, comments) = parse_program(&compilation_env, maps, targets, deps)?; for (fhash, (fname, contents)) in &source_text { // TODO better support for bytecode interface file paths @@ -480,12 +482,12 @@ impl SteppedCompiler

{ "Invalid pass for run_to. Target pass precedes the current pass" ); let Self { - mut compilation_env, + compilation_env, pre_compiled_lib, program, } = self; let new_prog = run( - &mut compilation_env, + &compilation_env, pre_compiled_lib.clone(), program.unwrap(), TARGET, @@ -498,10 +500,7 @@ impl SteppedCompiler

{ }) } - pub fn compilation_env(&mut self) -> &mut CompilationEnv { - &mut self.compilation_env - } - pub fn compilation_env_ref(&self) -> &CompilationEnv { + pub fn compilation_env(&self) -> &CompilationEnv { &self.compilation_env } } @@ -657,9 +656,9 @@ pub fn construct_pre_compiled_lib, NamedAddress: Into Ok(Err((files, errors))), Ok(PassResult::Compilation(compiled, _)) => Ok(Ok(FullyCompiledProgram { files, @@ -886,7 +885,7 @@ pub fn move_check_for_errors( ) -> Result<(Vec, Diagnostics), (Pass, Diagnostics)> { let (_, compiler) = comments_and_compiler_res?; - let (mut compiler, cfgir) = compiler.run::()?.into_ast(); + let (compiler, cfgir) = compiler.run::()?.into_ast(); let compilation_env = compiler.compilation_env(); if compilation_env.flags().is_testing() { unit_test::plan_builder::construct_test_plan(compilation_env, None, &cfgir); @@ -922,7 +921,7 @@ impl PassResult { } } - pub fn save(&self, compilation_env: &mut CompilationEnv) { + pub fn save(&self, compilation_env: &CompilationEnv) { match self { PassResult::Parser(prog) => { compilation_env.save_parser_ast(prog); @@ -949,14 +948,14 @@ impl PassResult { } fn run( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, cur: PassResult, until: Pass, ) -> Result { #[growing_stack] fn rec( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, cur: PassResult, until: Pass, diff --git a/external-crates/move/crates/move-compiler/src/diagnostics/mod.rs b/external-crates/move/crates/move-compiler/src/diagnostics/mod.rs index 3c7cbe46de462..93d6f878a8a9c 100644 --- a/external-crates/move/crates/move-compiler/src/diagnostics/mod.rs +++ b/external-crates/move/crates/move-compiler/src/diagnostics/mod.rs @@ -776,7 +776,7 @@ macro_rules! ice { macro_rules! ice_assert { ($env: expr, $cond: expr, $loc: expr, $($arg:tt)*) => {{ if !$cond { - $env.add_diag($crate::ice!(( + $env.add_error_diag($crate::ice!(( $loc, format!($($arg)*), ))); @@ -798,14 +798,14 @@ pub fn print_stack_trace() { } impl WarningFilters { - pub fn new_for_source() -> Self { + pub const fn new_for_source() -> Self { Self { filters: BTreeMap::new(), for_dependency: false, } } - pub fn new_for_dependency() -> Self { + pub const fn new_for_dependency() -> Self { Self { filters: BTreeMap::new(), for_dependency: true, diff --git a/external-crates/move/crates/move-compiler/src/editions/mod.rs b/external-crates/move/crates/move-compiler/src/editions/mod.rs index 5cfea4d99d59d..910a977791337 100644 --- a/external-crates/move/crates/move-compiler/src/editions/mod.rs +++ b/external-crates/move/crates/move-compiler/src/editions/mod.rs @@ -72,13 +72,13 @@ pub const UPGRADE_NOTE: &str = /// Returns true if the feature is present in the given edition. /// Adds an error to the environment. pub fn check_feature_or_error( - env: &mut CompilationEnv, + env: &CompilationEnv, edition: Edition, feature: FeatureGate, loc: Loc, ) -> bool { if !edition.supports(feature) { - env.add_diag(create_feature_error(edition, feature, loc)); + env.add_error_diag(create_feature_error(edition, feature, loc)); false } else { true diff --git a/external-crates/move/crates/move-compiler/src/expansion/name_validation.rs b/external-crates/move/crates/move-compiler/src/expansion/name_validation.rs index 1991ab59a7f98..dcd9de94e0d93 100644 --- a/external-crates/move/crates/move-compiler/src/expansion/name_validation.rs +++ b/external-crates/move/crates/move-compiler/src/expansion/name_validation.rs @@ -103,7 +103,7 @@ impl NameCase { #[allow(clippy::result_unit_err)] pub fn check_valid_address_name( - env: &mut CompilationEnv, + env: &CompilationEnv, sp!(_, ln_): &P::LeadingNameAccess, ) -> Result<(), ()> { use P::LeadingNameAccess_ as LN; @@ -120,11 +120,7 @@ pub fn valid_local_variable_name(s: Symbol) -> bool { } #[allow(clippy::result_unit_err)] -pub fn check_valid_function_parameter_name( - env: &mut CompilationEnv, - is_macro: Option, - v: &Var, -) { +pub fn check_valid_function_parameter_name(env: &CompilationEnv, is_macro: Option, v: &Var) { const SYNTAX_IDENTIFIER_NOTE: &str = "'macro' parameters start with '$' to indicate that their arguments are not evaluated \ before the macro is expanded, meaning the entire expression is substituted. \ @@ -144,7 +140,7 @@ pub fn check_valid_function_parameter_name( (macro_loc, macro_msg), ); diag.add_note(SYNTAX_IDENTIFIER_NOTE); - env.add_diag(diag); + env.add_error_diag(diag); } } else if is_syntax_identifier { let msg = format!( @@ -153,26 +149,26 @@ pub fn check_valid_function_parameter_name( ); let mut diag = diag!(Declarations::InvalidName, (v.loc(), msg)); diag.add_note(SYNTAX_IDENTIFIER_NOTE); - env.add_diag(diag); + env.add_error_diag(diag); } else if !is_valid_local_variable_name(v.value()) { let msg = format!( "Invalid parameter name '{}'. Local variable names must start with 'a'..'z', '_', \ or be a valid name quoted with backticks (`name`)", v, ); - env.add_diag(diag!(Declarations::InvalidName, (v.loc(), msg))); + env.add_error_diag(diag!(Declarations::InvalidName, (v.loc(), msg))); } let _ = check_restricted_name_all_cases(env, NameCase::Variable, &v.0); } -pub fn check_valid_local_name(env: &mut CompilationEnv, v: &Var) { +pub fn check_valid_local_name(env: &CompilationEnv, v: &Var) { if !is_valid_local_variable_name(v.value()) { let msg = format!( "Invalid local name '{}'. Local variable names must start with 'a'..'z', '_', \ or be a valid name quoted with backticks (`name`)", v, ); - env.add_diag(diag!(Declarations::InvalidName, (v.loc(), msg))); + env.add_error_diag(diag!(Declarations::InvalidName, (v.loc(), msg))); } let _ = check_restricted_name_all_cases(env, NameCase::Variable, &v.0); } @@ -182,7 +178,7 @@ fn is_valid_local_variable_name(s: Symbol) -> bool { } pub fn check_valid_module_member_name( - env: &mut CompilationEnv, + env: &CompilationEnv, member: ModuleMemberKind, name: Name, ) -> Option { @@ -193,7 +189,7 @@ pub fn check_valid_module_member_name( } pub fn check_valid_module_member_alias( - env: &mut CompilationEnv, + env: &CompilationEnv, member: ModuleMemberKind, alias: Name, ) -> Option { @@ -209,7 +205,7 @@ pub fn check_valid_module_member_alias( } fn check_valid_module_member_name_impl( - env: &mut CompilationEnv, + env: &CompilationEnv, member: ModuleMemberKind, n: &Name, case: NameCase, @@ -231,7 +227,7 @@ fn check_valid_module_member_name_impl( n, upper_first_letter(case.name()), ); - env.add_diag(diag!(Declarations::InvalidName, (n.loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidName, (n.loc, msg))); return Err(()); } } @@ -243,7 +239,7 @@ fn check_valid_module_member_name_impl( n, upper_first_letter(case.name()), ); - env.add_diag(diag!(Declarations::InvalidName, (n.loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidName, (n.loc, msg))); return Err(()); } } @@ -272,14 +268,14 @@ fn check_valid_module_member_name_impl( #[allow(clippy::result_unit_err)] pub fn check_valid_type_parameter_name( - env: &mut CompilationEnv, + env: &CompilationEnv, is_macro: Option, n: &Name, ) -> Result<(), ()> { // TODO move these names to a more central place? if n.value == symbol!("_") { let diag = restricted_name_error(NameCase::TypeParameter, n.loc, "_"); - env.add_diag(diag); + env.add_error_diag(diag); return Err(()); } @@ -302,7 +298,7 @@ pub fn check_valid_type_parameter_name( (macro_loc, macro_msg), ); diag.add_note(SYNTAX_IDENTIFIER_NOTE); - env.add_diag(diag); + env.add_error_diag(diag); } else { let next_char = n.value.chars().nth(1).unwrap(); if !next_char.is_ascii_alphabetic() { @@ -314,7 +310,7 @@ pub fn check_valid_type_parameter_name( ); let mut diag = diag!(Declarations::InvalidName, (n.loc, msg)); diag.add_note(SYNTAX_IDENTIFIER_NOTE); - env.add_diag(diag); + env.add_error_diag(diag); } } } else if is_syntax_ident { @@ -325,7 +321,7 @@ pub fn check_valid_type_parameter_name( ); let mut diag = diag!(Declarations::InvalidName, (n.loc, msg)); diag.add_note(SYNTAX_IDENTIFIER_NOTE); - env.add_diag(diag); + env.add_error_diag(diag); } // TODO move these names to a more central place? @@ -353,7 +349,7 @@ pub fn is_valid_datatype_or_constant_name(s: &str) -> bool { // Checks for a restricted name in any decl case // Self and vector are not allowed pub fn check_restricted_name_all_cases( - env: &mut CompilationEnv, + env: &CompilationEnv, case: NameCase, n: &Name, ) -> Result<(), ()> { @@ -373,7 +369,7 @@ pub fn check_restricted_name_all_cases( case.name(), n, ); - env.add_diag(diag!(Declarations::InvalidName, (n.loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidName, (n.loc, msg))); return Err(()); } } @@ -385,7 +381,7 @@ pub fn check_restricted_name_all_cases( if n_str == ModuleName::SELF_NAME || (!can_be_vector && n_str == crate::naming::ast::BuiltinTypeName_::VECTOR) { - env.add_diag(restricted_name_error(case, n.loc, n_str)); + env.add_error_diag(restricted_name_error(case, n.loc, n_str)); Err(()) } else { Ok(()) @@ -393,13 +389,13 @@ pub fn check_restricted_name_all_cases( } fn check_restricted_names( - env: &mut CompilationEnv, + env: &CompilationEnv, case: NameCase, sp!(loc, n_): &Name, all_names: &BTreeSet, ) -> Result<(), ()> { if all_names.contains(n_) { - env.add_diag(restricted_name_error(case, *loc, n_)); + env.add_error_diag(restricted_name_error(case, *loc, n_)); Err(()) } else { Ok(()) diff --git a/external-crates/move/crates/move-compiler/src/expansion/path_expander.rs b/external-crates/move/crates/move-compiler/src/expansion/path_expander.rs index 70e7cde321745..3c5c2ebadd262 100644 --- a/external-crates/move/crates/move-compiler/src/expansion/path_expander.rs +++ b/external-crates/move/crates/move-compiler/src/expansion/path_expander.rs @@ -247,7 +247,7 @@ impl Move2024PathExpander { NR::Address(name.loc, make_address(context, name, name.loc, address)) } Some(AliasEntry::TypeParam(_)) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( name.loc, "ICE alias map misresolved name as type param" ))); @@ -270,7 +270,7 @@ impl Move2024PathExpander { NR::ModuleAccess(name.loc, mident, mem) } AliasEntry::TypeParam(_) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( name.loc, "ICE alias map misresolved name as type param" ))); @@ -318,7 +318,7 @@ impl Move2024PathExpander { .join(","); diag.add_note(format!("Type arguments are used with the enum, as '{mident}::{name}<{tys}>::{variant}'")) } - context.env.add_diag(diag); + context.add_diag(diag); } } } @@ -326,7 +326,7 @@ impl Move2024PathExpander { fn check_is_macro(context: &mut DefnContext, is_macro: &Option, result: &NR) { if let NR::Address(_, _) | NR::ModuleIdent(_, _) = result { if let Some(loc) = is_macro { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::InvalidTypeParameter, ( *loc, @@ -385,7 +385,7 @@ impl Move2024PathExpander { && root.tyargs.is_none() => { if let Some(address) = top_level_address_opt(context, root.name) { - context.env.add_diag(diag!( + context.add_diag(diag!( Migration::NeedsGlobalQualification, (root.name.loc, "Must globally qualify name") )); @@ -467,9 +467,7 @@ impl Move2024PathExpander { is_macro = entry.is_macro; } NR::UnresolvedName(_, _) => { - context - .env - .add_diag(ice!((loc, "ICE access chain expansion failed"))); + context.add_diag(ice!((loc, "ICE access chain expansion failed"))); break; } NR::ResolutionFailure(_, _) => break, @@ -553,7 +551,6 @@ impl PathExpander for Move2024PathExpander { m_res.err_name() ); context - .env .add_diag(diag!(Attributes::AmbiguousAttributeValue, (loc, msg))); return None; } @@ -561,7 +558,7 @@ impl PathExpander for Move2024PathExpander { match result { NR::ModuleIdent(_, mident) => { if context.module_members.get(&mident).is_none() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, (loc, format!("Unbound module '{}'", mident)) )); @@ -581,11 +578,11 @@ impl PathExpander for Move2024PathExpander { } NR::Address(_, a) => EV::Address(a), result @ NR::ResolutionFailure(_, _) => { - context.env.add_diag(access_chain_resolution_error(result)); + context.add_diag(access_chain_resolution_error(result)); return None; } NR::IncompleteChain(loc) => { - context.env.add_diag(access_chain_incomplete_error(loc)); + context.add_diag(access_chain_incomplete_error(loc)); return None; } } @@ -628,7 +625,7 @@ impl PathExpander for Move2024PathExpander { access, ); diag.add_note("Variants may not be used as types. Use the enum instead."); - context.env.add_diag(diag); + context.add_diag(diag); // We could try to use the member access to try to keep going. return None; } @@ -637,7 +634,7 @@ impl PathExpander for Move2024PathExpander { (access, tyargs, is_macro) } NR::Address(_, _) => { - context.env.add_diag(unexpected_access_error( + context.add_diag(unexpected_access_error( resolved_name.loc(), resolved_name.name(), access, @@ -658,15 +655,15 @@ impl PathExpander for Move2024PathExpander { base_str, realized_str )); } - context.env.add_diag(diag); + context.add_diag(diag); return None; } result @ NR::ResolutionFailure(_, _) => { - context.env.add_diag(access_chain_resolution_error(result)); + context.add_diag(access_chain_resolution_error(result)); return None; } NR::IncompleteChain(loc) => { - context.env.add_diag(access_chain_incomplete_error(loc)); + context.add_diag(access_chain_incomplete_error(loc)); return None; } } @@ -692,7 +689,7 @@ impl PathExpander for Move2024PathExpander { (access, tyargs, is_macro) } NR::Address(_, _) | NR::ModuleIdent(_, _) => { - context.env.add_diag(unexpected_access_error( + context.add_diag(unexpected_access_error( resolved_name.loc(), resolved_name.name(), access, @@ -700,18 +697,18 @@ impl PathExpander for Move2024PathExpander { return None; } result @ NR::ResolutionFailure(_, _) => { - context.env.add_diag(access_chain_resolution_error(result)); + context.add_diag(access_chain_resolution_error(result)); return None; } NR::IncompleteChain(loc) => { - context.env.add_diag(access_chain_incomplete_error(loc)); + context.add_diag(access_chain_incomplete_error(loc)); return None; } } } }, Access::Module => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "ICE module access should never resolve to a module member" ))); @@ -734,11 +731,11 @@ impl PathExpander for Move2024PathExpander { match resolved_name { NR::ModuleIdent(_, mident) => Some(mident), NR::UnresolvedName(_, name) => { - context.env.add_diag(unbound_module_error(name)); + context.add_diag(unbound_module_error(name)); None } NR::Address(_, _) => { - context.env.add_diag(unexpected_access_error( + context.add_diag(unexpected_access_error( resolved_name.loc(), "address".to_string(), Access::Module, @@ -746,7 +743,7 @@ impl PathExpander for Move2024PathExpander { None } NR::ModuleAccess(_, _, _) | NR::Variant(_, _, _) => { - context.env.add_diag(unexpected_access_error( + context.add_diag(unexpected_access_error( resolved_name.loc(), "module member".to_string(), Access::Module, @@ -754,11 +751,11 @@ impl PathExpander for Move2024PathExpander { None } result @ NR::ResolutionFailure(_, _) => { - context.env.add_diag(access_chain_resolution_error(result)); + context.add_diag(access_chain_resolution_error(result)); None } NR::IncompleteChain(loc) => { - context.env.add_diag(access_chain_incomplete_error(loc)); + context.add_diag(access_chain_incomplete_error(loc)); None } } @@ -767,9 +764,7 @@ impl PathExpander for Move2024PathExpander { fn ide_autocomplete_suggestion(&mut self, context: &mut DefnContext, loc: Loc) { if context.env.ide_mode() { let info = self.aliases.get_ide_alias_information(); - context - .env - .add_ide_annotation(loc, IDEAnnotation::PathAutocompleteInfo(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::PathAutocompleteInfo(Box::new(info))); } } } @@ -934,7 +929,7 @@ impl PathExpander for LegacyPathExpander { let sp!(_, mident_) = self.aliases.module_alias_get(&name).unwrap(); let mident = sp(ident_loc, mident_); if context.module_members.get(&mident).is_none() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, (ident_loc, format!("Unbound module '{}'", mident)) )); @@ -949,7 +944,7 @@ impl PathExpander for LegacyPathExpander { let addr = Address::anonymous(*aloc, *a); let mident = sp(ident_loc, ModuleIdent_::new(addr, ModuleName(n.name))); if context.module_members.get(&mident).is_none() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, (ident_loc, format!("Unbound module '{}'", mident)) )); @@ -971,7 +966,7 @@ impl PathExpander for LegacyPathExpander { let mident = sp(ident_loc, ModuleIdent_::new(addr, ModuleName(n2.name))); if context.module_members.get(&mident).is_none() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, (ident_loc, format!("Unbound module '{}'", mident)) )); @@ -1007,7 +1002,7 @@ impl PathExpander for LegacyPathExpander { let tn_: ModuleAccessResult = match (access, ptn_) { (Access::Pattern, _) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Attempted to expand a variant with the legacy path expander" ))); @@ -1042,7 +1037,7 @@ impl PathExpander for LegacyPathExpander { make_access_result(sp(name.loc, EN::Name(name)), tyargs, is_macro) } (Access::Module, single_entry!(_name, _tyargs, _is_macro)) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "ICE path resolution produced an impossible path for a module" ))); @@ -1056,7 +1051,7 @@ impl PathExpander for LegacyPathExpander { // Error cases (sp!(aloc, LN::AnonymousAddress(_)), [_]) => { let diag = unexpected_address_module_error(loc, *aloc, access); - context.env.add_diag(diag); + context.add_diag(diag); return None; } (sp!(_aloc, LN::GlobalAddress(_)), [_]) => { @@ -1069,7 +1064,7 @@ impl PathExpander for LegacyPathExpander { loc, "Paths that start with `::` are not valid in legacy move.", )); - context.env.add_diag(diag); + context.add_diag(diag); return None; } // Others @@ -1077,7 +1072,7 @@ impl PathExpander for LegacyPathExpander { self.ide_autocomplete_suggestion(context, n1.loc); if let Some(mident) = self.aliases.module_alias_get(n1) { let n2_name = n2.name; - let (tyargs, is_macro) = if !(path.has_tyargs_last()) { + let (tyargs, is_macro) = if !path.has_tyargs_last() { let mut diag = diag!( Syntax::InvalidName, (path.tyargs_loc().unwrap(), "Invalid type argument position") @@ -1085,7 +1080,7 @@ impl PathExpander for LegacyPathExpander { diag.add_note( "Type arguments may only be used with module members", ); - context.env.add_diag(diag); + context.add_diag(diag); (None, path.is_macro()) } else { (path.take_tyargs(), path.is_macro()) @@ -1096,7 +1091,7 @@ impl PathExpander for LegacyPathExpander { is_macro.copied(), ) } else { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, (n1.loc, format!("Unbound module alias '{}'", n1)) )); @@ -1120,7 +1115,7 @@ impl PathExpander for LegacyPathExpander { (path.tyargs_loc().unwrap(), "Invalid type argument position") ); diag.add_note("Type arguments may only be used with module members"); - context.env.add_diag(diag); + context.add_diag(diag); (None, path.is_macro()) } else { (path.take_tyargs(), path.is_macro()) @@ -1129,14 +1124,14 @@ impl PathExpander for LegacyPathExpander { } (_ln, []) => { let diag = ice!((loc, "Found a root path with no additional entries")); - context.env.add_diag(diag); + context.add_diag(diag); return None; } (ln, [_n1, _n2, ..]) => { self.ide_autocomplete_suggestion(context, ln.loc); let mut diag = diag!(Syntax::InvalidName, (loc, "Too many name segments")); diag.add_note("Names may only have 0, 1, or 2 segments separated by '::'"); - context.env.add_diag(diag); + context.add_diag(diag); return None; } } @@ -1157,7 +1152,7 @@ impl PathExpander for LegacyPathExpander { ice_assert!(context.env, single.is_macro.is_none(), loc, "Found macro"); match self.aliases.module_alias_get(&single.name) { None => { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModule, ( single.name.loc, @@ -1182,9 +1177,7 @@ impl PathExpander for LegacyPathExpander { } // Error cases (_ln, []) => { - context - .env - .add_diag(ice!((loc, "Found path with no path entries"))); + context.add_diag(ice!((loc, "Found path with no path entries"))); None } (ln, [n, m, ..]) => { @@ -1199,7 +1192,7 @@ impl PathExpander for LegacyPathExpander { module: ModuleName(n.name), }; let _ = module_ident(context, sp(ident_loc, pmident_)); - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::NamePositionMismatch, if path.entries.len() < 3 { (m.name.loc, "Unexpected module member access. Expected a module identifier only") @@ -1227,7 +1220,7 @@ impl PathExpander for LegacyPathExpander { info.members.insert((*name, *mident, *member)); } let annotation = IDEAnnotation::PathAutocompleteInfo(Box::new(info)); - context.env.add_ide_annotation(loc, annotation) + context.add_ide_annotation(loc, annotation) } } } diff --git a/external-crates/move/crates/move-compiler/src/expansion/primitive_definers.rs b/external-crates/move/crates/move-compiler/src/expansion/primitive_definers.rs index cc1b92013c358..503a7c656fd51 100644 --- a/external-crates/move/crates/move-compiler/src/expansion/primitive_definers.rs +++ b/external-crates/move/crates/move-compiler/src/expansion/primitive_definers.rs @@ -20,7 +20,7 @@ use super::ast::Attribute_; /// Gather primitive defines from module declarations, erroring on duplicates for a given base /// type or for unknown base types. pub fn modules( - env: &mut CompilationEnv, + env: &CompilationEnv, pre_compiled_lib_opt: Option>, modules: &UniqueMap, ) { @@ -49,7 +49,7 @@ pub fn modules( } fn check_prim_definer( - env: &mut CompilationEnv, + env: &CompilationEnv, allow_shadowing: bool, definers: &mut BTreeMap, mident: ModuleIdent, @@ -61,12 +61,16 @@ fn check_prim_definer( let Some(sp!(attr_loc, attr_)) = defines_prim_attr else { return; }; + let warning_filters = env.top_level_warning_filter_scope(); let Attribute_::Parameterized(_, params) = attr_ else { let msg = format!( "Expected a primitive type parameterization, e.g. '{}()'", DefinesPrimitive::DEFINES_PRIM ); - env.add_diag(diag!(Attributes::InvalidUsage, (*attr_loc, msg))); + env.add_diag( + warning_filters, + diag!(Attributes::InvalidUsage, (*attr_loc, msg)), + ); return; }; if params.len() != 1 { @@ -74,7 +78,10 @@ fn check_prim_definer( "Expected a single primitive type parameterization, e.g. '{}()'", DefinesPrimitive::DEFINES_PRIM ); - env.add_diag(diag!(Attributes::InvalidUsage, (*attr_loc, msg))); + env.add_diag( + warning_filters, + diag!(Attributes::InvalidUsage, (*attr_loc, msg)), + ); return; } let (_, _, sp!(param_loc, param_)) = params.into_iter().next().unwrap(); @@ -83,7 +90,10 @@ fn check_prim_definer( "Expected a primitive type parameterization, e.g. '{}()'", DefinesPrimitive::DEFINES_PRIM ); - env.add_diag(diag!(Attributes::InvalidUsage, (*param_loc, msg))); + env.add_diag( + warning_filters, + diag!(Attributes::InvalidUsage, (*param_loc, msg)), + ); return; }; let Some(prim) = BuiltinTypeName_::resolve(name.value.as_str()) else { @@ -92,18 +102,24 @@ fn check_prim_definer( DefinesPrimitive::DEFINES_PRIM, name, ); - env.add_diag(diag!(Attributes::InvalidUsage, (name.loc, msg))); + env.add_diag( + warning_filters, + diag!(Attributes::InvalidUsage, (name.loc, msg)), + ); return; }; if let Some(prev) = definers.get(&prim) { if !allow_shadowing { let msg = format!("Duplicate definer annotated for primitive type '{}'", prim); - env.add_diag(diag!( - Attributes::InvalidUsage, - (*attr_loc, msg), - (prev.loc, "Previously declared here") - )); + env.add_diag( + warning_filters, + diag!( + Attributes::InvalidUsage, + (*attr_loc, msg), + (prev.loc, "Previously declared here") + ), + ); } } else { definers.insert(prim, mident); diff --git a/external-crates/move/crates/move-compiler/src/expansion/translate.rs b/external-crates/move/crates/move-compiler/src/expansion/translate.rs index 4e70132871e6e..b37d555b5994e 100644 --- a/external-crates/move/crates/move-compiler/src/expansion/translate.rs +++ b/external-crates/move/crates/move-compiler/src/expansion/translate.rs @@ -4,7 +4,7 @@ use crate::{ diag, - diagnostics::{codes::WarningFilter, Diagnostic, WarningFilters}, + diagnostics::{codes::WarningFilter, Diagnostic, Diagnostics, WarningFilters}, editions::{self, Edition, FeatureGate, Flavor}, expansion::{ alias_map_builder::{ @@ -33,6 +33,7 @@ use crate::{ NATIVE_MODIFIER, }, shared::{ + ide::{IDEAnnotation, IDEInfo}, known_attributes::AttributePosition, string_utils::{is_pascal_case, is_upper_snake_case}, unique_map::UniqueMap, @@ -65,10 +66,11 @@ type ModuleMembers = BTreeMap; pub(super) struct DefnContext<'env, 'map> { pub(super) named_address_mapping: Option<&'map NamedAddressMap>, pub(super) module_members: UniqueMap, - pub(super) env: &'env mut CompilationEnv, + pub(super) env: &'env CompilationEnv, pub(super) address_conflicts: BTreeSet, pub(super) current_package: Option, pub(super) is_source_definition: bool, + warning_filters_scope: WarningFiltersScope, } struct Context<'env, 'map> { @@ -82,7 +84,7 @@ struct Context<'env, 'map> { impl<'env, 'map> Context<'env, 'map> { fn new( - compilation_env: &'env mut CompilationEnv, + compilation_env: &'env CompilationEnv, module_members: UniqueMap, address_conflicts: BTreeSet, ) -> Self { @@ -92,6 +94,7 @@ impl<'env, 'map> Context<'env, 'map> { all_filter_alls.add(f); } } + let warning_filters_scope = compilation_env.top_level_warning_filter_scope().clone(); let defn_context = DefnContext { env: compilation_env, named_address_mapping: None, @@ -99,6 +102,7 @@ impl<'env, 'map> Context<'env, 'map> { module_members, current_package: None, is_source_definition: false, + warning_filters_scope, }; Context { defn_context, @@ -108,7 +112,7 @@ impl<'env, 'map> Context<'env, 'map> { } } - fn env(&mut self) -> &mut CompilationEnv { + fn env(&mut self) -> &CompilationEnv { self.defn_context.env } @@ -141,7 +145,7 @@ impl<'env, 'map> Context<'env, 'map> { .unwrap() .push_alias_scope(loc, new_scope); match res { - Err(diag) => self.env().add_diag(*diag), + Err(diag) => self.add_diag(*diag), Ok(unnecessaries) => unnecessary_alias_errors(self, unnecessaries), } } @@ -242,7 +246,7 @@ impl<'env, 'map> Context<'env, 'map> { pub fn spec_deprecated(&mut self, loc: Loc, is_error: bool) { let diag = self.spec_deprecated_diag(loc, is_error); - self.env().add_diag(diag); + self.add_diag(diag); } pub fn spec_deprecated_diag(&mut self, loc: Loc, is_error: bool) -> Diagnostic { @@ -258,6 +262,60 @@ impl<'env, 'map> Context<'env, 'map> { ) ) } + + pub fn add_diag(&self, diag: Diagnostic) { + self.defn_context.add_diag(diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.defn_context.add_diags(diags); + } + + #[allow(unused)] + pub fn extend_ide_info(&self, info: IDEInfo) { + self.defn_context.extend_ide_info(info); + } + + #[allow(unused)] + pub fn add_ide_annotation(&self, loc: Loc, info: IDEAnnotation) { + self.defn_context.add_ide_annotation(loc, info); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.defn_context.push_warning_filter_scope(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.defn_context.pop_warning_filter_scope() + } +} + +impl DefnContext<'_, '_> { + pub(super) fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + pub(super) fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub(super) fn extend_ide_info(&self, info: IDEInfo) { + self.env.extend_ide_info(&self.warning_filters_scope, info); + } + + pub(super) fn add_ide_annotation(&self, loc: Loc, info: IDEAnnotation) { + self.env + .add_ide_annotation(&self.warning_filters_scope, loc, info); + } + + pub(super) fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub(super) fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } } fn unnecessary_alias_errors(context: &mut Context, unnecessaries: Vec) { @@ -297,7 +355,7 @@ fn unnecessary_alias_error(context: &mut Context, unnecessary: UnnecessaryAlias) // nothing to point to for the default case diag.add_secondary_label((prev, "The same alias was previously declared here")) } - context.env().add_diag(diag); + context.add_diag(diag); } /// We mark named addresses as having a conflict if there is not a bidirectional mapping between @@ -402,12 +460,13 @@ fn default_aliases(context: &mut Context) -> AliasMapBuilder { //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: P::Program, ) -> E::Program { let address_conflicts = compute_address_conflicts(pre_compiled_lib.clone(), &prog); + let warning_filters_scope = compilation_env.top_level_warning_filter_scope().clone(); let mut member_computation_context = DefnContext { env: compilation_env, named_address_mapping: None, @@ -415,6 +474,7 @@ pub fn program( address_conflicts, current_package: None, is_source_definition: false, + warning_filters_scope, }; let module_members = { @@ -477,7 +537,7 @@ pub fn program( // should never fail if let Err(diag) = path_expander.push_alias_scope(Loc::invalid(), aliases) { - context.env().add_diag(*diag); + context.add_diag(*diag); } context.defn_context.named_address_mapping = Some(named_address_map); @@ -511,7 +571,7 @@ pub fn program( let aliases = named_addr_map_to_alias_map_builder(&mut context, named_address_map); // should never fail if let Err(diag) = path_expander.push_alias_scope(Loc::invalid(), aliases) { - context.env().add_diag(*diag); + context.add_diag(*diag); } context.defn_context.named_address_mapping = Some(named_address_map); context.path_expander = Some(Box::new(path_expander)); @@ -611,7 +671,7 @@ fn top_level_address_( // This should have been handled elsewhere in alias resolution for user-provided paths, and // should never occur in compiler-generated ones. P::LeadingNameAccess_::GlobalAddress(name) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Found an address in top-level address position that uses a global name" ))); @@ -622,7 +682,7 @@ fn top_level_address_( Some(addr) => make_address(context, name, loc, addr), None => { if name_res.is_ok() { - context.env.add_diag(address_without_value_error( + context.add_diag(address_without_value_error( suggest_declaration, loc, &name, @@ -650,7 +710,7 @@ pub(super) fn top_level_address_opt( // This should have been handled elsewhere in alias resolution for user-provided paths, and // should never occur in compiler-generated ones. P::LeadingNameAccess_::GlobalAddress(_) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Found an address in top-level address position that uses a global name" ))); @@ -730,7 +790,7 @@ fn check_module_address( } else { "Multiple addresses specified for module" }; - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (other_loc, msg), (loc, "Address previously specified here") @@ -750,7 +810,7 @@ fn duplicate_module( let old_mident = module_map.get_key(&mident).unwrap(); let dup_msg = format!("Duplicate definition for module '{}'", mident); let prev_msg = format!("Module previously defined here, with '{}'", old_mident); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (mident.loc, dup_msg), (old_loc, prev_msg), @@ -791,9 +851,7 @@ fn set_module_address( address 'module

::{}''", module_name ); - context - .env() - .add_diag(diag!(Declarations::InvalidModule, (loc, msg))); + context.add_diag(diag!(Declarations::InvalidModule, (loc, msg))); Address::anonymous(loc, NumericalAddress::DEFAULT_ERROR_ADDRESS) } }) @@ -819,9 +877,7 @@ fn module_( let config = context.env().package_config(package_name); warning_filter.union(&config.warning_filter); - context - .env() - .add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); assert!(context.address.is_none()); assert!(address.is_none()); set_module_address(context, &name, module_address); @@ -831,9 +887,7 @@ fn module_( "Invalid module name '{}'. Module names cannot start with '_'", name, ); - context - .env() - .add_diag(diag!(Declarations::InvalidName, (name.loc(), msg))); + context.add_diag(diag!(Declarations::InvalidName, (name.loc(), msg))); } let name_loc = name.0.loc; @@ -906,7 +960,7 @@ fn module_( functions, warning_filter, }; - context.env().pop_warning_filter_scope(); + context.pop_warning_filter_scope(); (current_module, def) } @@ -936,15 +990,13 @@ fn check_visibility_modifiers( let loc = friend_decl.loc; let diag = if edition == Edition::E2024_MIGRATION { for aloc in &friend_decl.attr_locs { - context - .env() - .add_diag(diag!(Migration::RemoveFriend, (*aloc, friend_msg))); + context.add_diag(diag!(Migration::RemoveFriend, (*aloc, friend_msg))); } diag!(Migration::RemoveFriend, (loc, friend_msg)) } else { diag!(Editions::DeprecatedFeature, (loc, friend_msg)) }; - context.env().add_diag(diag); + context.add_diag(diag); } for (_, _, function) in functions { let E::Visibility::Friend(loc) = function.visibility else { @@ -955,7 +1007,7 @@ fn check_visibility_modifiers( } else { diag!(Editions::DeprecatedFeature, (loc, pub_msg)) }; - context.env().add_diag(diag); + context.add_diag(diag); } } @@ -985,7 +1037,7 @@ fn check_visibility_modifiers( ); let package_definition_msg = format!("'{}' visibility used here", E::Visibility::PACKAGE); for (_, _, friend) in friends { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidVisibilityModifier, (friend.loc, friend_error_msg.clone()), ( @@ -1007,7 +1059,7 @@ fn check_visibility_modifiers( for (_, _, function) in functions { match function.visibility { E::Visibility::Friend(loc) => { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidVisibilityModifier, (loc, friend_error_msg.clone()), ( @@ -1017,7 +1069,7 @@ fn check_visibility_modifiers( )); } E::Visibility::Package(loc) => { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidVisibilityModifier, (loc, package_error_msg.clone()), ( @@ -1058,9 +1110,7 @@ fn known_attributes( e.g. #[{ext}({n})]", ext = known_attributes::ExternalAttribute::EXTERNAL ); - context - .env() - .add_diag(diag!(Declarations::UnknownAttribute, (loc, msg))); + context.add_diag(diag!(Declarations::UnknownAttribute, (loc, msg))); None } sp!(loc, E::AttributeName_::Known(n)) => { @@ -1111,9 +1161,7 @@ fn unique_attributes( let msg = format!( "Known attribute '{known}' is not expected in a nested attribute position" ); - context - .env() - .add_diag(diag!(Declarations::InvalidAttribute, (nloc, msg))); + context.add_diag(diag!(Declarations::InvalidAttribute, (nloc, msg))); continue; } @@ -1133,7 +1181,7 @@ fn unique_attributes( "Expected to be used with one of the following: {}", all_expected ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidAttribute, (nloc, msg), (nloc, expected_msg) @@ -1151,7 +1199,7 @@ fn unique_attributes( } if let Err((_, old_loc)) = attr_map.add(sp(nloc, name_), sp(loc, attr_)) { let msg = format!("Duplicate attribute '{}' attached to the same item", name_); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (loc, msg), (old_loc, "Attribute previously given here"), @@ -1235,9 +1283,7 @@ fn warning_filter(context: &mut Context, attributes: &E::Attributes) -> WarningF DiagnosticAttribute::ALLOW, n ); - context - .env() - .add_diag(diag!(Declarations::InvalidAttribute, (inner_attr_loc, msg))); + context.add_diag(diag!(Declarations::InvalidAttribute, (inner_attr_loc, msg))); (None, vec![*n]) } }; @@ -1262,9 +1308,7 @@ fn warning_filter(context: &mut Context, attributes: &E::Attributes) -> WarningF ) } }; - context - .env() - .add_diag(diag!(Attributes::ValueWarning, (nloc, msg))); + context.add_diag(diag!(Attributes::ValueWarning, (nloc, msg))); continue; }; for f in filters { @@ -1295,9 +1339,7 @@ fn get_allow_attribute_inners<'a>( .to_str() .unwrap(), ); - context - .env() - .add_diag(diag!(Attributes::ValueWarning, (allow_attr.loc, msg))); + context.add_diag(diag!(Attributes::ValueWarning, (allow_attr.loc, msg))); None } } @@ -1322,9 +1364,7 @@ fn prefixed_warning_filters( prefix, n ); - context - .env() - .add_diag(diag!(Attributes::ValueWarning, (*loc, msg))); + context.add_diag(diag!(Attributes::ValueWarning, (*loc, msg))); *n } }) @@ -1534,7 +1574,7 @@ fn use_( otherwise they must internal to declared scope.", P::Visibility::PUBLIC ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidUseFun, (loc, msg), (vis_loc, vis_msg) @@ -1592,7 +1632,7 @@ fn module_use( P::ModuleUse::Module(alias_opt) => { let mident = module_ident(&mut context.defn_context, in_mident); if !context.defn_context.module_members.contains_key(&mident) { - context.env().add_diag(unbound_module(&mident)); + context.add_diag(unbound_module(&mident)); return; }; let alias = alias_opt @@ -1605,7 +1645,7 @@ fn module_use( let members = match context.defn_context.module_members.get(&mident) { Some(members) => members, None => { - context.env().add_diag(unbound_module(&mident)); + context.add_diag(unbound_module(&mident)); return; } }; @@ -1644,7 +1684,7 @@ fn module_use( "Invalid 'use'. Unbound member '{}' in module '{}'", member, mident ); - context.env().add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundModuleMember, (member.loc, msg), (mloc, format!("Module '{}' declared here", mident)), @@ -1686,7 +1726,7 @@ fn module_use( P::ModuleUse::Partial { .. } => { let mident = module_ident(&mut context.defn_context, in_mident); if !context.defn_context.module_members.contains_key(&mident) { - context.env().add_diag(unbound_module(&mident)); + context.add_diag(unbound_module(&mident)); return; }; add_module_alias!(mident, mident.value.module.0) @@ -1762,7 +1802,7 @@ fn duplicate_module_alias(context: &mut Context, old_loc: Loc, alias: Name) { "Duplicate module alias '{}'. Module aliases must be unique within a given namespace", alias ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (alias.loc, msg), (old_loc, "Alias previously defined here"), @@ -1774,7 +1814,7 @@ fn duplicate_module_member(context: &mut Context, old_loc: Loc, alias: Name) { "Duplicate module member or alias '{}'. Top level names in a namespace must be unique", alias ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (alias.loc, msg), (old_loc, "Alias previously defined here"), @@ -1803,7 +1843,7 @@ fn unused_alias(context: &mut Context, _kind: &str, alias: Name) { alias )); } - context.env().add_diag(diag); + context.add_diag(diag); } //************************************************************************************************** @@ -1836,9 +1876,7 @@ fn struct_def_( } = pstruct; let attributes = flatten_attributes(context, AttributePosition::Struct, attributes); let warning_filter = warning_filter(context, &attributes); - context - .env() - .add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let type_parameters = datatype_type_parameters(context, pty_params); context.push_type_parameters(type_parameters.iter().map(|tp| &tp.name)); let abilities = ability_set(context, "modifier", abilities_vec); @@ -1853,7 +1891,7 @@ fn struct_def_( fields, }; context.pop_alias_scope(None); - context.env().pop_warning_filter_scope(); + context.pop_warning_filter_scope(); (name, sdef) } @@ -1874,7 +1912,7 @@ fn struct_fields( for (idx, (field, pt)) in pfields_vec.into_iter().enumerate() { let t = type_(context, pt); if let Err((field, old_loc)) = field_map.add(field, (idx, t)) { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, ( field.loc(), @@ -1920,9 +1958,7 @@ fn enum_def_( } = penum; let attributes = flatten_attributes(context, AttributePosition::Enum, attributes); let warning_filter = warning_filter(context, &attributes); - context - .env() - .add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let type_parameters = datatype_type_parameters(context, pty_params); context.push_type_parameters(type_parameters.iter().map(|tp| &tp.name)); let abilities = ability_set(context, "modifier", abilities_vec); @@ -1937,7 +1973,7 @@ fn enum_def_( variants, }; context.pop_alias_scope(None); - context.env().pop_warning_filter_scope(); + context.pop_warning_filter_scope(); (name, edef) } @@ -1949,7 +1985,7 @@ fn enum_variants( ) -> UniqueMap { let mut variants = UniqueMap::new(); if pvariants.is_empty() { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidEnum, (eloc, "An 'enum' must define at least one variant") )) @@ -1962,7 +1998,7 @@ fn enum_variants( "Duplicate definition for variant '{}' in enum '{}'", vname, ename ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (loc, msg), (old_loc.1, "Variant previously defined here") @@ -2000,7 +2036,7 @@ fn variant_fields( for (idx, (field, pt)) in pfields_vec.into_iter().enumerate() { let t = type_(context, pt); if let Err((field, old_loc)) = field_map.add(field, (idx, t)) { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, ( field.loc(), @@ -2034,7 +2070,7 @@ fn friend( unique", mident ); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (friend.loc, msg), (old_friend.loc, "Friend previously declared here"), @@ -2096,9 +2132,7 @@ fn constant_( } = pconstant; let attributes = flatten_attributes(context, AttributePosition::Constant, pattributes); let warning_filter = warning_filter(context, &attributes); - context - .env() - .add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let signature = type_(context, psignature); let value = *exp(context, Box::new(pvalue)); let constant = E::Constant { @@ -2109,7 +2143,7 @@ fn constant_( signature, value, }; - context.env().pop_warning_filter_scope(); + context.pop_warning_filter_scope(); (name, constant) } @@ -2147,9 +2181,7 @@ fn function_( } = pfunction; let attributes = flatten_attributes(context, AttributePosition::Function, pattributes); let warning_filter = warning_filter(context, &attributes); - context - .env() - .add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); if let (Some(entry_loc), Some(macro_loc)) = (entry, macro_) { let e_msg = format!( "Invalid function declaration. \ @@ -2157,7 +2189,7 @@ fn function_( are fully-expanded inline during compilation" ); let m_msg = format!("Function declared as '{MACRO_MODIFIER}' here"); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidFunction, (entry_loc, e_msg), (macro_loc, m_msg), @@ -2169,7 +2201,7 @@ fn function_( '{NATIVE_MODIFIER}' functions cannot be '{MACRO_MODIFIER}'", ); let m_msg = format!("Function declared as '{MACRO_MODIFIER}' here"); - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidFunction, (*native_loc, n_msg), (macro_loc, m_msg), @@ -2208,7 +2240,7 @@ fn function_( body, }; context.pop_alias_scope(None); - context.env().pop_warning_filter_scope(); + context.pop_warning_filter_scope(); (name, fdef) } @@ -2267,7 +2299,7 @@ fn ability_set(context: &mut Context, case: &str, abilities_vec: Vec) - for ability in abilities_vec { let loc = ability.loc; if let Err(prev_loc) = set.add(ability) { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (loc, format!("Duplicate '{}' ability {}", ability, case)), (prev_loc, "Ability previously given here") @@ -2501,9 +2533,7 @@ fn exp(context: &mut Context, pe: Box) -> Box { PE::Name(pn) if pn.value.has_tyargs() => { let msg = "Expected name to be followed by a brace-enclosed list of field expressions \ or a parenthesized list of arguments for a function call"; - context - .env() - .add_diag(diag!(NameResolution::NamePositionMismatch, (loc, msg))); + context.add_diag(diag!(NameResolution::NamePositionMismatch, (loc, msg))); EE::UnresolvedError } PE::Name(pn) => { @@ -2680,7 +2710,7 @@ fn exp(context: &mut Context, pe: Box) -> Box { consider updating your Move edition to '{valid_editions}'" )); diag.add_note(editions::UPGRADE_NOTE); - context.env().add_diag(diag); + context.add_diag(diag); EE::UnresolvedError } else { match exp_dotted(context, Box::new(sp(loc, pdotted_))) { @@ -2772,9 +2802,7 @@ fn exp_cast(context: &mut Context, in_parens: bool, plhs: Box, pty: P::T .check_feature(current_package, FeatureGate::NoParensCast, loc); if supports_feature && ambiguous_cast(&plhs) { let msg = "Potentially ambiguous 'as'. Add parentheses to disambiguate"; - context - .env() - .add_diag(diag!(Syntax::AmbiguousCast, (loc, msg))); + context.add_diag(diag!(Syntax::AmbiguousCast, (loc, msg))); } } EE::Cast(exp(context, plhs), type_(context, pty)) @@ -2804,9 +2832,7 @@ fn maybe_labeled_exp( _ => { let msg = "Invalid label. Labels can only be used on 'while', 'loop', or block '{{}}' \ expressions"; - context - .env() - .add_diag(diag!(Syntax::InvalidLabel, (loc, msg))); + context.add_diag(diag!(Syntax::InvalidLabel, (loc, msg))); E::Exp_::UnresolvedError } }; @@ -2820,7 +2846,7 @@ fn ensure_unique_label( label_opt: Option, ) { if let Some(old_label) = label_opt { - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidLabel, (loc, "Multiple labels for a single expression"), (old_label.0.loc, "Label previously given here"), @@ -2866,7 +2892,7 @@ fn move_or_copy_path_(context: &mut Context, case: PathCase, pe: Box) -> if !matches!(&inner.value, E::Exp_::Name(_, _)) { let cmsg = format!("Invalid '{}' of expression", case.case()); let emsg = "Expected a name or path access, e.g. 'x' or 'e.f'"; - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidMoveOrCopy, (cloc, cmsg), (inner.loc, emsg) @@ -2937,7 +2963,7 @@ fn check_ellipsis_usage(context: &mut Context, ellipsis_locs: &[Loc]) { diag.add_secondary_label((*loc, "Ellipsis pattern used again here")); } diag.add_note("An ellipsis pattern can only appear once in a constructor's pattern."); - context.env().add_diag(diag); + context.add_diag(diag); } } @@ -2971,7 +2997,7 @@ fn match_pattern(context: &mut Context, sp!(loc, pat_): P::MatchPattern) -> E::M EM::Variant(_, _) | EM::ModuleAccess(_, _) => Some(name), EM::Name(_) if identifier_okay => Some(name), EM::Name(_) => { - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::UnexpectedToken, ( name.loc, @@ -2996,7 +3022,7 @@ fn match_pattern(context: &mut Context, sp!(loc, pat_): P::MatchPattern) -> E::M } = context.name_access_chain_to_module_access(Access::Pattern, name_chain)?; let name = head_ctor_okay(context, access, identifier_okay)?; if let Some(loc) = is_macro { - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidMacro, (loc, "Macros are not allowed in patterns.") )); @@ -3102,14 +3128,14 @@ fn match_pattern(context: &mut Context, sp!(loc, pat_): P::MatchPattern) -> E::M resolve this constant's name", ); } - context.env().add_diag(diag); + context.add_diag(diag); error_pattern!() } else { if let Some(_tys) = pts_opt { let msg = "Invalid type arguments on a pattern variable"; let mut diag = diag!(Declarations::InvalidName, (name.loc, msg)); diag.add_note("Type arguments cannot appear on pattern variables"); - context.env().add_diag(diag); + context.add_diag(diag); } sp(loc, EP::Binder(mutability(context, loc, mut_), Var(name))) } @@ -3119,7 +3145,7 @@ fn match_pattern(context: &mut Context, sp!(loc, pat_): P::MatchPattern) -> E::M let msg = "'mut' can only be used with variable bindings in patterns"; let nmsg = "Expected a valid 'enum' variant, 'struct', or 'const', not a variable"; - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidName, (mloc, msg), (head_ctor_name.loc, nmsg) @@ -3153,7 +3179,7 @@ fn match_pattern(context: &mut Context, sp!(loc, pat_): P::MatchPattern) -> E::M ), PP::At(x, inner) => { if x.is_underscore() { - context.env().add_diag(diag!( + context.add_diag(diag!( NameResolution::InvalidPattern, (x.loc(), "Can't use '_' as a binder in an '@' pattern") )); @@ -3180,42 +3206,42 @@ pub(super) fn value(context: &mut DefnContext, sp!(loc, pvalue_): P::Value) -> O PV::Num(s) if s.ends_with("u8") => match parse_u8(&s[..s.len() - 2]) { Ok((u, _format)) => EV::U8(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u8'")); + context.add_diag(num_too_big_error(loc, "'u8'")); return None; } }, PV::Num(s) if s.ends_with("u16") => match parse_u16(&s[..s.len() - 3]) { Ok((u, _format)) => EV::U16(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u16'")); + context.add_diag(num_too_big_error(loc, "'u16'")); return None; } }, PV::Num(s) if s.ends_with("u32") => match parse_u32(&s[..s.len() - 3]) { Ok((u, _format)) => EV::U32(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u32'")); + context.add_diag(num_too_big_error(loc, "'u32'")); return None; } }, PV::Num(s) if s.ends_with("u64") => match parse_u64(&s[..s.len() - 3]) { Ok((u, _format)) => EV::U64(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u64'")); + context.add_diag(num_too_big_error(loc, "'u64'")); return None; } }, PV::Num(s) if s.ends_with("u128") => match parse_u128(&s[..s.len() - 4]) { Ok((u, _format)) => EV::U128(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u128'")); + context.add_diag(num_too_big_error(loc, "'u128'")); return None; } }, PV::Num(s) if s.ends_with("u256") => match parse_u256(&s[..s.len() - 4]) { Ok((u, _format)) => EV::U256(u), Err(_) => { - context.env.add_diag(num_too_big_error(loc, "'u256'")); + context.add_diag(num_too_big_error(loc, "'u256'")); return None; } }, @@ -3223,7 +3249,7 @@ pub(super) fn value(context: &mut DefnContext, sp!(loc, pvalue_): P::Value) -> O PV::Num(s) => match parse_u256(&s) { Ok((u, _format)) => EV::InferredNum(u), Err(_) => { - context.env.add_diag(num_too_big_error( + context.add_diag(num_too_big_error( loc, "the largest possible integer type, 'u256'", )); @@ -3234,14 +3260,14 @@ pub(super) fn value(context: &mut DefnContext, sp!(loc, pvalue_): P::Value) -> O PV::HexString(s) => match hex_string::decode(loc, &s) { Ok(v) => EV::Bytearray(v), Err(e) => { - context.env.add_diag(*e); + context.add_diag(*e); return None; } }, PV::ByteString(s) => match byte_string::decode(loc, &s) { Ok(v) => EV::Bytearray(v), Err(e) => { - context.env.add_diags(e); + context.add_diags(e); return None; } }, @@ -3278,7 +3304,7 @@ fn named_fields( let mut fmap = UniqueMap::new(); for (idx, (field, x)) in xs.into_iter().enumerate() { if let Err((field, old_loc)) = fmap.add(field, (idx, x)) { - context.env().add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (loc, format!("Invalid {}", case)), ( @@ -3395,7 +3421,7 @@ fn lvalues(context: &mut Context, e: Box) -> Option { L::FieldMutate(dotted) } PE::Index(_, _) => { - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidLValue, ( loc, @@ -3422,14 +3448,14 @@ fn assign(context: &mut Context, sp!(loc, e_): P::Exp) -> Option { "If you are trying to unpack a struct, try adding fields, e.g.'{} {{}}'", name )); - context.env().add_diag(diag); + context.add_diag(diag); None } Some(access_result!(_, _ptys_opt, Some(_))) => { let msg = "Unexpected assignment of name with macro invocation"; let mut diag = diag!(Syntax::InvalidLValue, (loc, msg)); diag.add_note("Macro invocation '!' must appear on an invocation"); - context.env().add_diag(diag); + context.add_diag(diag); None } Some(access_result!(sp!(_, name @ M::Name(_)), None, None)) => { @@ -3442,7 +3468,7 @@ fn assign(context: &mut Context, sp!(loc, e_): P::Exp) -> Option { "If you are trying to unpack a struct, try adding fields, e.g.'{} {{}}'", name )); - context.env().add_diag(diag); + context.add_diag(diag); None } Some(access_result!(sp!(loc, M::Variant(_, _)), _tys_opt, _is_macro)) => { @@ -3454,7 +3480,7 @@ fn assign(context: &mut Context, sp!(loc, e_): P::Exp) -> Option { let msg = "Unexpected assignment of variant"; let mut diag = diag!(Syntax::InvalidLValue, (loc, msg)); diag.add_note("If you are trying to unpack an enum variant, use 'match'"); - context.env().add_diag(diag); + context.add_diag(diag); None } else { assert!(context.env().has_errors()); @@ -3504,7 +3530,7 @@ fn assign(context: &mut Context, sp!(loc, e_): P::Exp) -> Option { )) } _ => { - context.env().add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidLValue, ( loc, diff --git a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs index 3b9c16cfd77b8..bb0a6037d42c1 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/detect_dead_code.rs @@ -3,6 +3,7 @@ use crate::{ diag, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, expansion::ast::ModuleIdent, ice, naming::ast::{self as N, BlockLabel}, @@ -188,15 +189,37 @@ impl ControlFlow { } struct Context<'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, + warning_filters_scope: WarningFiltersScope, // loops: Vec, } impl<'env> Context<'env> { - pub fn new(env: &'env mut CompilationEnv) -> Self { + pub fn new(env: &'env CompilationEnv) -> Self { // let loops = vec![]; // Context { env , loops } - Context { env } + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); + Context { + env, + warning_filters_scope, + } + } + + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() } fn maybe_report_value_error(&mut self, error: &mut ControlFlow) -> bool { @@ -208,8 +231,7 @@ impl<'env> Context<'env> { reported, } if !*reported => { *reported = true; - self.env - .add_diag(diag!(UnusedItem::DeadCode, (*loc, VALUE_UNREACHABLE_MSG))); + self.add_diag(diag!(UnusedItem::DeadCode, (*loc, VALUE_UNREACHABLE_MSG))); true } CF::Divergent { .. } | CF::None | CF::Possible => false, @@ -225,8 +247,7 @@ impl<'env> Context<'env> { reported, } if !*reported => { *reported = true; - self.env - .add_diag(diag!(UnusedItem::DeadCode, (*loc, DIVERGENT_MSG))); + self.add_diag(diag!(UnusedItem::DeadCode, (*loc, DIVERGENT_MSG))); true } CF::Divergent { .. } | CF::None | CF::Possible => false, @@ -250,7 +271,7 @@ impl<'env> Context<'env> { if let Some(next_loc) = next_stmt { diag.add_secondary_label((*next_loc, UNREACHABLE_MSG)); } - self.env.add_diag(diag); + self.add_diag(diag); true } CF::Divergent { .. } | CF::None | CF::Possible => false, @@ -271,7 +292,7 @@ impl<'env> Context<'env> { reported, } if !*reported => { *reported = true; - self.env.add_diag(diag!( + self.add_diag(diag!( UnusedItem::TrailingSemi, (tail_exp.exp.loc, SEMI_MSG), (*loc, DIVERGENT_MSG), @@ -344,7 +365,7 @@ fn infinite_loop(loc: Loc) -> ControlFlow { // Entry //************************************************************************************************** -pub fn program(compilation_env: &mut CompilationEnv, prog: &T::Program) { +pub fn program(compilation_env: &CompilationEnv, prog: &T::Program) { let mut context = Context::new(compilation_env); modules(&mut context, &prog.modules); } @@ -356,16 +377,14 @@ fn modules(context: &mut Context, modules: &UniqueMap ControlFlow { |context, flow| context.maybe_report_tail_error(flow), ), E::VariantMatch(..) => { - context - .env - .add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); + context.add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); CF::None } @@ -508,7 +523,7 @@ fn tail_block(context: &mut Context, seq: &VecDeque) -> Control None => ControlFlow::None, Some(sp!(_, S::Seq(last))) => tail(context, last), Some(sp!(loc, _)) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *loc, "ICE last sequence item should have been an exp in dead code analysis" ))); @@ -560,9 +575,7 @@ fn value(context: &mut Context, e: &T::Exp) -> ControlFlow { |context, flow| context.maybe_report_value_error(flow), ), E::VariantMatch(_subject, _, _arms) => { - context - .env - .add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); + context.add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); CF::None } E::While(..) => statement(context, e), @@ -618,7 +631,7 @@ fn value(context: &mut Context, e: &T::Exp) -> ControlFlow { context.maybe_report_value_error(&mut flow); } T::ExpListItem::Splat(_, _, _) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *eloc, "ICE splat exp unsupported by dead code analysis" ))); @@ -686,7 +699,7 @@ fn value_block(context: &mut Context, seq: &VecDeque) -> Contro None => ControlFlow::None, Some(sp!(_, S::Seq(last))) => value(context, last), Some(sp!(loc, _)) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *loc, "ICE last sequence item should have been an exp in dead code analysis" ))); @@ -739,9 +752,7 @@ fn statement(context: &mut Context, e: &T::Exp) -> ControlFlow { |_, _| false, ), E::VariantMatch(_subject, _, _arms) => { - context - .env - .add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); + context.add_diag(ice!((*eloc, "Found variant match in detect_dead_code"))); CF::None } E::While(name, test, body) => { @@ -826,9 +837,7 @@ fn statement(context: &mut Context, e: &T::Exp) -> ControlFlow { // odds and ends -- things we need to deal with but that don't do much // ----------------------------------------------------------------------------------------- E::Use(_) => { - context - .env - .add_diag(ice!((*eloc, "ICE found unexpanded use"))); + context.add_diag(ice!((*eloc, "ICE found unexpanded use"))); CF::None } } diff --git a/external-crates/move/crates/move-compiler/src/hlir/match_compilation.rs b/external-crates/move/crates/move-compiler/src/hlir/match_compilation.rs index aa29efa59883a..2783fce778fd9 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/match_compilation.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/match_compilation.rs @@ -724,7 +724,7 @@ fn make_arm_unpack( let Some((queue_entries, unpack)) = arm_variant_unpack(context, None, ploc, m, e, tys, v, fs, entry) else { - context.hlir_context.env.add_diag(ice!(( + context.hlir_context.add_diag(ice!(( ploc, "Did not build an arm unpack for a value variant" ))); @@ -750,7 +750,7 @@ fn make_arm_unpack( let Some((queue_entries, unpack)) = arm_struct_unpack(context, None, ploc, m, s, tys, fs, entry) else { - context.hlir_context.env.add_diag(ice!(( + context.hlir_context.add_diag(ice!(( ploc, "Did not build an arm unpack for a value struct" ))); diff --git a/external-crates/move/crates/move-compiler/src/hlir/translate.rs b/external-crates/move/crates/move-compiler/src/hlir/translate.rs index 127ad7ec78b24..48f772ec5f418 100644 --- a/external-crates/move/crates/move-compiler/src/hlir/translate.rs +++ b/external-crates/move/crates/move-compiler/src/hlir/translate.rs @@ -4,6 +4,7 @@ use crate::{ debug_display, debug_display_verbose, diag, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, editions::{FeatureGate, Flavor}, expansion::ast::{self as E, Fields, ModuleIdent, Mutability, TargetKind}, hlir::{ @@ -127,9 +128,10 @@ pub(super) struct HLIRDebugFlags { } pub(super) struct Context<'env> { - pub env: &'env mut CompilationEnv, + pub env: &'env CompilationEnv, pub info: Arc, pub debug: HLIRDebugFlags, + warning_filters_scope: WarningFiltersScope, current_package: Option, function_locals: UniqueMap, signature: Option, @@ -142,7 +144,7 @@ pub(super) struct Context<'env> { impl<'env> Context<'env> { pub fn new( - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, _pre_compiled_lib_opt: Option>, prog: &T::Program, ) -> Self { @@ -154,8 +156,10 @@ impl<'env> Context<'env> { match_specialization: false, match_work_queue: false, }; + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, info: prog.info.clone(), debug, current_package: None, @@ -168,6 +172,23 @@ impl<'env> Context<'env> { } } + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } + pub fn has_empty_locals(&self) -> bool { self.function_locals.is_empty() } @@ -250,7 +271,7 @@ impl<'env> Context<'env> { } impl MatchContext for Context<'_> { - fn env(&mut self) -> &mut CompilationEnv { + fn env(&mut self) -> &CompilationEnv { self.env } @@ -288,7 +309,7 @@ impl MatchContext for Context<'_> { //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: T::Program, ) -> H::Program { @@ -337,7 +358,7 @@ fn module( constants: tconstants, } = mdef; context.current_package = package_name; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let structs = tstructs.map(|name, s| struct_def(context, name, s)); let enums = tenums.map(|name, s| enum_def(context, name, s)); @@ -353,7 +374,7 @@ fn module( gen_unused_warnings(context, target_kind, &structs); context.current_package = None; - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); ( module_ident, H::ModuleDefinition { @@ -391,10 +412,10 @@ fn function(context: &mut Context, _name: FunctionName, f: T::Function) -> H::Fu body, } = f; assert!(macro_.is_none(), "ICE macros filtered above"); - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let signature = function_signature(context, signature); let body = function_body(context, &signature, _name, body); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); H::Function { warning_filter, index, @@ -499,7 +520,7 @@ fn constant(context: &mut Context, _name: ConstantName, cdef: T::Constant) -> H: signature: tsignature, value: tvalue, } = cdef; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let signature = base_type(context, tsignature); let eloc = tvalue.exp.loc; let tseq = { @@ -513,7 +534,7 @@ fn constant(context: &mut Context, _name: ConstantName, cdef: T::Constant) -> H: return_type: H::Type_::base(signature.clone()), }; let (locals, body) = function_body_defined(context, &function_signature, loc, tseq); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); H::Constant { warning_filter, index, @@ -542,9 +563,9 @@ fn struct_def( type_parameters, fields, } = sdef; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let fields = struct_fields(context, fields); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); H::StructDefinition { warning_filter, index, @@ -586,13 +607,13 @@ fn enum_def( type_parameters, variants, } = edef; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let variants = variants.map(|_, defn| H::VariantDefinition { index: defn.index, loc: defn.loc, fields: variant_fields(context, defn.fields), }); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); H::EnumDefinition { warning_filter, index, @@ -648,7 +669,7 @@ fn base_type(context: &mut Context, sp!(loc, nb_): N::Type) -> H::BaseType { use N::Type_ as NT; let b_ = match nb_ { NT::Var(_) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, format!( "ICE type inf. var not expanded: {}", @@ -658,7 +679,7 @@ fn base_type(context: &mut Context, sp!(loc, nb_): N::Type) -> H::BaseType { return error_base_type(loc); } NT::Apply(None, _, _) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, format!("ICE kind not expanded: {}", debug_display_verbose!(nb_)) ))); @@ -669,7 +690,7 @@ fn base_type(context: &mut Context, sp!(loc, nb_): N::Type) -> H::BaseType { NT::UnresolvedError => HB::UnresolvedError, NT::Anything => HB::Unreachable, NT::Ref(_, _) | NT::Unit | NT::Fun(_, _) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, format!( "ICE base type constraint failed: {}", @@ -716,7 +737,7 @@ fn type_(context: &mut Context, sp!(loc, ty_): N::Type) -> H::Type { let t_ = match ty_ { NT::Unit => HT::Unit, NT::Apply(None, _, _) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, format!("ICE kind not expanded: {}", debug_display_verbose!(ty_)) ))); @@ -972,9 +993,7 @@ fn tail( | E::Continue(_) | E::Assign(_, _, _) | E::Mutate(_, _) => { - context - .env - .add_diag(ice!((eloc, "ICE statement mishandled in HLIR lowering"))); + context.add_diag(ice!((eloc, "ICE statement mishandled in HLIR lowering"))); None } @@ -1004,9 +1023,7 @@ fn tail_block( None => None, Some(sp!(_, S::Seq(last))) => tail(context, block, expected_type, *last), Some(sp!(loc, _)) => { - context - .env - .add_diag(ice!((loc, "ICE statement mishandled in HLIR lowering"))); + context.add_diag(ice!((loc, "ICE statement mishandled in HLIR lowering"))); None } } @@ -1068,18 +1085,14 @@ fn value( let [cond_item, code_item]: [TI; 2] = match arguments.exp.value { E::ExpList(arg_list) => arg_list.try_into().unwrap(), _ => { - context - .env - .add_diag(ice!((eloc, "ICE type checking assert failed"))); + context.add_diag(ice!((eloc, "ICE type checking assert failed"))); return error_exp(eloc); } }; let (econd, ecode) = match (cond_item, code_item) { (TI::Single(econd, _), TI::Single(ecode, _)) => (econd, ecode), _ => { - context - .env - .add_diag(ice!((eloc, "ICE type checking assert failed"))); + context.add_diag(ice!((eloc, "ICE type checking assert failed"))); return error_exp(eloc); } }; @@ -1106,18 +1119,14 @@ fn value( let [cond_item, code_item]: [TI; 2] = match arguments.exp.value { E::ExpList(arg_list) => arg_list.try_into().unwrap(), _ => { - context - .env - .add_diag(ice!((eloc, "ICE type checking assert failed"))); + context.add_diag(ice!((eloc, "ICE type checking assert failed"))); return error_exp(eloc); } }; let (econd, ecode) = match (cond_item, code_item) { (TI::Single(econd, _), TI::Single(ecode, _)) => (econd, ecode), _ => { - context - .env - .add_diag(ice!((eloc, "ICE type checking assert failed"))); + context.add_diag(ice!((eloc, "ICE type checking assert failed"))); return error_exp(eloc); } }; @@ -1514,7 +1523,7 @@ fn value( var, } => var, _ => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( eloc, format!( "ICE invalid bind_exp for single value: {}", @@ -1538,7 +1547,7 @@ fn value( | Some(bt @ sp!(_, BT::U128)) | Some(bt @ sp!(_, BT::U256)) => *bt, _ => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( eloc, format!( "ICE typing failed for cast: {} : {}", @@ -1603,9 +1612,7 @@ fn value( | E::Continue(_) | E::Assign(_, _, _) | E::Mutate(_, _) => { - context - .env - .add_diag(ice!((eloc, "ICE statement mishandled in HLIR lowering"))); + context.add_diag(ice!((eloc, "ICE statement mishandled in HLIR lowering"))); error_exp(eloc) } @@ -1613,7 +1620,7 @@ fn value( // odds and ends -- things we need to deal with but that don't do much // ----------------------------------------------------------------------------------------- E::Use(_) => { - context.env.add_diag(ice!((eloc, "ICE unexpanded use"))); + context.add_diag(ice!((eloc, "ICE unexpanded use"))); error_exp(eloc) } E::UnresolvedError => { @@ -1637,15 +1644,11 @@ fn value_block( match last_exp { Some(sp!(_, S::Seq(last))) => value(context, block, expected_type, *last), Some(sp!(loc, _)) => { - context - .env - .add_diag(ice!((loc, "ICE last sequence item should be an exp"))); + context.add_diag(ice!((loc, "ICE last sequence item should be an exp"))); error_exp(loc) } None => { - context - .env - .add_diag(ice!((seq_loc, "ICE empty sequence in value position"))); + context.add_diag(ice!((seq_loc, "ICE empty sequence in value position"))); error_exp(seq_loc) } } @@ -1980,7 +1983,7 @@ fn statement(context: &mut Context, block: &mut Block, e: T::Exp) { // odds and ends -- things we need to deal with but that don't do much // ----------------------------------------------------------------------------------------- E::Use(_) => { - context.env.add_diag(ice!((eloc, "ICE unexpanded use"))); + context.add_diag(ice!((eloc, "ICE unexpanded use"))); } } } @@ -2503,7 +2506,7 @@ fn bind_value_in_block( match lvalue { H::LValue_::Var { .. } => (), lv => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *loc, format!( "ICE tried bind_value for non-var lvalue {}", @@ -2603,9 +2606,7 @@ fn process_value(context: &mut Context, sp!(loc, ev_): E::Value) -> H::Value { use H::Value_ as HV; let v_ = match ev_ { EV::InferredNum(_) => { - context - .env - .add_diag(ice!((loc, "ICE not expanded to value"))); + context.add_diag(ice!((loc, "ICE not expanded to value"))); HV::U64(0) } EV::Address(a) => HV::Address(a.into_addr_bytes()), @@ -2941,7 +2942,7 @@ fn needs_freeze( format!("Expected type: {}", debug_display_verbose!(_expected)) ), ); - context.env.add_diag(diag); + context.add_diag(diag); } Freeze::NotNeeded } @@ -2982,7 +2983,7 @@ fn freeze(context: &mut Context, expected_type: &H::Type, e: H::Exp) -> (Block, "ICE list item has Multple type: {}", debug_display_verbose!(e.ty) ); - context.env.add_diag(ice!((e.ty.loc, msg))); + context.add_diag(ice!((e.ty.loc, msg))); H::SingleType_::base(error_base_type(e.ty.loc)) } }) @@ -3044,9 +3045,7 @@ fn gen_unused_warnings( let is_sui_mode = context.env.package_config(context.current_package).flavor == Flavor::Sui; for (_, sname, sdef) in structs { - context - .env - .add_warning_filter_scope(sdef.warning_filter.clone()); + context.push_warning_filter_scope(sdef.warning_filter.clone()); let has_key = sdef.abilities.has_ability_(Ability_::Key); @@ -3062,13 +3061,11 @@ fn gen_unused_warnings( .is_some_and(|names| names.contains(&f.value())) { let msg = format!("The '{}' field of the '{sname}' type is unused", f.value()); - context - .env - .add_diag(diag!(UnusedItem::StructField, (f.loc(), msg))); + context.add_diag(diag!(UnusedItem::StructField, (f.loc(), msg))); } } } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } } diff --git a/external-crates/move/crates/move-compiler/src/linters/abort_constant.rs b/external-crates/move/crates/move-compiler/src/linters/abort_constant.rs index efa848336d976..6433ede72a976 100644 --- a/external-crates/move/crates/move-compiler/src/linters/abort_constant.rs +++ b/external-crates/move/crates/move-compiler/src/linters/abort_constant.rs @@ -13,50 +13,56 @@ use crate::{ visitor::{CFGIRVisitorConstructor, CFGIRVisitorContext}, }, diag, - diagnostics::WarningFilters, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, editions::FeatureGate, hlir::ast as H, - shared::CompilationEnv, + shared::{CompilationEnv, WarningFiltersScope}, }; pub struct AssertAbortNamedConstants; pub struct Context<'a> { package_name: Option, - env: &'a mut CompilationEnv, + env: &'a CompilationEnv, + warning_filters_scope: WarningFiltersScope, } impl CFGIRVisitorConstructor for AssertAbortNamedConstants { type Context<'a> = Context<'a>; - fn context<'a>(env: &'a mut CompilationEnv, program: &G::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a CompilationEnv, program: &G::Program) -> Self::Context<'a> { let package_name = program .modules .iter() .next() .and_then(|(_, _, mdef)| mdef.package_name); - Context { env, package_name } + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); + Context { + env, + warning_filters_scope, + package_name, + } } } impl Context<'_> { - fn add_diag(&mut self, diag: crate::diagnostics::Diagnostic) { - self.env.add_diag(diag); + fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); } #[allow(unused)] - fn add_diags(&mut self, diags: crate::diagnostics::Diagnostics) { - self.env.add_diags(diags); + fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); } } impl CFGIRVisitorContext for Context<'_> { - fn add_warning_filter_scope(&mut self, filters: WarningFilters) { - self.env.add_warning_filter_scope(filters) + fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } fn visit_command_custom(&mut self, cmd: &H::Command) -> bool { diff --git a/external-crates/move/crates/move-compiler/src/naming/fake_natives.rs b/external-crates/move/crates/move-compiler/src/naming/fake_natives.rs index 814174cb72e6b..56574e6e7408b 100644 --- a/external-crates/move/crates/move-compiler/src/naming/fake_natives.rs +++ b/external-crates/move/crates/move-compiler/src/naming/fake_natives.rs @@ -19,7 +19,7 @@ use move_symbol_pool::symbol; /// verify fake native attribute usage usage pub fn function( - env: &mut CompilationEnv, + env: &CompilationEnv, module: ModuleIdent, function_name: FunctionName, function: &N::Function, @@ -45,7 +45,7 @@ pub fn function( (loc, attr_msg), (function_name.loc(), name_msg), ); - env.add_diag(diag); + env.add_error_diag(diag); } match &function.body.value { N::FunctionBody_::Native => (), @@ -55,7 +55,7 @@ pub fn function( NativeAttribute::BYTECODE_INSTRUCTION ); let diag = diag!(Attributes::InvalidBytecodeInst, (loc, attr_msg)); - env.add_diag(diag); + env.add_error_diag(diag); } } } diff --git a/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs b/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs index 36d627d124978..b66c4c5d98d87 100644 --- a/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs +++ b/external-crates/move/crates/move-compiler/src/naming/resolve_use_funs.rs @@ -1,6 +1,7 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use crate::diagnostics::{Diagnostic, Diagnostics, WarningFilters}; use crate::expansion::ast::{self as E, ModuleIdent}; use crate::naming::ast as N; use crate::parser::ast::{FunctionName, Visibility}; @@ -15,30 +16,50 @@ use move_proc_macros::growing_stack; //************************************************************************************************** struct Context<'env, 'info> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, info: &'info NamingProgramInfo, + warning_filters_scope: WarningFiltersScope, current_module: ModuleIdent, } impl<'env, 'info> Context<'env, 'info> { fn new( - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, info: &'info NamingProgramInfo, current_module: ModuleIdent, ) -> Self { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Self { env, info, + warning_filters_scope, current_module, } } + + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } } //************************************************************************************************** // Entry //************************************************************************************************** -pub fn program(env: &mut CompilationEnv, info: &mut NamingProgramInfo, inner: &mut N::Program_) { +pub fn program(env: &CompilationEnv, info: &mut NamingProgramInfo, inner: &mut N::Program_) { let N::Program_ { modules } = inner; for (mident, mdef) in modules.key_cloned_iter_mut() { module(env, info, mident, mdef); @@ -59,15 +80,13 @@ pub fn program(env: &mut CompilationEnv, info: &mut NamingProgramInfo, inner: &m } fn module( - env: &mut CompilationEnv, + env: &CompilationEnv, info: &mut NamingProgramInfo, mident: ModuleIdent, mdef: &mut N::ModuleDefinition, ) { let context = &mut Context::new(env, info, mident); - context - .env - .add_warning_filter_scope(mdef.warning_filter.clone()); + context.push_warning_filter_scope(mdef.warning_filter.clone()); use_funs(context, &mut mdef.use_funs); for (_, _, c) in &mut mdef.constants { constant(context, c); @@ -75,25 +94,21 @@ fn module( for (_, _, f) in &mut mdef.functions { function(context, f); } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } fn constant(context: &mut Context, c: &mut N::Constant) { - context - .env - .add_warning_filter_scope(c.warning_filter.clone()); + context.push_warning_filter_scope(c.warning_filter.clone()); exp(context, &mut c.value); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } fn function(context: &mut Context, function: &mut N::Function) { - context - .env - .add_warning_filter_scope(function.warning_filter.clone()); + context.push_warning_filter_scope(function.warning_filter.clone()); if let N::FunctionBody_::Defined(seq) = &mut function.body.value { sequence(context, seq) } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } //************************************************************************************************** @@ -128,7 +143,7 @@ fn use_funs(context: &mut Context, uf: &mut N::UseFuns) { if let Some(public_loc) = nuf.is_public { let defining_module = match &tn.value { N::TypeName_::Multiple(_) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( tn.loc, "ICE tuple type should not be reachable from use fun" ))); @@ -155,7 +170,7 @@ fn use_funs(context: &mut Context, uf: &mut N::UseFuns) { format!("The type '{tn}' is defined here"), )) } - context.env.add_diag(diag); + context.add_diag(diag); nuf.is_public = None; } } @@ -173,7 +188,7 @@ fn use_funs(context: &mut Context, uf: &mut N::UseFuns) { } None => format!("But '{m}::{f}' takes no arguments"), }; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidUseFun, (loc, msg), (first_ty_loc, first_tn_msg), @@ -199,9 +214,7 @@ fn use_funs(context: &mut Context, uf: &mut N::UseFuns) { let Some((target_f, tn)) = is_valid_method(context, &target_m, target_f) else { if matches!(ekind, E::ImplicitUseFunKind::UseAlias { used: false }) { let msg = format!("Unused 'use' of alias '{}'. Consider removing it", method); - context - .env - .add_diag(diag!(UnusedItem::Alias, (method.loc, msg),)) + context.add_diag(diag!(UnusedItem::Alias, (method.loc, msg),)) } continue; }; @@ -238,7 +251,7 @@ fn use_funs(context: &mut Context, uf: &mut N::UseFuns) { argument is a type defined in the same module" } }; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (nuf_loc, msg), (prev, "Previously declared here"), diff --git a/external-crates/move/crates/move-compiler/src/naming/syntax_methods.rs b/external-crates/move/crates/move-compiler/src/naming/syntax_methods.rs index d5c19587d6af8..38a46961b5625 100644 --- a/external-crates/move/crates/move-compiler/src/naming/syntax_methods.rs +++ b/external-crates/move/crates/move-compiler/src/naming/syntax_methods.rs @@ -68,7 +68,7 @@ pub(super) fn resolve_syntax_attributes( if let Some(macro_loc) = function.macro_ { let msg = "Syntax attributes may not appear on macro definitions"; let fn_msg = "This function is a macro"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (attr_loc, msg), (macro_loc, fn_msg) @@ -125,7 +125,7 @@ fn prev_syntax_defn_error( kind_string, type_name ); let prev_msg = "This syntax method was previously defined here."; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidAttribute, (sloc, msg), (prev.loc, prev_msg) @@ -147,7 +147,7 @@ fn attr_param_from_str(loc: Loc, name_str: &str) -> Option /// Resolve the mapping for a function + syntax attribute into a SyntaxMethodKind. fn resolve_syntax_method_prekind( - env: &mut CompilationEnv, + env: &CompilationEnv, sp!(loc, attr_): &Attribute, ) -> Option> { match attr_ { @@ -157,7 +157,7 @@ fn resolve_syntax_method_prekind( SyntaxAttribute::SYNTAX, SyntaxAttribute::INDEX ); - env.add_diag(diag!(Declarations::InvalidAttribute, (*loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidAttribute, (*loc, msg))); None } Attribute_::Parameterized(_, inner) => { @@ -169,7 +169,7 @@ fn resolve_syntax_method_prekind( if let Some(prev_kind) = kinds.replace(kind) { let msg = "Repeated syntax method identifier".to_string(); let prev = "Initially defined here".to_string(); - env.add_diag(diag!( + env.add_error_diag(diag!( Declarations::InvalidAttribute, (loc, msg), (prev_kind.loc, prev) @@ -177,7 +177,7 @@ fn resolve_syntax_method_prekind( } } else { let msg = format!("Invalid syntax method identifier '{}'", name); - env.add_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); } } Attribute_::Assigned(n, _) => { @@ -186,7 +186,7 @@ fn resolve_syntax_method_prekind( SyntaxAttribute::SYNTAX, n ); - env.add_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); } Attribute_::Parameterized(n, _) => { let msg = format!( @@ -194,7 +194,7 @@ fn resolve_syntax_method_prekind( SyntaxAttribute::SYNTAX, n ); - env.add_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); + env.add_error_diag(diag!(Declarations::InvalidAttribute, (loc, msg))); } } } @@ -221,7 +221,7 @@ fn determine_valid_kind( SyntaxAttribute::INDEX, ); let ty_msg = "This type is not a reference"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidAttribute, (sloc, msg), (subject_type.loc, ty_msg) @@ -231,9 +231,7 @@ fn determine_valid_kind( } SyntaxMethodPrekind_::For => { let msg = "'for' syntax attributes are not currently supported"; - context - .env - .add_diag(diag!(Declarations::InvalidAttribute, (sloc, msg),)); + context.add_diag(diag!(Declarations::InvalidAttribute, (sloc, msg),)); return None; } // SyntaxMethodPrekind_::For => match mut_opt { @@ -243,9 +241,7 @@ fn determine_valid_kind( // }, SyntaxMethodPrekind_::Assign => { let msg = "'assign' syntax attributes are not currently supported"; - context - .env - .add_diag(diag!(Declarations::InvalidAttribute, (sloc, msg),)); + context.add_diag(diag!(Declarations::InvalidAttribute, (sloc, msg),)); return None; } // SyntaxMethodPrekind_::Assign => match mut_opt { // Some((loc, true)) => SK::Assign, @@ -255,7 +251,7 @@ fn determine_valid_kind( // SyntaxAttribute::INDEX, // ); // let ty_msg = "This type is not a reference"; - // context.env.add_diag(diag!( + // context.add_diag(diag!( // Declarations::InvalidAttribute, // (sloc, msg), // (*ty_loc, msg) @@ -287,7 +283,7 @@ fn determine_subject_type_name( let msg = "Invalid type for syntax method definition"; let mut diag = diag!(Declarations::InvalidSyntaxMethod, (*loc, msg)); diag.add_note("Syntax methods may only be defined for single base types"); - context.env.add_diag(diag); + context.add_diag(diag); return None; } N::TypeName_::Builtin(sp!(_, bt_)) => context.env.primitive_definer(*bt_), @@ -296,7 +292,7 @@ fn determine_subject_type_name( if Some(cur_module) == defining_module { Some(type_name.clone()) } else { - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*ann_loc, INVALID_MODULE_MSG), (*loc, INVALID_MODULE_TYPE_MSG) @@ -314,7 +310,7 @@ fn determine_subject_type_name( "But '{}' was declared as a type parameter here", param.user_specified_name ); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*ann_loc, msg), (*loc, tmsg) @@ -329,7 +325,7 @@ fn determine_subject_type_name( let msg = "Invalid type for syntax method definition"; let mut diag = diag!(Declarations::InvalidSyntaxMethod, (*loc, msg)); diag.add_note("Syntax methods may only be defined for single base types"); - context.env.add_diag(diag); + context.add_diag(diag); None } } @@ -349,7 +345,7 @@ fn valid_return_type( let msg = format!("Invalid {} annotation", SyntaxAttribute::SYNTAX); let tmsg = "This syntax method must return an immutable reference to match its subject type"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*loc, msg), (ty.loc, tmsg), @@ -362,7 +358,7 @@ fn valid_return_type( SyntaxAttribute::SYNTAX ); let tmsg = "This is not an immutable reference"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*loc, msg), (ty.loc, tmsg), @@ -379,7 +375,7 @@ fn valid_return_type( let msg = format!("Invalid {} annotation", SyntaxAttribute::SYNTAX); let tmsg = "This syntax method must return a mutable reference to match its subject type"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*loc, msg), (ty.loc, tmsg), @@ -392,7 +388,7 @@ fn valid_return_type( SyntaxAttribute::SYNTAX ); let tmsg = "This is not a mutable reference"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*loc, msg), (ty.loc, tmsg), @@ -426,7 +422,7 @@ fn valid_index_return_type( SyntaxAttribute::SYNTAX ); let tmsg = "Unit type occurs as the return type for this function"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*kind_loc, msg), (*tloc, tmsg) @@ -439,7 +435,7 @@ fn valid_index_return_type( SyntaxAttribute::SYNTAX ); let tmsg = "But a function type appears in this return type"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidSyntaxMethod, (*kind_loc, msg), (*tloc, tmsg) @@ -466,9 +462,7 @@ fn get_first_type( "Invalid attribute. {} is only valid if the function takes at least one parameter", SyntaxAttribute::SYNTAX ); - context - .env - .add_diag(diag!(Declarations::InvalidAttribute, (*attr_loc, msg))); + context.add_diag(diag!(Declarations::InvalidAttribute, (*attr_loc, msg))); None } } diff --git a/external-crates/move/crates/move-compiler/src/naming/translate.rs b/external-crates/move/crates/move-compiler/src/naming/translate.rs index 47aaf65713c66..6aeaf20fcb437 100644 --- a/external-crates/move/crates/move-compiler/src/naming/translate.rs +++ b/external-crates/move/crates/move-compiler/src/naming/translate.rs @@ -7,7 +7,7 @@ use crate::{ diagnostics::{ self, codes::{self, *}, - Diagnostic, + Diagnostic, Diagnostics, WarningFilters, }, editions::FeatureGate, expansion::{ @@ -24,7 +24,10 @@ use crate::{ self as P, ConstantName, DatatypeName, Field, FunctionName, VariantName, MACRO_MODIFIER, }, shared::{ - ide::EllipsisMatchEntries, program_info::NamingProgramInfo, unique_map::UniqueMap, *, + ide::{EllipsisMatchEntries, IDEAnnotation, IDEInfo}, + program_info::NamingProgramInfo, + unique_map::UniqueMap, + *, }, FullyCompiledProgram, }; @@ -519,13 +522,19 @@ pub fn build_member_map( // Context //************************************************************************************************** -pub(super) struct Context<'env> { - pub env: &'env mut CompilationEnv, - current_module: Option, +pub(super) struct OuterContext { /// Nothing should ever use this directly, and should instead go through /// `resolve_module_access` because it preserves source location information. module_members: ModuleMembers, + unscoped_types: BTreeMap, +} + +pub(super) struct Context<'outer, 'env> { + pub env: &'env CompilationEnv, + outer: &'outer OuterContext, unscoped_types: Vec>, + warning_filters_scope: WarningFiltersScope, + current_module: ModuleIdent, local_scopes: Vec>, local_count: BTreeMap, used_locals: BTreeSet, @@ -546,7 +555,7 @@ macro_rules! resolve_from_module_access { Some(other) => { let diag = make_invalid_module_member_kind_error($context, &$expected_kind, $loc, &other); - $context.env.add_diag(diag); + $context.add_diag(diag); None } None => { @@ -557,26 +566,43 @@ macro_rules! resolve_from_module_access { }}; } -impl<'env> Context<'env> { +impl OuterContext { fn new( - compilation_env: &'env mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: &E::Program, ) -> Self { use ResolvedType as RT; let module_members = build_member_map(compilation_env, pre_compiled_lib, prog); - let unscoped_types = vec![N::BuiltinTypeName_::all_names() + let unscoped_types = N::BuiltinTypeName_::all_names() .iter() .map(|s| { let b_ = RT::BuiltinType(N::BuiltinTypeName_::resolve(s.as_str()).unwrap()); (*s, b_) }) - .collect()]; + .collect(); Self { - env: compilation_env, - current_module: None, module_members, unscoped_types, + } + } +} + +impl<'outer, 'env> Context<'outer, 'env> { + fn new( + env: &'env CompilationEnv, + outer: &'outer OuterContext, + current_package: Option, + current_module: ModuleIdent, + ) -> Self { + let unscoped_types = vec![outer.unscoped_types.clone()]; + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); + Self { + env, + outer, + unscoped_types, + current_module, + warning_filters_scope, local_scopes: vec![], local_count: BTreeMap::new(), nominal_blocks: vec![], @@ -584,15 +610,42 @@ impl<'env> Context<'env> { used_locals: BTreeSet::new(), used_fun_tparams: BTreeSet::new(), translating_fun: false, - current_package: None, + current_package, } } + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + #[allow(unused)] + pub fn extend_ide_info(&self, info: IDEInfo) { + self.env.extend_ide_info(&self.warning_filters_scope, info); + } + + pub fn add_ide_annotation(&self, loc: Loc, info: IDEAnnotation) { + self.env + .add_ide_annotation(&self.warning_filters_scope, loc, info); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } + fn valid_module(&mut self, m: &ModuleIdent) -> bool { - let resolved = self.module_members.contains_key(m); + let resolved = self.outer.module_members.contains_key(m); if !resolved { let diag = make_unbound_module_error(self, m.loc, m); - self.env.add_diag(diag); + self.add_diag(diag); } resolved } @@ -606,14 +659,14 @@ impl<'env> Context<'env> { m: &ModuleIdent, n: &Name, ) -> Option { - let Some(members) = self.module_members.get(m) else { - self.env.add_diag(make_unbound_module_error(self, m.loc, m)); + let Some(members) = self.outer.module_members.get(m) else { + self.add_diag(make_unbound_module_error(self, m.loc, m)); return None; }; let result = members.get(&n.value); if result.is_none() { let diag = make_unbound_module_member_error(self, kind, loc, *m, n.value); - self.env.add_diag(diag); + self.env.add_diag(&self.warning_filters_scope, diag); } result.map(|inner| { let mut result = inner.clone(); @@ -690,7 +743,7 @@ impl<'env> Context<'env> { } EN::Name(n) => match self.resolve_unscoped_type(nloc, n) { ResolvedType::ModuleType(mut module_type) => { - module_type.set_name_info(self.current_module.unwrap(), nloc); + module_type.set_name_info(self.current_module, nloc); ResolvedType::ModuleType(module_type) } ty @ (ResolvedType::BuiltinType(_) @@ -725,7 +778,7 @@ impl<'env> Context<'env> { { None => { let diag = make_unbound_local_name_error(self, &ErrorKind::Type, loc, n); - self.env.add_diag(diag); + self.add_diag(diag); ResolvedType::Unbound } Some(rn) => rn.clone(), @@ -748,7 +801,7 @@ impl<'env> Context<'env> { Some(c @ ResolvedModuleMember::Constant(_)) => { let diag = make_invalid_module_member_kind_error(self, &EK::Function, mloc, &c); - self.env.add_diag(diag); + self.add_diag(diag); ResolvedCallSubject::Unbound } Some(e @ ResolvedModuleMember::Datatype(ResolvedDatatype::Enum(_))) => { @@ -758,7 +811,7 @@ impl<'env> Context<'env> { "Enums cannot be instantiated directly. \ Instead, you must instantiate a variant.", ); - self.env.add_diag(diag); + self.add_diag(diag); ResolvedCallSubject::Unbound } None => { @@ -776,7 +829,7 @@ impl<'env> Context<'env> { _ => { let diag = make_unbound_local_name_error(self, &EK::Function, n.loc, n.value); - self.env.add_diag(diag); + self.add_diag(diag); return ResolvedCallSubject::Unbound; } }; @@ -815,7 +868,7 @@ impl<'env> Context<'env> { ResolvedCallSubject::Constructor(Box::new(variant)) } Some(ResolvedConstructor::Struct(struct_)) => { - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::NamePositionMismatch, (sloc, "Invalid constructor. Expected an enum".to_string()), ( @@ -862,7 +915,7 @@ impl<'env> Context<'env> { _ => { let diag = make_unbound_local_name_error(self, &ErrorKind::Function, n.loc, n); - self.env.add_diag(diag); + self.add_diag(diag); return ResolvedUseFunFunction::Unbound; } }; @@ -872,11 +925,11 @@ impl<'env> Context<'env> { } EA::Name(n) => { let diag = make_unbound_local_name_error(self, &ErrorKind::Function, n.loc, n); - self.env.add_diag(diag); + self.add_diag(diag); ResolvedUseFunFunction::Unbound } EA::Variant(_, _) => { - self.env.add_diag(ice!(( + self.add_diag(ice!(( mloc, "Tried to resolve variant '{}' as a function in current scope" ),)); @@ -924,7 +977,7 @@ impl<'env> Context<'env> { } else { format!("Invalid {}. Expected a struct name", verb) }; - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::NamePositionMismatch, (ma.loc, msg), (rtloc, rtmsg) @@ -944,7 +997,7 @@ impl<'env> Context<'env> { "Invalid {verb}. Variant '{variant_name}' is not part of this enum", ); let decl_msg = format!("Enum '{}' is defined here", enum_type.name); - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::UnboundVariant, (ma.loc, primary_msg), (enum_type.decl_loc, decl_msg), @@ -960,7 +1013,7 @@ impl<'env> Context<'env> { Some(ResolvedConstructor::Variant(Box::new(variant_info))) } (EN::Name(_) | EN::ModuleAccess(_, _), D::Enum(enum_type)) => { - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::NamePositionMismatch, (ma.loc, format!("Invalid {verb}. Expected a struct")), ( @@ -971,7 +1024,7 @@ impl<'env> Context<'env> { None } (EN::Variant(sp!(sloc, _), _), D::Struct(stype)) => { - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::NamePositionMismatch, (*sloc, format!("Invalid {verb}. Expected an enum")), (stype.decl_loc, format!("But '{}' is an struct", stype.name)) @@ -1003,7 +1056,7 @@ impl<'env> Context<'env> { } } E::ModuleAccess_::Name(name) => { - self.env.add_diag(diag!( + self.add_diag(diag!( NameResolution::UnboundUnscopedName, (mloc, format!("Unbound constant '{}'", name)), )); @@ -1065,7 +1118,7 @@ impl<'env> Context<'env> { } ResolvedModuleMember::Constant(_) => (), }; - self.env.add_diag(diag); + self.add_diag(diag); ResolvedTerm::Unbound } }, @@ -1098,13 +1151,12 @@ impl<'env> Context<'env> { fn resolve_pattern_term(&mut self, sp!(mloc, ma_): E::ModuleAccess) -> ResolvedPatternTerm { match ma_ { E::ModuleAccess_::Name(name) if !is_constant_name(&name.value) => { - self.env - .add_diag(ice!((mloc, "This should have become a binder"))); + self.add_diag(ice!((mloc, "This should have become a binder"))); ResolvedPatternTerm::Unbound } // If we have a name, try to resolve it in our module. E::ModuleAccess_::Name(name) => { - let mut mident = self.current_module.unwrap(); + let mut mident = self.current_module; mident.loc = mloc; let maccess = sp(mloc, E::ModuleAccess_::ModuleAccess(mident, name)); self.resolve_pattern_term(maccess) @@ -1181,7 +1233,7 @@ impl<'env> Context<'env> { match id_opt { None => { let msg = variable_msg(name); - self.env.add_diag(diag!(code, (loc, msg))); + self.add_diag(diag!(code, (loc, msg))); None } Some(id) => { @@ -1202,7 +1254,7 @@ impl<'env> Context<'env> { match id_opt { None => { let msg = format!("Failed to resolve pattern binder {}", name); - self.env.add_diag(ice!((loc, msg))); + self.add_diag(ice!((loc, msg))); None } Some(id) => { @@ -1242,8 +1294,7 @@ impl<'env> Context<'env> { "Invalid usage of '{usage}'. \ '{usage}' can only be used inside a loop body or lambda", ); - self.env - .add_diag(diag!(TypeSafety::InvalidLoopControl, (loc, msg))); + self.add_diag(diag!(TypeSafety::InvalidLoopControl, (loc, msg))); return None; }; if *name_type == NominalBlockType::LambdaLoopCapture { @@ -1281,7 +1332,7 @@ impl<'env> Context<'env> { }; diag.add_secondary_label((loop_label.label.loc, msg)); } - self.env.add_diag(diag); + self.add_diag(diag); return None; } Some(*label) @@ -1337,13 +1388,12 @@ impl<'env> Context<'env> { not 'continue'." } }); - self.env.add_diag(diag); + self.add_diag(diag); None } } else { let msg = format!("Invalid {usage}. Unbound label '{name}"); - self.env - .add_diag(diag!(NameResolution::UnboundLabel, (loc, msg))); + self.add_diag(diag!(NameResolution::UnboundLabel, (loc, msg))); None } } @@ -1549,7 +1599,7 @@ fn make_unbound_module_member_error( name: impl std::fmt::Display, ) -> Diagnostic { let expected = expected.as_ref().unwrap_or(&ErrorKind::ModuleMember); - let same_module = context.current_module == Some(mident); + let same_module = context.current_module == mident; let (prefix, postfix) = if same_module { ("", " in current scope".to_string()) } else { @@ -1572,7 +1622,7 @@ fn make_invalid_module_member_kind_error( actual: &ResolvedModuleMember, ) -> Diagnostic { let mident = actual.mident(); - let same_module = context.current_module == Some(mident); + let same_module = context.current_module == mident; let (prefix, postfix) = if same_module { ("", " in current scope".to_string()) } else { @@ -1604,13 +1654,13 @@ fn arity_string(arity: usize) -> &'static str { //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: E::Program, ) -> N::Program { - let mut context = Context::new(compilation_env, pre_compiled_lib.clone(), &prog); + let outer_context = OuterContext::new(compilation_env, pre_compiled_lib.clone(), &prog); let E::Program { modules: emodules } = prog; - let modules = modules(&mut context, emodules); + let modules = modules(compilation_env, &outer_context, emodules); let mut inner = N::Program_ { modules }; let mut info = NamingProgramInfo::new(pre_compiled_lib, &inner); super::resolve_use_funs::program(compilation_env, &mut info, &mut inner); @@ -1618,18 +1668,19 @@ pub fn program( } fn modules( - context: &mut Context, + env: &CompilationEnv, + outer: &OuterContext, modules: UniqueMap, ) -> UniqueMap { - modules.map(|ident, mdef| module(context, ident, mdef)) + modules.map(|ident, mdef| module(env, outer, ident, mdef)) } fn module( - context: &mut Context, + env: &CompilationEnv, + outer: &OuterContext, ident: ModuleIdent, mdef: E::ModuleDefinition, ) -> N::ModuleDefinition { - context.current_module = Some(ident); let E::ModuleDefinition { loc, warning_filter, @@ -1643,8 +1694,8 @@ fn module( functions: efunctions, constants: econstants, } = mdef; - context.current_package = package_name; - context.env.add_warning_filter_scope(warning_filter.clone()); + let context = &mut Context::new(env, outer, package_name, ident); + context.push_warning_filter_scope(warning_filter.clone()); let mut use_funs = use_funs(context, euse_funs); let mut syntax_methods = N::SyntaxMethods::new(); let friends = efriends.filter_map(|mident, f| friend(context, mident, f)); @@ -1699,8 +1750,7 @@ fn module( if has_macro { mark_all_use_funs_as_used(&mut use_funs); } - context.env.pop_warning_filter_scope(); - context.current_package = None; + context.pop_warning_filter_scope(); N::ModuleDefinition { loc, warning_filter, @@ -1736,7 +1786,7 @@ fn use_funs(context: &mut Context, eufs: E::UseFuns) -> N::UseFuns { let nuf_loc = nuf.loc; if let Err((_, prev)) = methods.add(method, nuf) { let msg = format!("Duplicate 'use fun' for '{}.{}'", tn, method); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (nuf_loc, msg), (prev, "Previously declared here"), @@ -1774,9 +1824,7 @@ fn explicit_use_fun( } ResolvedUseFunFunction::Builtin(_) => { let msg = "Invalid 'use fun'. Cannot use a builtin function as a method"; - context - .env - .add_diag(diag!(Declarations::InvalidUseFun, (loc, msg))); + context.add_diag(diag!(Declarations::InvalidUseFun, (loc, msg))); None } ResolvedUseFunFunction::Unbound => { @@ -1809,7 +1857,7 @@ fn explicit_use_fun( ResolvedType::Hole => { let msg = "Invalid 'use fun'. Cannot associate a method with an inferred type"; let tmsg = "The '_' type is a placeholder for type inference"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidUseFun, (loc, msg), (ty_loc, tmsg) @@ -1822,7 +1870,7 @@ fn explicit_use_fun( "But '{}' was declared as a type parameter here", tp.user_specified_name ); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidUseFun, (loc, msg,), (tloc, tmsg) @@ -1855,7 +1903,7 @@ fn check_use_fun_scope( return true; }; let current_module = context.current_module; - let Err(def_loc_opt) = use_fun_module_defines(context, use_fun_loc, current_module, rtype) + let Err(def_loc_opt) = use_fun_module_defines(context, use_fun_loc, ¤t_module, rtype) else { return true; }; @@ -1874,22 +1922,19 @@ fn check_use_fun_scope( if let Some(def_loc) = def_loc_opt { diag.add_secondary_label((def_loc, "Type defined in another module here")); } - context.env.add_diag(diag); + context.add_diag(diag); false } fn use_fun_module_defines( context: &mut Context, use_fun_loc: &Loc, - specified: Option, + specified: &ModuleIdent, rtype: &ResolvedType, ) -> Result<(), Option> { match rtype { ResolvedType::ModuleType(mtype) => { - if specified - .as_ref() - .is_some_and(|mident| mident == &mtype.mident()) - { + if specified == &mtype.mident() { Ok(()) } else { Err(Some(mtype.decl_loc())) @@ -1897,11 +1942,10 @@ fn use_fun_module_defines( } ResolvedType::BuiltinType(b_) => { let definer_opt = context.env.primitive_definer(*b_); - match (definer_opt, &specified) { - (None, _) => Err(None), - (Some(d), None) => Err(Some(d.loc)), - (Some(d), Some(s)) => { - if d == s { + match definer_opt { + None => Err(None), + Some(d) => { + if d == specified { Ok(()) } else { Err(Some(d.loc)) @@ -1910,7 +1954,7 @@ fn use_fun_module_defines( } } ResolvedType::TParam(_, _) | ResolvedType::Hole | ResolvedType::Unbound => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *use_fun_loc, "Tried to validate use fun for invalid type" ))); @@ -1943,20 +1987,20 @@ fn mark_all_use_funs_as_used(use_funs: &mut N::UseFuns) { //************************************************************************************************** fn friend(context: &mut Context, mident: ModuleIdent, friend: E::Friend) -> Option { - let current_mident = context.current_module.as_ref().unwrap(); + let current_mident = &context.current_module; if mident.value.address != current_mident.value.address { // NOTE: in alignment with the bytecode verifier, this constraint is a policy decision // rather than a technical requirement. The compiler, VM, and bytecode verifier DO NOT // rely on the assumption that friend modules must reside within the same account address. let msg = "Cannot declare modules out of the current address as a friend"; - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidFriendDeclaration, (friend.loc, "Invalid friend declaration"), (mident.loc, msg), )); None } else if &mident == current_mident { - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidFriendDeclaration, (friend.loc, "Invalid friend declaration"), (mident.loc, "Cannot declare the module itself as a friend"), @@ -1998,7 +2042,7 @@ fn function( assert!(context.nominal_block_id == 0); assert!(context.used_fun_tparams.is_empty()); assert!(context.used_locals.is_empty()); - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); context.local_scopes = vec![BTreeMap::new()]; context.local_count = BTreeMap::new(); context.translating_fun = true; @@ -2015,9 +2059,7 @@ fn function( if !context.used_fun_tparams.contains(&tparam.id) { let sp!(loc, n) = tparam.user_specified_name; let msg = format!("Unused type parameter '{}'.", n); - context - .env - .add_diag(diag!(UnusedItem::FunTypeParam, (loc, msg))) + context.add_diag(diag!(UnusedItem::FunTypeParam, (loc, msg))) } } } @@ -2042,7 +2084,7 @@ fn function( context.nominal_block_id = 0; context.used_fun_tparams = BTreeSet::new(); context.used_locals = BTreeSet::new(); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); context.translating_fun = false; f } @@ -2073,14 +2115,14 @@ fn function_signature( ); let mut diag = diag!(NameResolution::InvalidMacroParameter, (mutloc, msg)); diag.add_note(ASSIGN_SYNTAX_IDENTIFIER_NOTE); - context.env.add_diag(diag); + context.add_diag(diag); mut_ = Mutability::Imm; } } if let Err((param, prev_loc)) = declared.add(param, ()) { if !is_underscore { let msg = format!("Duplicate parameter with name '{}'", param); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (param.loc(), msg), (prev_loc, "Previously declared here"), @@ -2129,10 +2171,10 @@ fn struct_def( type_parameters, fields, } = sdef; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let type_parameters = datatype_type_parameters(context, type_parameters); let fields = struct_fields(context, fields); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); N::StructDefinition { warning_filter, index, @@ -2187,10 +2229,10 @@ fn enum_def( type_parameters, variants, } = edef; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); let type_parameters = datatype_type_parameters(context, type_parameters); let variants = enum_variants(context, variants); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); N::EnumDefinition { warning_filter, index, @@ -2259,7 +2301,7 @@ fn constant(context: &mut Context, _name: ConstantName, econstant: E::Constant) assert!(context.local_scopes.is_empty()); assert!(context.local_count.is_empty()); assert!(context.used_locals.is_empty()); - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); context.local_scopes = vec![BTreeMap::new()]; let signature = type_(context, TypeAnnotation::ConstantSignature, esignature); let value = *exp(context, Box::new(evalue)); @@ -2267,7 +2309,7 @@ fn constant(context: &mut Context, _name: ConstantName, econstant: E::Constant) context.local_count = BTreeMap::new(); context.used_locals = BTreeSet::new(); context.nominal_block_id = 0; - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); N::Constant { warning_filter, index, @@ -2325,7 +2367,7 @@ fn type_parameter( context.bind_type(name.value, ResolvedType::TParam(loc, tp.clone())); if let Err((name, old_loc)) = unique_tparams.add(name, ()) { let msg = format!("Duplicate type parameter declared with name '{}'", name); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::DuplicateItem, (loc, msg), (old_loc, "Type parameter previously defined here"), @@ -2392,7 +2434,7 @@ fn type_(context: &mut Context, case: TypeAnnotation, sp!(loc, ety_): E::Type) - if let TypeAnnotation::FunctionSignature = case { diag.add_note("Only 'macro' functions can use '_' in their signatures"); } - context.env.add_diag(diag); + context.add_diag(diag); NT::UnresolvedError } else { // replaced with a type variable during type instantiation @@ -2408,7 +2450,7 @@ fn type_(context: &mut Context, case: TypeAnnotation, sp!(loc, ety_): E::Type) - } RT::TParam(_, tp) => { if !tys.is_empty() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::NamePositionMismatch, (loc, "Generic type parameters cannot take type arguments"), )); @@ -2483,7 +2525,7 @@ fn check_type_instantiation_arity String>( arity, args_len ); - context.env.add_diag(diag!(diag_code, (loc, msg))); + context.add_diag(diag!(diag_code, (loc, msg))); } while ty_args.len() > arity { @@ -2892,7 +2934,7 @@ fn exp(context: &mut Context, e: Box) -> Box { "ICE compiler should not have parsed this form as a specification" )); diag.add_note(format!("Compiler parsed: {}", debug_display!(e))); - context.env.add_diag(diag); + context.add_diag(diag); NE::UnresolvedError } }; @@ -2921,7 +2963,7 @@ fn dotted(context: &mut Context, edot: E::ExpDotted) -> Option { modified by path operations.\n\ Path operations include 'move', 'copy', '&', '&mut', and field references", ); - context.env.add_diag(diag); + context.add_diag(diag); N::ExpDotted_::Exp(Box::new(sp(ne.loc, N::Exp_::UnresolvedError))) } _ => N::ExpDotted_::Exp(ne), @@ -3008,7 +3050,7 @@ fn check_constructor_form( } else { diag.add_note(named_note!()); } - context.env.add_diag(diag); + context.add_diag(diag); } CF::Parens if stype.field_info.is_positional() => (), CF::Parens => { @@ -3018,7 +3060,7 @@ fn check_constructor_form( (loc, &msg), (stype.decl_loc, defn_loc_error(&name)), ); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Braces if stype.field_info.is_positional() => { let msg = invalid_inst_msg!("struct", POSNL_UPCASE, POSNL); @@ -3027,7 +3069,7 @@ fn check_constructor_form( (loc, &msg), (stype.decl_loc, defn_loc_error(&name)), ); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Braces => (), }, @@ -3053,7 +3095,7 @@ fn check_constructor_form( } else { diag.add_note(named_note!()); } - context.env.add_diag(diag); + context.add_diag(diag); } CF::Parens if vfields.is_empty() => { let msg = invalid_inst_msg!("variant", EMPTY_UPCASE, EMPTY); @@ -3063,7 +3105,7 @@ fn check_constructor_form( (vloc, defn_loc_error(&name)), ); diag.add_note(format!("Remove '()' arguments from this {position}")); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Parens if vfields.is_positional() => (), CF::Parens => { @@ -3074,7 +3116,7 @@ fn check_constructor_form( (vloc, defn_loc_error(&name)), ); diag.add_note(named_note!()); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Braces if vfields.is_empty() => { let msg = invalid_inst_msg!("variant", EMPTY_UPCASE, EMPTY); @@ -3084,7 +3126,7 @@ fn check_constructor_form( (vloc, defn_loc_error(&name)), ); diag.add_note(format!("Remove '{{ }}' arguments from this {position}")); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Braces if vfields.is_positional() => { let msg = invalid_inst_msg!("variant", POSNL_UPCASE, POSNL); @@ -3094,7 +3136,7 @@ fn check_constructor_form( (vloc, defn_loc_error(&name)), ); diag.add_note(posnl_note!()); - context.env.add_diag(diag); + context.add_diag(diag); } CF::Braces => (), } @@ -3213,7 +3255,7 @@ fn unique_pattern_binders( diag.add_secondary_label((*loc, "and repeated here")); } diag.add_note("A pattern variable must be unique, and must appear once in each or-pattern alternative."); - context.env.add_diag(diag); + context.add_diag(diag); } enum OrPosn { @@ -3231,7 +3273,7 @@ fn unique_pattern_binders( let mut diag = diag!(NameResolution::InvalidPattern, (var.loc(), primary_msg)); diag.add_secondary_label((other_loc, secondary_msg)); diag.add_note("Both sides of an or-pattern must bind the same variables."); - context.env.add_diag(diag); + context.add_diag(diag); } fn report_mismatched_or_mutability( @@ -3252,7 +3294,7 @@ fn unique_pattern_binders( diag.add_note( "Both sides of an or-pattern must bind the same variables with the same mutability.", ); - context.env.add_diag(diag); + context.add_diag(diag); } type Bindings = BTreeMap>; @@ -3414,7 +3456,7 @@ fn expand_positional_ellipsis( let entries = (0..=missing).map(|_| "_".into()).collect::>(); let info = EllipsisMatchEntries::Positional(entries); let info = ide::IDEAnnotation::EllipsisMatchEntries(Box::new(info)); - context.env.add_ide_annotation(eloc, info); + context.add_ide_annotation(eloc, info); } result } @@ -3451,7 +3493,7 @@ fn expand_named_ellipsis( let entries = fields.iter().map(|field| field.value()).collect::>(); let info = EllipsisMatchEntries::Named(entries); let info = ide::IDEAnnotation::EllipsisMatchEntries(Box::new(info)); - context.env.add_ide_annotation(ellipsis_loc, info); + context.add_ide_annotation(ellipsis_loc, info); } let start_idx = args.len(); @@ -3553,7 +3595,7 @@ fn match_pattern(context: &mut Context, in_pat: Box) -> Box { if etys_opt.is_some() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::TooManyTypeArguments, (ploc, "Constants in patterns do not take type arguments") )); @@ -3663,9 +3705,7 @@ fn lvalue( ((var.loc, msg), (prev_loc, "Previously assigned here")) } }; - context - .env - .add_diag(diag!(Declarations::DuplicateItem, primary, secondary)); + context.add_diag(diag!(Declarations::DuplicateItem, primary, secondary)); } if v.is_syntax_identifier() { debug_assert!( @@ -3679,7 +3719,7 @@ fn lvalue( ); let mut diag = diag!(TypeSafety::CannotExpandMacro, (loc, msg)); diag.add_note(ASSIGN_SYNTAX_IDENTIFIER_NOTE); - context.env.add_diag(diag); + context.add_diag(diag); return None; } let nv = match case { @@ -3725,7 +3765,7 @@ fn lvalue( stype } Some(ResolvedConstructor::Variant(variant)) => { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::NamePositionMismatch, (tn.loc, format!("Invalid {}. Expected a struct", msg)), ( @@ -3795,7 +3835,7 @@ fn lvalue( "ICE compiler should not have parsed this form as a specification" )); diag.add_note(format!("Compiler parsed: {}", debug_display!(e))); - context.env.add_diag(diag); + context.add_diag(diag); NL::Ignore } }; @@ -3808,9 +3848,7 @@ fn check_mut_underscore(context: &mut Context, mut_: Option) { return; }; let msg = "Invalid 'mut' declaration. 'mut' is applied to variables and cannot be applied to the '_' pattern"; - context - .env - .add_diag(diag!(NameResolution::InvalidMut, (loc, msg))); + context.add_diag(diag!(NameResolution::InvalidMut, (loc, msg))); } fn bind_list(context: &mut Context, ls: E::LValueList) -> Option { @@ -3907,9 +3945,7 @@ fn resolve_call( match tyargs_opt.as_deref() { Some([ty]) => B::Freeze(Some(ty.clone())), Some(_tys) => { - context - .env - .add_diag(ice!((call_loc, "Builtin tyarg arity failure"))); + context.add_diag(ice!((call_loc, "Builtin tyarg arity failure"))); return N::Exp_::UnresolvedError; } None => B::Freeze(None), @@ -3930,7 +3966,7 @@ fn resolve_call( let mut diag = diag!(Uncategorized::DeprecatedWillBeRemoved, (call_loc, dep_msg),); diag.add_note(help_msg); - context.env.add_diag(diag); + context.add_diag(diag); } exp_types_opt_with_arity_check( context, @@ -4013,7 +4049,7 @@ fn resolve_call( check_is_not_macro(context, is_macro, &var.value.name); let tyargs_opt = types_opt(context, TypeAnnotation::Expression, in_tyargs_opt); if tyargs_opt.is_some() { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::TooManyTypeArguments, ( subject_loc, @@ -4034,7 +4070,7 @@ fn resolve_call( ); let mut diag = diag!(TypeSafety::InvalidCallTarget, (var.loc, msg)); diag.add_note(note); - context.env.add_diag(diag); + context.add_diag(diag); N::Exp_::UnresolvedError } else if var.value.id != 0 { let msg = format!( @@ -4042,9 +4078,7 @@ fn resolve_call( Only lambda-typed syntax parameters may be invoked", var.value.name ); - context - .env - .add_diag(diag!(TypeSafety::InvalidCallTarget, (var.loc, msg))); + context.add_diag(diag!(TypeSafety::InvalidCallTarget, (var.loc, msg))); N::Exp_::UnresolvedError } else { N::Exp_::VarCall(sp(subject_loc, var.value), args) @@ -4065,9 +4099,7 @@ fn check_is_not_macro(context: &mut Context, is_macro: Option, name: &str) macro", name ); - context - .env - .add_diag(diag!(TypeSafety::InvalidCallTarget, (mloc, msg))); + context.add_diag(diag!(TypeSafety::InvalidCallTarget, (mloc, msg))); } } @@ -4077,9 +4109,7 @@ fn report_invalid_macro(context: &mut Context, is_macro: Option, kind: &str "Unexpected macro invocation. {} cannot be invoked as macros", kind ); - context - .env - .add_diag(diag!(NameResolution::PositionalCallMismatch, (mloc, msg))); + context.add_diag(diag!(NameResolution::PositionalCallMismatch, (mloc, msg))); } } @@ -4104,7 +4134,7 @@ fn exp_types_opt_with_arity_check( }; let msg = fmsg(); let targs_msg = format!("Expected {} type argument(s) but got {}", arity, args_len); - context.env.add_diag(diag!( + context.add_diag(diag!( diag_code, (msg_loc, msg), (tyarg_error_loc, targs_msg) @@ -4378,7 +4408,5 @@ fn report_unused_local(context: &mut Context, sp!(loc, unused_): &N::Var) { let msg = format!( "Unused {kind} '{name}'. Consider removing or prefixing with an underscore: '_{name}'", ); - context - .env - .add_diag(diag!(UnusedItem::Variable, (*loc, msg))); + context.add_diag(diag!(UnusedItem::Variable, (*loc, msg))); } diff --git a/external-crates/move/crates/move-compiler/src/parser/lexer.rs b/external-crates/move/crates/move-compiler/src/parser/lexer.rs index 610d978e733fb..18271da49805d 100644 --- a/external-crates/move/crates/move-compiler/src/parser/lexer.rs +++ b/external-crates/move/crates/move-compiler/src/parser/lexer.rs @@ -482,10 +482,7 @@ impl<'input> Lexer<'input> { // At the end of parsing, checks whether there are any unmatched documentation comments, // producing errors if so. Otherwise returns a map from file position to associated // documentation. - pub fn check_and_get_doc_comments( - &mut self, - env: &mut CompilationEnv, - ) -> MatchedFileCommentMap { + pub fn check_and_get_doc_comments(&mut self, env: &CompilationEnv) -> MatchedFileCommentMap { let msg = "Documentation comment cannot be matched to a language item"; let diags = self .doc_comments @@ -495,7 +492,8 @@ impl<'input> Lexer<'input> { diag!(Syntax::InvalidDocComment, (loc, msg)) }) .collect(); - env.add_diags(diags); + let warning_filters = env.top_level_warning_filter_scope(); + env.add_diags(warning_filters, diags); std::mem::take(&mut self.matched_doc_comments) } diff --git a/external-crates/move/crates/move-compiler/src/parser/mod.rs b/external-crates/move/crates/move-compiler/src/parser/mod.rs index 5b2e299d813e2..724e7e8012b9f 100644 --- a/external-crates/move/crates/move-compiler/src/parser/mod.rs +++ b/external-crates/move/crates/move-compiler/src/parser/mod.rs @@ -25,7 +25,7 @@ use vfs::VfsPath; /// Parses program's targets and dependencies, both of which are read from different virtual file /// systems (vfs and deps_out_vfs, respectively). pub(crate) fn parse_program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, named_address_maps: NamedAddressMaps, mut targets: Vec, mut deps: Vec, @@ -113,7 +113,7 @@ fn ensure_targets_deps_dont_intersect( fn parse_file( path: &VfsPath, - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, files: &mut MappedFiles, package: Option, ) -> anyhow::Result<( @@ -126,8 +126,9 @@ fn parse_file( let file_hash = FileHash::new(&source_buffer); let fname = Symbol::from(path.as_str()); let source_str = Arc::from(source_buffer); + let warning_filters = compilation_env.top_level_warning_filter_scope(); if let Err(ds) = verify_string(file_hash, &source_str) { - compilation_env.add_diags(ds); + compilation_env.add_diags(warning_filters, ds); files.add(file_hash, fname, source_str); return Ok((vec![], MatchedFileCommentMap::new(), file_hash)); } @@ -135,7 +136,7 @@ fn parse_file( { Ok(defs_and_comments) => defs_and_comments, Err(ds) => { - compilation_env.add_diags(ds); + compilation_env.add_diags(warning_filters, ds); (vec![], MatchedFileCommentMap::new()) } }; diff --git a/external-crates/move/crates/move-compiler/src/parser/syntax.rs b/external-crates/move/crates/move-compiler/src/parser/syntax.rs index 7fdf9221d598a..d8301e56732c9 100644 --- a/external-crates/move/crates/move-compiler/src/parser/syntax.rs +++ b/external-crates/move/crates/move-compiler/src/parser/syntax.rs @@ -22,14 +22,14 @@ use move_symbol_pool::{symbol, Symbol}; struct Context<'env, 'lexer, 'input> { current_package: Option, - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, tokens: &'lexer mut Lexer<'input>, stop_set: TokenSet, } impl<'env, 'lexer, 'input> Context<'env, 'lexer, 'input> { fn new( - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, tokens: &'lexer mut Lexer<'input>, package_name: Option, ) -> Self { @@ -71,8 +71,9 @@ impl<'env, 'lexer, 'input> Context<'env, 'lexer, 'input> { } } - fn add_diag(&mut self, diag: Diagnostic) { - self.env.add_diag(diag); + fn add_diag(&self, diag: Diagnostic) { + let warning_filters = self.env.top_level_warning_filter_scope(); + self.env.add_diag(warning_filters, diag); } } @@ -758,15 +759,13 @@ fn parse_name_access_chain_<'a, F: Fn() -> &'a str>( "Macro invocation are disallowed here. Expected {}", item_description() ); - context - .env - .add_diag(diag!(Syntax::InvalidName, (*loc, msg))); + context.add_diag(diag!(Syntax::InvalidName, (*loc, msg))); is_macro = None; } } if let Some(sp!(ty_loc, _)) = tys { if !tyargs_allowed { - context.env.add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidName, ( ty_loc, @@ -845,7 +844,7 @@ fn parse_name_access_chain_<'a, F: Fn() -> &'a str>( parse_macro_opt_and_tyargs_opt(context, tyargs_whitespace_allowed, name.loc); if let Some(loc) = &is_macro { if !macros_allowed { - context.env.add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidName, ( *loc, @@ -857,7 +856,7 @@ fn parse_name_access_chain_<'a, F: Fn() -> &'a str>( } if let Some(sp!(ty_loc, _)) = tys { if !tyargs_allowed { - context.env.add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidName, ( ty_loc, @@ -870,7 +869,7 @@ fn parse_name_access_chain_<'a, F: Fn() -> &'a str>( path.push_path_entry(name, tys, is_macro) .into_iter() - .for_each(|diag| context.env.add_diag(diag)); + .for_each(|diag| context.add_diag(diag)); } Ok(NameAccessChain_::Path(path)) } @@ -2124,7 +2123,7 @@ fn parse_match_pattern(context: &mut Context) -> Result { if context.at_stop_set() { - context - .env - .add_diag(*unexpected_token_error(context.tokens, "a type name")); + context.add_diag(*unexpected_token_error(context.tokens, "a type name")); Type_::UnresolvedError } else { let tn = if whitespace_sensitive_ty_args { @@ -3502,7 +3499,7 @@ fn check_enum_visibility(visibility: Option, context: &mut Context) let note = "Visibility annotations are required on enum declarations."; let mut err = diag!(Syntax::InvalidModifier, (loc, msg)); err.add_note(note); - context.env.add_diag(err); + context.add_diag(err); } } } @@ -3952,9 +3949,7 @@ fn parse_address_block( addr_name.loc.start() as usize, context.tokens.current_token_loc().end() as usize, ); - context - .env - .add_diag(diag!(Migration::AddressRemove, (loc, "address decl"))); + context.add_diag(diag!(Migration::AddressRemove, (loc, "address decl"))); } context.tokens.advance()?; let mut modules = vec![]; @@ -3969,7 +3964,7 @@ fn parse_address_block( let (module, next_mod_attributes) = parse_module(attributes, context)?; if in_migration_mode { - context.env.add_diag(diag!( + context.add_diag(diag!( Migration::AddressAdd, ( module.name.loc(), @@ -3989,7 +3984,7 @@ fn parse_address_block( } for module in &modules { if matches!(module.definition_mode, ModuleDefinitionMode::Semicolon) { - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidModule, ( module.name.loc(), @@ -4001,9 +3996,7 @@ fn parse_address_block( if in_migration_mode { let loc = context.tokens.current_token_loc(); - context - .env - .add_diag(diag!(Migration::AddressRemove, (loc, "close lbrace"))); + context.add_diag(diag!(Migration::AddressRemove, (loc, "close lbrace"))); } consume_token(context.tokens, context.tokens.peek())?; @@ -4023,7 +4016,7 @@ fn parse_address_block( format!("Replace with '{}::{}'", addr, module.name), )); } - context.env.add_diag(diag); + context.add_diag(diag); } Ok(AddressDefinition { @@ -4054,7 +4047,7 @@ fn parse_friend_decl( || "a friend declaration", )?; if friend.value.is_macro().is_some() || friend.value.has_tyargs() { - context.env.add_diag(diag!( + context.add_diag(diag!( Syntax::InvalidName, (friend.loc, "Invalid 'friend' name") )) @@ -4669,7 +4662,7 @@ fn parse_file_def( "Either move each 'module' label and definitions into its own file or \ define each as 'module { contents }'", ); - context.env.add_diag(diag); + context.add_diag(diag); } } defs.push(Definition::Module(module)); @@ -4692,7 +4685,7 @@ fn parse_file_def( /// result as either a pair of FileDefinition and doc comments or some Diagnostics. The `file` name /// is used to identify source locations in error messages. pub fn parse_file_string( - env: &mut CompilationEnv, + env: &CompilationEnv, file_hash: FileHash, input: &str, package: Option, diff --git a/external-crates/move/crates/move-compiler/src/parser/verification_attribute_filter.rs b/external-crates/move/crates/move-compiler/src/parser/verification_attribute_filter.rs index 46c94e75991dd..4e23c1a5003b8 100644 --- a/external-crates/move/crates/move-compiler/src/parser/verification_attribute_filter.rs +++ b/external-crates/move/crates/move-compiler/src/parser/verification_attribute_filter.rs @@ -15,13 +15,13 @@ use crate::{ }; struct Context<'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, is_source_def: bool, current_package: Option, } impl<'env> Context<'env> { - fn new(env: &'env mut CompilationEnv) -> Self { + fn new(env: &'env CompilationEnv) -> Self { Self { env, is_source_def: false, @@ -56,6 +56,7 @@ impl FilterContext for Context<'_> { // expansion // Ideally we would just have a warning filter scope here // (but again, need expansion for that) + let top_warning_filter_scope = self.env.top_level_warning_filter_scope(); let silence_warning = !self.is_source_def || self.env.package_config(self.current_package).is_dependency; if !silence_warning { @@ -64,8 +65,10 @@ impl FilterContext for Context<'_> { "The '{}' attribute has been deprecated along with specification blocks", VerificationAttribute::VERIFY_ONLY ); - self.env - .add_diag(diag!(Uncategorized::DeprecatedWillBeRemoved, (*loc, msg))); + self.env.add_diag( + top_warning_filter_scope, + diag!(Uncategorized::DeprecatedWillBeRemoved, (*loc, msg)), + ); } } should_remove @@ -79,7 +82,7 @@ impl FilterContext for Context<'_> { // This filters out all AST elements annotated with verify-only annotated from `prog` // if the `verify` flag in `compilation_env` is not set. If the `verify` flag is set, // no filtering is performed. -pub fn program(compilation_env: &mut CompilationEnv, prog: P::Program) -> P::Program { +pub fn program(compilation_env: &CompilationEnv, prog: P::Program) -> P::Program { let mut context = Context::new(compilation_env); filter_program(&mut context, prog) } diff --git a/external-crates/move/crates/move-compiler/src/shared/matching.rs b/external-crates/move/crates/move-compiler/src/shared/matching.rs index 26ca069a61b9b..9beb38564ab7b 100644 --- a/external-crates/move/crates/move-compiler/src/shared/matching.rs +++ b/external-crates/move/crates/move-compiler/src/shared/matching.rs @@ -67,7 +67,7 @@ pub struct ArmResult { /// A shared match context trait for use with counterexample generation in Typing and match /// compilation in HLIR lowering. pub trait MatchContext { - fn env(&mut self) -> &mut CompilationEnv; + fn env(&mut self) -> &CompilationEnv; fn env_ref(&self) -> &CompilationEnv; fn new_match_var(&mut self, name: String, loc: Loc) -> N::Var; fn program_info(&self) -> &ProgramInfo; @@ -481,7 +481,7 @@ impl PatternMatrix { // Make a match pattern that only holds guard binders let guard_binders = guard_binders.union_with(&const_binders, |k, _, x| { let msg = "Match compilation made a binder for this during const compilation"; - context.env().add_diag(ice!((k.loc, msg))); + context.env().add_error_diag(ice!((k.loc, msg))); *x }); let pat = apply_pattern_subst(pat, &guard_binders); diff --git a/external-crates/move/crates/move-compiler/src/shared/mod.rs b/external-crates/move/crates/move-compiler/src/shared/mod.rs index b0609c6f4fd93..d094d5f2051a2 100644 --- a/external-crates/move/crates/move-compiler/src/shared/mod.rs +++ b/external-crates/move/crates/move-compiler/src/shared/mod.rs @@ -33,14 +33,12 @@ use move_ir_types::location::*; use move_symbol_pool::Symbol; use petgraph::{algo::astar as petgraph_astar, graphmap::DiGraphMap}; use std::{ - cell::RefCell, collections::{BTreeMap, BTreeSet}, fmt, hash::Hash, - rc::Rc, sync::{ atomic::{AtomicUsize, Ordering as AtomicOrdering}, - Arc, + Arc, Mutex, OnceLock, RwLock, }, }; use vfs::{VfsError, VfsPath}; @@ -239,10 +237,9 @@ pub type FilterName = Symbol; pub struct CompilationEnv { flags: Flags, - // filters warnings when added. - warning_filter: Vec, - diags: Diagnostics, - visitors: Rc, + top_level_warning_filter_scope: &'static WarningFiltersScope, + diags: RwLock, + visitors: Visitors, package_configs: BTreeMap, /// Config for any package not found in `package_configs`, or for inputs without a package. default_config: PackageConfig, @@ -250,13 +247,17 @@ pub struct CompilationEnv { known_filters: BTreeMap>>, /// Maps a diagnostics ID to a known filter name. known_filter_names: BTreeMap, - prim_definers: - BTreeMap, + prim_definers: OnceLock>, // TODO(tzakian): Remove the global counter and use this counter instead // pub counter: u64, mapped_files: MappedFiles, save_hooks: Vec, - pub ide_information: IDEInfo, + ide_information: RwLock, +} + +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct WarningFiltersScope { + scopes: Vec, } macro_rules! known_code_filter { @@ -278,6 +279,7 @@ impl CompilationEnv { flags: Flags, mut visitors: Vec, save_hooks: Vec, + warning_filters: Option, package_configs: BTreeMap, default_config: Option, ) -> Self { @@ -363,30 +365,32 @@ impl CompilationEnv { }) .collect(); - let warning_filter = if flags.silence_warnings() { + let top_level_warning_filter = if flags.silence_warnings() { let mut f = WarningFilters::new_for_source(); f.add(WarningFilter::All(None)); - vec![f] + Some(f) } else { - vec![] + warning_filters }; + let top_level_warning_filter_scope = + Box::leak(Box::new(WarningFiltersScope::new(top_level_warning_filter))); let mut diags = Diagnostics::new(); if flags.json_errors() { diags.set_format(DiagnosticsFormat::JSON); } Self { flags, - warning_filter, - diags, - visitors: Rc::new(Visitors::new(visitors)), + top_level_warning_filter_scope, + diags: RwLock::new(diags), + visitors: Visitors::new(visitors), package_configs, default_config: default_config.unwrap_or_default(), known_filters, known_filter_names, - prim_definers: BTreeMap::new(), + prim_definers: OnceLock::new(), mapped_files: MappedFiles::empty(), save_hooks, - ide_information: IDEInfo::new(), + ide_information: RwLock::new(IDEInfo::new()), } } @@ -403,10 +407,16 @@ impl CompilationEnv { &self.mapped_files } - pub fn add_diag(&mut self, mut diag: Diagnostic) { + pub fn top_level_warning_filter_scope(&self) -> &'static WarningFiltersScope { + self.top_level_warning_filter_scope + } + + pub fn add_diag(&self, warning_filters: &WarningFiltersScope, mut diag: Diagnostic) { if diag.info().severity() <= Severity::NonblockingError && self .diags + .read() + .unwrap() .any_syntax_error_with_primary_loc(diag.primary_loc()) { // do not report multiple diags for the same location (unless they are blocking) to @@ -417,7 +427,7 @@ impl CompilationEnv { return; } - if !self.is_filtered(&diag) { + if !warning_filters.is_filtered(&diag) { // add help to suppress warning, if applicable // TODO do we want a centralized place for tips like this? if diag.info().severity() == Severity::Warning { @@ -434,21 +444,34 @@ impl CompilationEnv { diag = diag.set_severity(Severity::NonblockingError) } } - self.diags.add(diag) - } else if !self.filter_for_dependency() { + self.diags.write().unwrap().add(diag) + } else if !warning_filters.is_filtered_for_dependency() { // unwrap above is safe as the filter has been used (thus it must exist) - self.diags.add_source_filtered(diag) + self.diags.write().unwrap().add_source_filtered(diag) } } - pub fn add_diags(&mut self, diags: Diagnostics) { + pub fn add_diags(&self, warning_filters: &WarningFiltersScope, diags: Diagnostics) { for diag in diags.into_vec() { - self.add_diag(diag) + self.add_diag(warning_filters, diag) + } + } + + /// Aborts if the diagnostic is a warning + pub fn add_error_diag(&self, diag: Diagnostic) { + assert!(diag.info().severity() > Severity::Warning); + self.add_diag(WarningFiltersScope::EMPTY, diag) + } + + /// Aborts if any diagnostic is a warning + pub fn add_error_diags(&self, diags: Diagnostics) { + for diag in diags.into_vec() { + self.add_error_diag(diag) } } pub fn has_warnings_or_errors(&self) -> bool { - !self.diags.is_empty() + !self.diags.read().unwrap().is_empty() } pub fn has_errors(&self) -> bool { @@ -457,63 +480,45 @@ impl CompilationEnv { } pub fn count_diags(&self) -> usize { - self.diags.len() + self.diags.read().unwrap().len() } pub fn count_diags_at_or_above_severity(&self, threshold: Severity) -> usize { - self.diags.count_diags_at_or_above_severity(threshold) + self.diags + .read() + .unwrap() + .count_diags_at_or_above_severity(threshold) } pub fn has_diags_at_or_above_severity(&self, threshold: Severity) -> bool { - self.diags.max_severity_at_or_above_severity(threshold) + self.diags + .read() + .unwrap() + .max_severity_at_or_above_severity(threshold) } - pub fn check_diags_at_or_above_severity( - &mut self, - threshold: Severity, - ) -> Result<(), Diagnostics> { + pub fn check_diags_at_or_above_severity(&self, threshold: Severity) -> Result<(), Diagnostics> { if self.has_diags_at_or_above_severity(threshold) { - Err(std::mem::take(&mut self.diags)) + let diagnostics: &mut Diagnostics = &mut self.diags.write().unwrap(); + Err(std::mem::take(diagnostics)) } else { Ok(()) } } /// Should only be called after compilation is finished - pub fn take_final_diags(&mut self) -> Diagnostics { - std::mem::take(&mut self.diags) + pub fn take_final_diags(&self) -> Diagnostics { + let diagnostics: &mut Diagnostics = &mut self.diags.write().unwrap(); + std::mem::take(diagnostics) } /// Should only be called after compilation is finished - pub fn take_final_warning_diags(&mut self) -> Diagnostics { + pub fn take_final_warning_diags(&self) -> Diagnostics { let final_diags = self.take_final_diags(); debug_assert!(final_diags.max_severity_at_or_under_severity(Severity::Warning)); final_diags } - /// Add a new filter for warnings - pub fn add_warning_filter_scope(&mut self, filter: WarningFilters) { - self.warning_filter.push(filter) - } - - pub fn pop_warning_filter_scope(&mut self) { - self.warning_filter.pop().unwrap(); - } - - fn is_filtered(&self, diag: &Diagnostic) -> bool { - self.warning_filter - .iter() - .rev() - .any(|filter| filter.is_filtered(diag)) - } - - fn filter_for_dependency(&self) -> bool { - self.warning_filter - .iter() - .rev() - .any(|filter| filter.for_dependency()) - } - pub fn known_filter_names(&self) -> impl IntoIterator + '_ { self.known_filters.keys().copied() } @@ -573,24 +578,19 @@ impl CompilationEnv { &self.flags } - pub fn visitors(&self) -> Rc { - self.visitors.clone() + pub fn visitors(&self) -> &Visitors { + &self.visitors } // Logs an error if the feature isn't supported. Returns `false` if the feature is not // supported, and `true` otherwise. - pub fn check_feature( - &mut self, - package: Option, - feature: FeatureGate, - loc: Loc, - ) -> bool { + pub fn check_feature(&self, package: Option, feature: FeatureGate, loc: Loc) -> bool { check_feature_or_error(self, self.package_config(package).edition, feature, loc) } // Returns an error string if if the feature isn't supported, or None otherwise. pub fn feature_edition_error_msg( - &mut self, + &self, feature: FeatureGate, package: Option, ) -> Option { @@ -619,15 +619,12 @@ impl CompilationEnv { ) } - pub fn set_primitive_type_definers( - &mut self, - m: BTreeMap, - ) { - self.prim_definers = m + pub fn set_primitive_type_definers(&self, m: BTreeMap) { + self.prim_definers.set(m).unwrap() } pub fn primitive_definer(&self, t: N::BuiltinTypeName_) -> Option<&E::ModuleIdent> { - self.prim_definers.get(&t) + self.prim_definers.get().and_then(|m| m.get(&t)) } pub fn save_parser_ast(&self, ast: &P::Program) { @@ -678,22 +675,61 @@ impl CompilationEnv { self.flags.ide_mode() } - pub fn extend_ide_info(&mut self, info: IDEInfo) { + pub fn extend_ide_info(&self, warning_filters: &WarningFiltersScope, info: IDEInfo) { if self.flags().ide_test_mode() { for entry in info.annotations.iter() { let diag = entry.clone().into(); - self.add_diag(diag); + self.add_diag(warning_filters, diag); } } - self.ide_information.extend(info); + self.ide_information.write().unwrap().extend(info); } - pub fn add_ide_annotation(&mut self, loc: Loc, info: IDEAnnotation) { + pub fn add_ide_annotation( + &self, + warning_filters: &WarningFiltersScope, + loc: Loc, + info: IDEAnnotation, + ) { if self.flags().ide_test_mode() { let diag = (loc, info.clone()).into(); - self.add_diag(diag); + self.add_diag(warning_filters, diag); + } + self.ide_information + .write() + .unwrap() + .add_ide_annotation(loc, info); + } + + pub fn ide_information(&self) -> std::sync::RwLockReadGuard<'_, IDEInfo> { + self.ide_information.read().unwrap() + } +} + +impl WarningFiltersScope { + /// Unsafe and should be used only for internal purposes, such as ide annotations + const EMPTY: &'static Self = &WarningFiltersScope { scopes: vec![] }; + + fn new(top_level_warning_filter: Option) -> Self { + Self { + scopes: top_level_warning_filter.into_iter().collect(), } - self.ide_information.add_ide_annotation(loc, info); + } + + pub fn push(&mut self, filters: WarningFilters) { + self.scopes.push(filters) + } + + pub fn pop(&mut self) { + self.scopes.pop().unwrap(); + } + + pub fn is_filtered(&self, diag: &Diagnostic) -> bool { + self.scopes.iter().any(|filters| filters.is_filtered(diag)) + } + + pub fn is_filtered_for_dependency(&self) -> bool { + self.scopes.iter().any(|filters| filters.for_dependency()) } } @@ -974,6 +1010,7 @@ fn check() {} fn check_all() { check::(); check::<&Visitors>(); + check::<&CompilationEnv>(); } //************************************************************************************************** @@ -981,7 +1018,7 @@ fn check_all() { //************************************************************************************************** #[derive(Clone)] -pub struct SaveHook(Rc>); +pub struct SaveHook(Arc>); #[derive(Clone)] pub(crate) struct SavedInfo { @@ -1009,7 +1046,7 @@ pub enum SaveFlag { impl SaveHook { pub fn new(flags: impl IntoIterator) -> Self { let flags = flags.into_iter().collect(); - Self(Rc::new(RefCell::new(SavedInfo { + Self(Arc::new(Mutex::new(SavedInfo { flags, parser: None, expansion: None, @@ -1022,56 +1059,56 @@ impl SaveHook { } pub(crate) fn save_parser_ast(&self, ast: &P::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.parser.is_none() && r.flags.contains(&SaveFlag::Parser) { r.parser = Some(ast.clone()) } } pub(crate) fn save_expansion_ast(&self, ast: &E::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.expansion.is_none() && r.flags.contains(&SaveFlag::Expansion) { r.expansion = Some(ast.clone()) } } pub(crate) fn save_naming_ast(&self, ast: &N::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.naming.is_none() && r.flags.contains(&SaveFlag::Naming) { r.naming = Some(ast.clone()) } } pub(crate) fn save_typing_ast(&self, ast: &T::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.typing.is_none() && r.flags.contains(&SaveFlag::Typing) { r.typing = Some(ast.clone()) } } pub(crate) fn save_typing_info(&self, info: &Arc) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.typing_info.is_none() && r.flags.contains(&SaveFlag::TypingInfo) { r.typing_info = Some(info.clone()) } } pub(crate) fn save_hlir_ast(&self, ast: &H::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.hlir.is_none() && r.flags.contains(&SaveFlag::HLIR) { r.hlir = Some(ast.clone()) } } pub(crate) fn save_cfgir_ast(&self, ast: &G::Program) { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); if r.cfgir.is_none() && r.flags.contains(&SaveFlag::CFGIR) { r.cfgir = Some(ast.clone()) } } pub fn take_parser_ast(&self) -> P::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::Parser), "Parser AST not saved. Please set the flag when creating the SaveHook" @@ -1080,7 +1117,7 @@ impl SaveHook { } pub fn take_expansion_ast(&self) -> E::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::Expansion), "Expansion AST not saved. Please set the flag when creating the SaveHook" @@ -1089,7 +1126,7 @@ impl SaveHook { } pub fn take_naming_ast(&self) -> N::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::Naming), "Naming AST not saved. Please set the flag when creating the SaveHook" @@ -1098,7 +1135,7 @@ impl SaveHook { } pub fn take_typing_ast(&self) -> T::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::Typing), "Typing AST not saved. Please set the flag when creating the SaveHook" @@ -1107,7 +1144,7 @@ impl SaveHook { } pub fn take_typing_info(&self) -> Arc { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::TypingInfo), "Typing info not saved. Please set the flag when creating the SaveHook" @@ -1116,7 +1153,7 @@ impl SaveHook { } pub fn take_hlir_ast(&self) -> H::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::HLIR), "HLIR AST not saved. Please set the flag when creating the SaveHook" @@ -1125,7 +1162,7 @@ impl SaveHook { } pub fn take_cfgir_ast(&self) -> G::Program { - let mut r = RefCell::borrow_mut(&self.0); + let mut r = self.0.lock().unwrap(); assert!( r.flags.contains(&SaveFlag::CFGIR), "CFGIR AST not saved. Please set the flag when creating the SaveHook" diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs b/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs index 2a67686ce4ba2..03d7d42a388c6 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/id_leak.rs @@ -20,7 +20,7 @@ use crate::{ expansion::ast::{ModuleIdent, TargetKind}, hlir::ast::{self as H, Exp, Label, ModuleCall, SingleType, Type, Type_, Var}, parser::ast::Ability_, - shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier}, + shared::{program_info::TypingProgramInfo, Identifier}, sui_mode::{OBJECT_NEW, TEST_SCENARIO_MODULE_NAME, TS_NEW_OBJECT}, }; use std::collections::BTreeMap; @@ -94,7 +94,6 @@ impl SimpleAbsIntConstructor for IDLeakVerifier { type AI<'a> = IDLeakVerifierAI<'a>; fn new<'a>( - env: &CompilationEnv, context: &'a CFGContext<'a>, cfg: &ImmForwardCFG, _init_state: &mut as SimpleAbsInt>::State, @@ -102,7 +101,7 @@ impl SimpleAbsIntConstructor for IDLeakVerifier { let module = &context.module; let minfo = context.info.module(module); let package_name = minfo.package; - let config = env.package_config(package_name); + let config = context.env.package_config(package_name); if config.flavor != Flavor::Sui { // Skip if not sui return None; diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/info.rs b/external-crates/move/crates/move-compiler/src/sui_mode/info.rs index 614443d2c2679..68538ae7b1c50 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/info.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/info.rs @@ -271,7 +271,7 @@ fn add_private_transfers( transferred: &'a mut BTreeMap<(ModuleIdent, DatatypeName), TransferKind>, } impl<'a> TypingVisitorContext for TransferVisitor<'a> { - fn add_warning_filter_scope(&mut self, _: crate::diagnostics::WarningFilters) { + fn push_warning_filter_scope(&mut self, _: crate::diagnostics::WarningFilters) { unreachable!("no warning filters in function bodies") } diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs index 085135f676b0d..f0e542d5a50af 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/custom_state_change.rs @@ -29,7 +29,7 @@ use crate::{ BaseType_, Label, ModuleCall, SingleType, SingleType_, Type, TypeName_, Type_, Var, }, parser::ast::Ability_, - shared::{CompilationEnv, Identifier}, + shared::Identifier, }; use std::collections::BTreeMap; @@ -87,7 +87,6 @@ impl SimpleAbsIntConstructor for CustomStateChangeVerifier { type AI<'a> = CustomStateChangeVerifierAI; fn new<'a>( - _env: &CompilationEnv, context: &'a CFGContext<'a>, cfg: &ImmForwardCFG, init_state: &mut State, diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs index e5f9c63aecd00..58c5ff438df27 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/freeze_wrapped.rs @@ -7,6 +7,7 @@ use std::{collections::BTreeMap, sync::Arc}; +use crate::shared::WarningFiltersScope; use crate::{ diag, diagnostics::{ @@ -74,7 +75,8 @@ type WrappingFields = pub struct FreezeWrappedVisitor; pub struct Context<'a> { - env: &'a mut CompilationEnv, + env: &'a CompilationEnv, + warning_filters_scope: WarningFiltersScope, program_info: Arc, /// Memoizes information about struct fields wrapping other objects as they are discovered wrapping_fields: WrappingFields, @@ -83,9 +85,11 @@ pub struct Context<'a> { impl TypingVisitorConstructor for FreezeWrappedVisitor { type Context<'a> = Context<'a>; - fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a CompilationEnv, program: &T::Program) -> Self::Context<'a> { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, program_info: program.info.clone(), wrapping_fields: WrappingFields::new(), } @@ -93,13 +97,13 @@ impl TypingVisitorConstructor for FreezeWrappedVisitor { } impl Context<'_> { - fn add_diag(&mut self, diag: Diagnostic) { - self.env.add_diag(diag); + fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); } #[allow(unused)] - fn add_diags(&mut self, diags: Diagnostics) { - self.env.add_diags(diags); + fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); } } @@ -151,12 +155,12 @@ impl<'a> TypingVisitorContext for Context<'a> { false } - fn add_warning_filter_scope(&mut self, filter: WarningFilters) { - self.env.add_warning_filter_scope(filter) + fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } } diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs index 84f8ca01f41e7..45ab199583213 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/self_transfer.rs @@ -23,7 +23,6 @@ use crate::{ }, hlir::ast::{Label, ModuleCall, Type, Type_, Var}, parser::ast::Ability_, - shared::CompilationEnv, }; use std::collections::BTreeMap; @@ -80,7 +79,6 @@ impl SimpleAbsIntConstructor for SelfTransferVerifier { type AI<'a> = SelfTransferVerifierAI; fn new<'a>( - _env: &CompilationEnv, context: &'a CFGContext<'a>, cfg: &ImmForwardCFG, _init_state: &mut as SimpleAbsInt>::State, diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs b/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs index a3e44f87a3a2d..86003cd647ca6 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/linters/share_owned.rs @@ -32,7 +32,7 @@ use crate::{ parser::ast::{Ability_, DatatypeName}, shared::{ program_info::{DatatypeKind, TypingProgramInfo}, - CompilationEnv, Identifier, + Identifier, }, sui_mode::{ info::{SuiInfo, TransferKind}, @@ -96,7 +96,6 @@ impl SimpleAbsIntConstructor for ShareOwnedVerifier { type AI<'a> = ShareOwnedVerifierAI<'a>; fn new<'a>( - _env: &CompilationEnv, context: &'a CFGContext<'a>, cfg: &ImmForwardCFG, _init_state: &mut as SimpleAbsInt>::State, diff --git a/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs b/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs index 7ec26a176398c..ef0c4ab54bfd7 100644 --- a/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs +++ b/external-crates/move/crates/move-compiler/src/sui_mode/typing.rs @@ -8,14 +8,14 @@ use move_symbol_pool::Symbol; use crate::{ diag, - diagnostics::{Diagnostic, WarningFilters}, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, editions::Flavor, expansion::ast::{AbilitySet, Fields, ModuleIdent, Mutability, TargetKind, Visibility}, naming::ast::{ self as N, BuiltinTypeName_, FunctionSignature, StructFields, Type, TypeName_, Type_, Var, }, parser::ast::{Ability_, DatatypeName, FunctionName}, - shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier}, + shared::{program_info::TypingProgramInfo, CompilationEnv, Identifier, WarningFiltersScope}, sui_mode::*, typing::{ ast::{self as T, ModuleCall}, @@ -32,7 +32,7 @@ pub struct SuiTypeChecks; impl TypingVisitorConstructor for SuiTypeChecks { type Context<'a> = Context<'a>; - fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a CompilationEnv, program: &T::Program) -> Self::Context<'a> { Context::new(env, program.info.clone()) } } @@ -43,7 +43,8 @@ impl TypingVisitorConstructor for SuiTypeChecks { #[allow(unused)] pub struct Context<'a> { - env: &'a mut CompilationEnv, + env: &'a CompilationEnv, + warning_filters_scope: WarningFiltersScope, info: Arc, sui_transfer_ident: Option, current_module: Option, @@ -53,14 +54,16 @@ pub struct Context<'a> { } impl<'a> Context<'a> { - fn new(env: &'a mut CompilationEnv, info: Arc) -> Self { + fn new(env: &'a CompilationEnv, info: Arc) -> Self { let sui_module_ident = info .modules .key_cloned_iter() .find(|(m, _)| m.value.is(SUI_ADDR_NAME, TRANSFER_MODULE_NAME)) .map(|(m, _)| m); + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, info, sui_transfer_ident: sui_module_ident, current_module: None, @@ -70,6 +73,15 @@ impl<'a> Context<'a> { } } + fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + fn set_module(&mut self, current_module: ModuleIdent) { self.current_module = Some(current_module); self.otw_name = Some(Symbol::from( @@ -98,12 +110,12 @@ const OTW_NOTE: &str = "One-time witness types are structs with the following re //************************************************************************************************** impl<'a> TypingVisitorContext for Context<'a> { - fn add_warning_filter_scope(&mut self, filter: WarningFilters) { - self.env.add_warning_filter_scope(filter) + fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } fn visit_module_custom(&mut self, ident: ModuleIdent, mdef: &T::ModuleDefinition) -> bool { @@ -205,9 +217,7 @@ fn struct_def(context: &mut Context, name: DatatypeName, sdef: &N::StructDefinit }; if let Some(loc) = invalid_first_field { // no fields or an invalid 'id' field - context - .env - .add_diag(invalid_object_id_field_diag(key_loc, loc, name)); + context.add_diag(invalid_object_id_field_diag(key_loc, loc, name)); return; }; @@ -223,7 +233,7 @@ fn struct_def(context: &mut Context, name: DatatypeName, sdef: &N::StructDefinit ); let mut diag = invalid_object_id_field_diag(key_loc, *id_field_loc, name); diag.add_secondary_label((id_field_type.loc, actual)); - context.env.add_diag(diag); + context.add_diag(diag); } } @@ -261,7 +271,7 @@ fn enum_def(context: &mut Context, name: DatatypeName, edef: &N::EnumDefinition) let msg = format!("Invalid object '{name}'"); let key_msg = format!("Enums cannot have the '{}' ability.", Ability_::Key); let diag = diag!(OBJECT_DECL_DIAG, (name.loc(), msg), (key_loc, key_msg)); - context.env.add_diag(diag); + context.add_diag(diag); }; } @@ -309,17 +319,16 @@ fn init_visibility( entry: Option, ) { match visibility { - Visibility::Public(loc) | Visibility::Friend(loc) | Visibility::Package(loc) => { - context.env.add_diag(diag!( + Visibility::Public(loc) | Visibility::Friend(loc) | Visibility::Package(loc) => context + .add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), (loc, "'init' functions must be internal to their module"), - )) - } + )), Visibility::Internal => (), } if let Some(entry) = entry { - context.env.add_diag(diag!( + context.add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), (entry, "'init' functions cannot be 'entry' functions"), @@ -335,7 +344,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio } = signature; if !type_parameters.is_empty() { let tp_loc = type_parameters[0].user_specified_name.loc; - context.env.add_diag(diag!( + context.add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), (tp_loc, "'init' functions cannot have type parameters"), @@ -346,7 +355,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio "'init' functions must have a return type of {}", error_format_(&Type_::Unit, &Subst::empty()) ); - context.env.add_diag(diag!( + context.add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), (return_type.loc, msg), @@ -368,7 +377,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio m = TX_CONTEXT_MODULE_NAME, t = TX_CONTEXT_TYPE_NAME, ); - context.env.add_diag(diag!( + context.add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), (last_loc, msg), @@ -397,7 +406,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio (otw_loc, otw_msg), ); diag.add_note(OTW_NOTE); - context.env.add_diag(diag) + context.add_diag(diag) } else if parameters.len() > 1 { // if there is more than one parameter, the first must be the OTW let (_, first_var, first_ty) = parameters.first().unwrap(); @@ -421,7 +430,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio (first_ty.loc, msg) ); diag.add_note(OTW_NOTE); - context.env.add_diag(diag) + context.add_diag(diag) } else if let Some(sdef) = info .module(context.current_module()) .structs @@ -439,7 +448,7 @@ fn init_signature(context: &mut Context, name: FunctionName, signature: &Functio if parameters.len() > 2 { // no init function can take more than 2 parameters (the OTW and the TxContext) let (_, third_var, _) = ¶meters[2]; - context.env.add_diag(diag!( + context.add_diag(diag!( INIT_FUN_DIAG, (name.loc(), "Invalid 'init' function declaration"), ( @@ -474,7 +483,7 @@ fn check_otw_type( let mut valid = true; if let Some(tp) = sdef.type_parameters.first() { let msg = "One-time witness types cannot have type parameters"; - context.env.add_diag(otw_diag(diag!( + context.add_diag(otw_diag(diag!( OTW_DECL_DIAG, (name.loc(), "Invalid one-time witness declaration"), (tp.param.user_specified_name.loc, msg), @@ -496,7 +505,7 @@ fn check_otw_type( (loc, format!("Found more than one field. {msg_base}")) } }; - context.env.add_diag(otw_diag(diag!( + context.add_diag(otw_diag(diag!( OTW_DECL_DIAG, (name.loc(), "Invalid one-time witness declaration"), (invalid_loc, invalid_msg), @@ -527,7 +536,7 @@ fn check_otw_type( "One-time witness types can only have the have the '{}' ability", Ability_::Drop ); - context.env.add_diag(otw_diag(diag!( + context.add_diag(otw_diag(diag!( OTW_DECL_DIAG, (name.loc(), "Invalid one-time witness declaration"), (loc, msg), @@ -691,7 +700,7 @@ fn entry_param_ty( .to_owned() }; let emsg = format!("'{name}' was declared 'entry' here"); - context.env.add_diag(diag!( + context.add_diag(diag!( ENTRY_FUN_SIGNATURE_DIAG, (param.loc, pmsg), (param_ty.loc, tmsg), @@ -843,7 +852,7 @@ fn entry_return( Type_::Ref(_, _) => { let fmsg = format!("Invalid return type for entry function '{}'", name); let tmsg = "Expected a non-reference type"; - context.env.add_diag(diag!( + context.add_diag(diag!( ENTRY_FUN_SIGNATURE_DIAG, (entry_loc, fmsg), (*tloc, tmsg) @@ -917,7 +926,7 @@ fn invalid_entry_return_ty<'a>( declared_abilities, ty_args, ); - context.env.add_diag(diag) + context.add_diag(diag) } //************************************************************************************************** @@ -941,7 +950,7 @@ fn exp(context: &mut Context, e: &T::Exp) { consider extracting the logic into a new function and \ calling that instead.", ); - context.env.add_diag(diag) + context.add_diag(diag) } if module.value.is(SUI_ADDR_NAME, EVENT_MODULE_NAME) && name.value() == EVENT_FUNCTION_NAME @@ -965,7 +974,7 @@ fn exp(context: &mut Context, e: &T::Exp) { cannot be created manually, but are passed as an argument 'init'"; let mut diag = diag!(OTW_USAGE_DIAG, (e.exp.loc, msg)); diag.add_note(OTW_NOTE); - context.env.add_diag(diag) + context.add_diag(diag) } } _ => (), @@ -1005,7 +1014,7 @@ fn check_event_emit(context: &mut Context, loc: Loc, mcall: &ModuleCall) { "The type {} is not declared in the current module", error_format(first_ty, &Subst::empty()), ); - context.env.add_diag(diag!( + context.add_diag(diag!( EVENT_EMIT_CALL_DIAG, (loc, msg), (first_ty.loc, ty_msg) @@ -1083,6 +1092,6 @@ fn check_private_transfer(context: &mut Context, loc: Loc, mcall: &ModuleCall) { ); diag.add_secondary_label((store_loc, store_msg)) } - context.env.add_diag(diag) + context.add_diag(diag) } } diff --git a/external-crates/move/crates/move-compiler/src/to_bytecode/context.rs b/external-crates/move/crates/move-compiler/src/to_bytecode/context.rs index 627c30fa3049c..cd99815152253 100644 --- a/external-crates/move/crates/move-compiler/src/to_bytecode/context.rs +++ b/external-crates/move/crates/move-compiler/src/to_bytecode/context.rs @@ -27,7 +27,7 @@ pub type DatatypeDeclarations = /// Compilation context for a single compilation unit (module). /// Contains all of the dependencies actually used in the module pub struct Context<'a> { - pub env: &'a mut CompilationEnv, + pub env: &'a CompilationEnv, current_package: Option, current_module: Option<&'a ModuleIdent>, seen_datatypes: BTreeSet<(ModuleIdent, DatatypeName)>, @@ -36,7 +36,7 @@ pub struct Context<'a> { impl<'a> Context<'a> { pub fn new( - env: &'a mut CompilationEnv, + env: &'a CompilationEnv, current_package: Option, current_module: Option<&'a ModuleIdent>, ) -> Self { diff --git a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs index bb1ba8ab8727b..d024c40bf6b03 100644 --- a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs +++ b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs @@ -38,7 +38,7 @@ type CollectedInfos = UniqueMap; type CollectedInfo = (Vec<(Mutability, Var, H::SingleType)>, Attributes); fn extract_decls( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: &G::Program, ) -> ( @@ -127,7 +127,7 @@ fn extract_decls( //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: G::Program, ) -> Vec { @@ -153,7 +153,7 @@ pub fn program( } fn module( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, ident: ModuleIdent, mdef: G::ModuleDefinition, dependency_orderings: &HashMap, @@ -227,7 +227,7 @@ fn module( match move_ir_to_bytecode::compiler::compile_module(ir_module, deps) { Ok(res) => res, Err(e) => { - compilation_env.add_diag(diag!( + compilation_env.add_error_diag(diag!( Bug::BytecodeGeneration, (ident_loc, format!("IR ERROR: {}", e)) )); diff --git a/external-crates/move/crates/move-compiler/src/typing/ast.rs b/external-crates/move/crates/move-compiler/src/typing/ast.rs index 358372e53f54d..fceb763243b31 100644 --- a/external-crates/move/crates/move-compiler/src/typing/ast.rs +++ b/external-crates/move/crates/move-compiler/src/typing/ast.rs @@ -3,23 +3,19 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - debug_display, diagnostics::WarningFilters, expansion::ast::{ Address, Attributes, Fields, Friend, ModuleIdent, Mutability, TargetKind, Value, Visibility, }, - ice, naming::ast::{ BlockLabel, EnumDefinition, FunctionSignature, Neighbor, StructDefinition, SyntaxMethods, - Type, TypeName_, Type_, UseFuns, Var, + Type, Type_, UseFuns, Var, }, parser::ast::{ BinOp, ConstantName, DatatypeName, Field, FunctionName, UnaryOp, VariantName, ENTRY_MODIFIER, MACRO_MODIFIER, NATIVE_MODIFIER, }, - shared::{ - ast_debug::*, program_info::TypingProgramInfo, unique_map::UniqueMap, CompilationEnv, Name, - }, + shared::{ast_debug::*, program_info::TypingProgramInfo, unique_map::UniqueMap, Name}, }; use move_ir_types::location::*; use move_symbol_pool::Symbol; @@ -361,20 +357,6 @@ pub fn single_item(e: Exp) -> ExpListItem { ExpListItem::Single(e, ty) } -pub fn splat_item(env: &mut CompilationEnv, splat_loc: Loc, e: Exp) -> ExpListItem { - let ss = match &e.ty { - sp!(_, Type_::Unit) => vec![], - sp!(_, Type_::Apply(_, sp!(_, TypeName_::Multiple(_)), ss)) => ss.clone(), - _ => { - let mut diag = ice!((splat_loc, "ICE called `splat_item` on a non-list type")); - diag.add_note(format!("Expression: {}", debug_display!(e))); - env.add_diag(diag); - vec![] - } - }; - ExpListItem::Splat(splat_loc, e, ss) -} - pub fn pat(ty: Type, pat: UnannotatedPat) -> MatchPattern { MatchPattern { ty, pat } } diff --git a/external-crates/move/crates/move-compiler/src/typing/core.rs b/external-crates/move/crates/move-compiler/src/typing/core.rs index 8c99ff9e66074..d0afe06ad536d 100644 --- a/external-crates/move/crates/move-compiler/src/typing/core.rs +++ b/external-crates/move/crates/move-compiler/src/typing/core.rs @@ -6,7 +6,7 @@ use crate::{ debug_display, diag, diagnostics::{ codes::{NameResolution, TypeSafety}, - Diagnostic, + Diagnostic, Diagnostics, WarningFilters, }, editions::FeatureGate, expansion::ast::{AbilitySet, ModuleIdent, ModuleIdent_, Mutability, Visibility}, @@ -91,7 +91,8 @@ pub(super) struct TypingDebugFlags { pub struct Context<'env> { pub modules: NamingProgramInfo, macros: UniqueMap>, - pub env: &'env mut CompilationEnv, + pub env: &'env CompilationEnv, + warning_filters_scope: WarningFiltersScope, pub(super) debug: TypingDebugFlags, deprecations: Deprecations, @@ -179,7 +180,7 @@ impl UseFunsScope { impl<'env> Context<'env> { pub fn new( - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, _pre_compiled_lib: Option>, info: NamingProgramInfo, ) -> Self { @@ -191,6 +192,7 @@ impl<'env> Context<'env> { function_translation: false, type_elaboration: false, }; + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { use_funs: vec![global_use_funs], subst: Subst::empty(), @@ -206,6 +208,7 @@ impl<'env> Context<'env> { macros: UniqueMap::new(), named_block_map: BTreeMap::new(), env, + warning_filters_scope, debug, next_match_var_id: 0, new_friends: BTreeSet::new(), @@ -217,6 +220,31 @@ impl<'env> Context<'env> { } } + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn extend_ide_info(&self, info: IDEInfo) { + self.env.extend_ide_info(&self.warning_filters_scope, info); + } + + pub fn add_ide_annotation(&self, loc: Loc, info: IDEAnnotation) { + self.env + .add_ide_annotation(&self.warning_filters_scope, loc, info); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } + pub fn set_macros( &mut self, macros: UniqueMap>, @@ -266,7 +294,7 @@ impl<'env> Context<'env> { let (target_m, target_f) = &use_fun.target_function; let msg = format!("{case} method alias '{tn}.{method}' for '{target_m}::{target_f}'"); - self.env.add_diag(diag!( + self.add_diag(diag!( Declarations::DuplicateAlias, (use_fun.loc, msg), (prev_loc, "The same alias was previously declared here") @@ -306,18 +334,18 @@ impl<'env> Context<'env> { UseFunKind::Explicit => { let msg = format!("Unused 'use fun' of '{tn}.{method}'. Consider removing it"); - self.env.add_diag(diag!(UnusedItem::Alias, (*loc, msg))) + self.add_diag(diag!(UnusedItem::Alias, (*loc, msg))) } UseFunKind::UseAlias => { let msg = format!("Unused 'use' of alias '{method}'. Consider removing it"); - self.env.add_diag(diag!(UnusedItem::Alias, (*loc, msg))) + self.add_diag(diag!(UnusedItem::Alias, (*loc, msg))) } UseFunKind::FunctionDeclaration => { let diag = ice!(( *loc, "ICE fun declaration 'use' funs should never be added to 'use' funs" )); - self.env.add_diag(diag); + self.add_diag(diag); } } } @@ -411,7 +439,7 @@ impl<'env> Context<'env> { }; diag.add_secondary_label((*prev_loc, msg)); } - self.env.add_diag(diag); + self.add_diag(diag); false } else { self.macro_expansion @@ -433,7 +461,7 @@ impl<'env> Context<'env> { loc, "ICE macro expansion stack should have a call when leaving a macro expansion" )); - self.env.add_diag(diag); + self.add_diag(diag); return false; } }; @@ -471,7 +499,7 @@ impl<'env> Context<'env> { loc, "ICE macro expansion stack should have a lambda when leaving a lambda", )); - self.env.add_diag(diag); + self.add_diag(diag); } } } @@ -507,8 +535,7 @@ impl<'env> Context<'env> { self.lambda_expansion = vec![]; if !self.ide_info.is_empty() { - self.env - .add_diag(ice!((loc, "IDE info should be cleared after each item"))); + self.add_diag(ice!((loc, "IDE info should be cleared after each item"))); self.ide_info = IDEInfo::new(); } } @@ -575,15 +602,14 @@ impl<'env> Context<'env> { pub fn declare_local(&mut self, _: Mutability, var: Var, ty: Type) { if let Err((_, prev_loc)) = self.locals.add(var, ty) { let msg = format!("ICE duplicate {var:?}. Should have been made unique in naming"); - self.env - .add_diag(ice!((var.loc, msg), (prev_loc, "Previously declared here"))); + self.add_diag(ice!((var.loc, msg), (prev_loc, "Previously declared here"))); } } pub fn get_local_type(&mut self, var: &Var) -> Type { if !self.locals.contains_key(var) { let msg = format!("ICE unbound {var:?}. Should have failed in naming"); - self.env.add_diag(ice!((var.loc, msg))); + self.add_diag(ice!((var.loc, msg))); return self.error_type(var.loc); } @@ -659,7 +685,8 @@ impl<'env> Context<'env> { if deprecation.location == AttributePosition::Module && in_same_module { return; } - deprecation.emit_deprecation_warning(self.env, name, method_opt); + let diags = deprecation.deprecation_warnings(name, method_opt); + self.add_diags(diags); } } @@ -847,7 +874,7 @@ impl<'env> Context<'env> { } impl MatchContext for Context<'_> { - fn env(&mut self) -> &mut CompilationEnv { + fn env(&mut self) -> &CompilationEnv { self.env } @@ -1102,7 +1129,7 @@ fn debug_abilities_info(context: &mut Context, ty: &Type) -> (Option, Abili loc, "ICE did not call unfold_type before debug_abiliites_info" )); - context.env.add_diag(diag); + context.add_diag(diag); (None, AbilitySet::all(loc), vec![]) } T::UnresolvedError | T::Anything => (None, AbilitySet::all(loc), vec![]), @@ -1238,7 +1265,7 @@ pub fn make_struct_field_type( N::StructFields::Native(nloc) => { let nloc = *nloc; let msg = format!("Unbound field '{}' for native struct '{}::{}'", field, m, n); - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundField, (loc, msg), (nloc, "Struct declared 'native' here") @@ -1249,7 +1276,7 @@ pub fn make_struct_field_type( }; match fields_map.get(field).cloned() { None => { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundField, (loc, format!("Unbound field '{}' in '{}::{}'", field, m, n)), )); @@ -1364,7 +1391,7 @@ pub fn make_constant_type( let msg = format!("Invalid access of '{}::{}'", m, c); let internal_msg = "Constants are internal to their module, and cannot can be accessed \ outside of their module"; - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::Visibility, (loc, msg), (defined_loc, internal_msg) @@ -1396,7 +1423,7 @@ pub fn make_method_call_type( loc, format!("ICE method on tuple type {}", debug_display!(tn)) )); - context.env.add_diag(diag); + context.add_diag(diag); return None; } TypeName_::Builtin(sp!(_, bt_)) => context.env.primitive_definer(*bt_), @@ -1433,7 +1460,7 @@ pub fn make_method_call_type( No known method '{method}' on type '{lhs_ty_str}'" ); let fmsg = format!("The function '{m}::{method}' exists, {arg_msg}"); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidMethodCall, (loc, msg), (first_ty_loc, fmsg) @@ -1451,7 +1478,7 @@ pub fn make_method_call_type( }; let fmsg = format!("No local 'use fun' alias was found for '{lhs_ty_str}.{method}'{decl_msg}"); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidMethodCall, (loc, msg), (method.loc, fmsg) @@ -1739,7 +1766,7 @@ fn report_visibility_error_( diag.add_secondary_label((call.invocation, "While expanding this macro")); } _ => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( call_loc, "Error when dealing with macro visibilities" ))); @@ -1752,7 +1779,7 @@ fn report_visibility_error_( "Visibility inside of expanded macros is resolved in the scope of the caller.", ); } - context.env.add_diag(diag); + context.add_diag(diag); } pub fn check_call_arity S>( @@ -1777,7 +1804,7 @@ pub fn check_call_arity S>( arity, given_len ); - context.env.add_diag(diag!( + context.add_diag(diag!( code, (loc, cmsg), (argloc, format!("Found {} argument(s) here", given_len)), @@ -1873,7 +1900,7 @@ fn solve_ability_constraint( format!("'{}' constraint declared here", constraint), )); } - context.env.add_diag(diag) + context.add_diag(diag) } } @@ -1973,7 +2000,7 @@ fn solve_builtin_type_constraint( } _ => { let tmsg = mk_tmsg(); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::BuiltinOperation, (loc, format!("Invalid argument to '{}'", op)), (tloc, tmsg) @@ -1991,7 +2018,7 @@ fn solve_base_type_constraint(context: &mut Context, loc: Loc, msg: String, ty: Unit | Ref(_, _) | Apply(_, sp!(_, Multiple(_)), _) => { let tystr = error_format(ty, &context.subst); let tmsg = format!("Expected a single non-reference type, but found: {}", tystr); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::ExpectedBaseType, (loc, msg), (tyloc, tmsg) @@ -2012,7 +2039,7 @@ fn solve_single_type_constraint(context: &mut Context, loc: Loc, msg: String, ty "Expected a single type, but found expression list type: {}", error_format(ty, &context.subst) ); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::ExpectedSingleType, (loc, msg), (tyloc, tmsg) @@ -2363,7 +2390,7 @@ fn check_type_argument_arity String>( arity, args_len ); - context.env.add_diag(diag!(code, (loc, msg))); + context.add_diag(diag!(code, (loc, msg))); } while ty_args.len() > arity { diff --git a/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs b/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs index f32f7ee2d8600..0db5e1b0f4a2b 100644 --- a/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs +++ b/external-crates/move/crates/move-compiler/src/typing/dependency_ordering.rs @@ -20,7 +20,7 @@ use std::collections::{BTreeMap, BTreeSet}; //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, modules: &mut UniqueMap, ) { let imm_modules = &modules; @@ -38,7 +38,7 @@ pub fn program( Err(cycle_node) => { let cycle_ident = *cycle_node.node_id(); let error = cycle_error(&module_neighbors, cycle_ident); - compilation_env.add_diag(error); + compilation_env.add_error_diag(error); } Ok(ordered_ids) => { for (order, mident) in ordered_ids.iter().rev().enumerate() { @@ -63,7 +63,7 @@ enum DepType { } struct Context<'a, 'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, modules: &'a UniqueMap, // A union of uses and friends for modules (used for cyclyc dependency checking) // - if A uses B, add edge A -> B @@ -79,7 +79,7 @@ struct Context<'a, 'env> { impl<'a, 'env> Context<'a, 'env> { fn new( - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, modules: &'a UniqueMap, ) -> Self { Context { @@ -372,7 +372,7 @@ fn lvalue(context: &mut Context, sp!(loc, lv_): &T::LValue) { } } L::BorrowUnpackVariant(..) | L::UnpackVariant(..) => { - context.env.add_diag(ice!(( + context.env.add_error_diag(ice!(( *loc, "variant unpacking shouldn't occur before match expansion" ))); @@ -420,7 +420,7 @@ fn exp(context: &mut Context, e: &T::Exp) { } } E::VariantMatch(..) => { - context.env.add_diag(ice!(( + context.env.add_error_diag(ice!(( e.exp.loc, "shouldn't find variant match before HLIR lowering" ))); diff --git a/external-crates/move/crates/move-compiler/src/typing/deprecation_warnings.rs b/external-crates/move/crates/move-compiler/src/typing/deprecation_warnings.rs index 9ba6765d66dc3..e4df3a5fe4aec 100644 --- a/external-crates/move/crates/move-compiler/src/typing/deprecation_warnings.rs +++ b/external-crates/move/crates/move-compiler/src/typing/deprecation_warnings.rs @@ -3,6 +3,7 @@ use crate::{ diag, + diagnostics::Diagnostics, expansion::ast::{self as E, ModuleIdent}, ice, shared::{ @@ -43,7 +44,7 @@ pub struct Deprecations { impl Deprecations { /// Index the modules and their members for deprecation attributes and register each /// deprecation attribute for use later on. - pub fn new(env: &mut CompilationEnv, info: &NamingProgramInfo) -> Self { + pub fn new(env: &CompilationEnv, info: &NamingProgramInfo) -> Self { let mut deprecated_members = HashMap::new(); for (mident, module_info) in info.modules.key_cloned_iter() { @@ -120,12 +121,7 @@ impl Deprecations { impl Deprecation { /// Emit a warning for the deprecation of a module member. - pub fn emit_deprecation_warning( - &self, - env: &mut CompilationEnv, - member_name: Name, - method_opt: Option, - ) { + pub fn deprecation_warnings(&self, member_name: Name, method_opt: Option) -> Diagnostics { let mident_string = self.module_ident.to_string(); let location_string = match (self.location, method_opt) { (AttributePosition::Module, None) => { @@ -159,7 +155,10 @@ impl Deprecation { let location = method_opt.map_or(member_name.loc, |method| method.loc); - env.add_diag(diag!(TypeSafety::DeprecatedUsage, (location, message))); + Diagnostics::from(vec![diag!( + TypeSafety::DeprecatedUsage, + (location, message) + )]) } } @@ -168,7 +167,7 @@ impl Deprecation { // #[deprecated] attributes (malformed, or multiple on the member), add an error diagnostic to // `env` and return None. fn deprecations( - env: &mut CompilationEnv, + env: &CompilationEnv, attr_position: AttributePosition, attrs: &E::Attributes, source_location: Loc, @@ -184,7 +183,7 @@ fn deprecations( } if deprecations.len() != 1 { - env.add_diag(ice!(( + env.add_error_diag(ice!(( source_location, "ICE: verified that there is at at least one deprecation attribute above, \ and expansion should have failed if there were multiple deprecation attributes." @@ -196,7 +195,7 @@ fn deprecations( .last() .expect("Verified deprecations is not empty above"); - let mut make_invalid_deprecation_diag = || { + let make_invalid_deprecation_diag = || { let mut diag = diag!( Attributes::InvalidUsage, ( @@ -209,7 +208,7 @@ fn deprecations( DeprecationAttribute.name() ); diag.add_note(note); - env.add_diag(diag); + env.add_error_diag(diag); None }; diff --git a/external-crates/move/crates/move-compiler/src/typing/expand.rs b/external-crates/move/crates/move-compiler/src/typing/expand.rs index 150756a5fa786..bae757038b6c7 100644 --- a/external-crates/move/crates/move-compiler/src/typing/expand.rs +++ b/external-crates/move/crates/move-compiler/src/typing/expand.rs @@ -69,14 +69,14 @@ pub fn type_(context: &mut Context, ty: &mut Type) { ty.loc, "ICE unfold_type_base failed to expand type inf. var" )); - context.env.add_diag(diag); + context.env.add_error_diag(diag); sp(loc, UnresolvedError) } sp!(loc, Anything) => { let msg = "Could not infer this type. Try adding an annotation"; context .env - .add_diag(diag!(TypeSafety::UninferredType, (ty.loc, msg))); + .add_error_diag(diag!(TypeSafety::UninferredType, (ty.loc, msg))); sp(loc, UnresolvedError) } sp!(loc, Fun(_, _)) if !context.in_macro_function => { @@ -96,7 +96,7 @@ pub fn type_(context: &mut Context, ty: &mut Type) { ty.loc, format!("ICE expanding pre-expanded type {}", debug_display!(aty)) )); - context.env.add_diag(diag); + context.env.add_error_diag(diag); *ty = sp(ty.loc, UnresolvedError) } Apply(None, _, _) => { @@ -108,7 +108,7 @@ pub fn type_(context: &mut Context, ty: &mut Type) { } _ => { let diag = ice!((ty.loc, "ICE type-apply switched to non-apply")); - context.env.add_diag(diag); + context.env.add_error_diag(diag); *ty = sp(ty.loc, UnresolvedError) } } @@ -134,7 +134,7 @@ fn unexpected_lambda_type(context: &mut Context, loc: Loc) { Lambdas can only be used with 'macro' functions, as parameters or direct arguments"; context .env - .add_diag(diag!(TypeSafety::UnexpectedFunctionType, (loc, msg))); + .add_error_diag(diag!(TypeSafety::UnexpectedFunctionType, (loc, msg))); } } @@ -248,7 +248,7 @@ pub fn exp(context: &mut Context, e: &mut T::Exp) { } } E::VariantMatch(subject, _, arms) => { - context.env.add_diag(ice!(( + context.env.add_error_diag(ice!(( e.exp.loc, "shouldn't find variant match before match compilation" ))); @@ -357,7 +357,7 @@ fn inferred_numerical_value( "Annotating the literal might help inference: '{value}{type}'", type=fix_bt, ); - context.env.add_diag(diag!( + context.env.add_error_diag(diag!( TypeSafety::InvalidNum, (eloc, "Invalid numerical literal"), (ty.loc, msg), diff --git a/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs b/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs index 431faa117b18b..0e9745d4b4f1f 100644 --- a/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs +++ b/external-crates/move/crates/move-compiler/src/typing/infinite_instantiations.rs @@ -140,7 +140,7 @@ impl<'a> Context<'a> { //************************************************************************************************** pub fn modules( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, modules: &UniqueMap, ) { let tparams = modules @@ -171,7 +171,7 @@ macro_rules! scc_edges { } fn module<'a>( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, tparams: &'a BTreeMap>>, mname: ModuleIdent, module: &T::ModuleDefinition, @@ -188,7 +188,7 @@ fn module<'a>( petgraph_scc(&graph) .into_iter() .filter(|scc| scc_edges!(&graph, scc).any(|(_, e, _)| e == Edge::Nested)) - .for_each(|scc| compilation_env.add_diag(cycle_error(context, &graph, scc))) + .for_each(|scc| compilation_env.add_error_diag(cycle_error(context, &graph, scc))) } //************************************************************************************************** diff --git a/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs b/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs index 8e050eeed924f..58fb3c512d551 100644 --- a/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs +++ b/external-crates/move/crates/move-compiler/src/typing/macro_expand.rs @@ -64,7 +64,7 @@ pub(crate) fn call( let reloc_clever_errors = match &context.macro_expansion[0] { core::MacroExpansion::Call(call) => call.invocation, core::MacroExpansion::Argument { .. } => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( call_loc, "ICE top level macro scope should never be an argument" ))); @@ -92,7 +92,7 @@ pub(crate) fn call( return None; } Err(Some(diag)) => { - context.env.add_diag(*diag); + context.add_diag(*diag); return None; } }; @@ -288,9 +288,7 @@ fn bind_lambda( "Unable to bind lambda to parameter '{}'. The lambda must be passed directly", param.name ); - context - .env - .add_diag(diag!(TypeSafety::CannotExpandMacro, (arg.loc, msg))); + context.add_diag(diag!(TypeSafety::CannotExpandMacro, (arg.loc, msg))); None } } @@ -747,9 +745,7 @@ fn report_unused_argument(context: &mut core::Context, loc: EvalStrategy { context.mark_used(v_); let (arg, _expected_ty) = context.by_name_args.get(v_).unwrap(); - context.core.env.add_diag(diag!( + context.core.add_diag(diag!( TypeSafety::CannotExpandMacro, (*eloc, "Cannot call non-lambda argument"), (arg.loc, "Expected a lambda argument") diff --git a/external-crates/move/crates/move-compiler/src/typing/match_analysis.rs b/external-crates/move/crates/move-compiler/src/typing/match_analysis.rs index 5c3fcc78e31d1..95635d8839c86 100644 --- a/external-crates/move/crates/move-compiler/src/typing/match_analysis.rs +++ b/external-crates/move/crates/move-compiler/src/typing/match_analysis.rs @@ -70,12 +70,12 @@ impl TypingMutVisitorContext for MatchCompiler<'_, '_> { } } - fn add_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { - self.context.env.add_warning_filter_scope(filter); + fn push_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { + self.context.push_warning_filter_scope(filter); } fn pop_warning_filter_scope(&mut self) { - self.context.env.pop_warning_filter_scope(); + self.context.pop_warning_filter_scope(); } } @@ -564,7 +564,7 @@ fn find_counterexample_impl( } else { // An error case: no entry on the fringe but no if !context.env.has_errors() { - context.env.add_diag(ice!(( + context.add_diag(ice!(( matrix.loc, "Non-empty matrix with non errors but no type" ))); @@ -593,7 +593,7 @@ fn find_counterexample_impl( if has_guards { diag.add_note("Match arms with guards are not considered for coverage."); } - context.env.add_diag(diag); + context.add_diag(diag); true } else { false @@ -622,9 +622,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr if !unused.is_empty() { let arms = unused.into_iter().map(PS::Value).collect::>(); let info = MissingMatchArmsInfo { arms }; - context - .env - .add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); } } @@ -635,9 +633,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr let info = MissingMatchArmsInfo { arms: vec![PS::Wildcard], }; - context - .env - .add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); } } @@ -657,7 +653,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr // If the matrix _is_ empty, we suggest adding an unpack. let is_positional = context.modules.struct_is_positional(&mident, &name); let Some(fields) = context.modules.struct_fields(&mident, &name) else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Tried to look up fields for this struct and found none" ))); @@ -684,9 +680,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr let info = MissingMatchArmsInfo { arms: vec![suggestion], }; - context - .env - .add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); } else { // If there's a default arm, no suggestion is necessary. if matrix.has_default_arm() { @@ -722,7 +716,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr .modules .enum_variant_fields(&mident, &name, &variant) else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Tried to look up fields for this enum and found none" ))); @@ -752,14 +746,12 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr arms.push(suggestion); } let info = MissingMatchArmsInfo { arms }; - context - .env - .add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); } } let Some(ty) = matrix.tys.first() else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Pattern matrix with no types handed to IDE function" ))); @@ -778,7 +770,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr } else { if !context.env.has_errors() { // It's unclear how we got here, so report an ICE and suggest a wildcard. - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, format!( "Found non-matchable type {} as match subject", @@ -790,9 +782,7 @@ fn ide_report_missing_arms(context: &mut Context, loc: Loc, matrix: &PatternMatr let info = MissingMatchArmsInfo { arms: vec![PS::Wildcard], }; - context - .env - .add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); + context.add_ide_annotation(loc, IDEAnnotation::MissingMatchArms(Box::new(info))); } } } diff --git a/external-crates/move/crates/move-compiler/src/typing/match_compilation.rs b/external-crates/move/crates/move-compiler/src/typing/match_compilation.rs index 347376fe9eda9..bb80f3f350b3f 100644 --- a/external-crates/move/crates/move-compiler/src/typing/match_compilation.rs +++ b/external-crates/move/crates/move-compiler/src/typing/match_compilation.rs @@ -61,8 +61,8 @@ impl TypingVisitorContext for MatchCompiler<'_, '_> { } } - fn add_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { - self.context.env.add_warning_filter_scope(filter); + fn push_warning_filter_scope(&mut self, filter: crate::diagnostics::WarningFilters) { + self.context.env.push_warning_filter_scope(filter); } fn pop_warning_filter_scope(&mut self) { diff --git a/external-crates/move/crates/move-compiler/src/typing/recursive_datatypes.rs b/external-crates/move/crates/move-compiler/src/typing/recursive_datatypes.rs index 58a9053120255..11f053a366236 100644 --- a/external-crates/move/crates/move-compiler/src/typing/recursive_datatypes.rs +++ b/external-crates/move/crates/move-compiler/src/typing/recursive_datatypes.rs @@ -54,7 +54,7 @@ impl Context { //************************************************************************************************** pub fn modules( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, modules: &UniqueMap, ) { modules @@ -62,7 +62,7 @@ pub fn modules( .for_each(|(mname, m)| module(compilation_env, mname, m)) } -fn module(compilation_env: &mut CompilationEnv, mname: ModuleIdent, module: &T::ModuleDefinition) { +fn module(compilation_env: &CompilationEnv, mname: ModuleIdent, module: &T::ModuleDefinition) { let context = &mut Context::new(mname); module .structs @@ -79,7 +79,7 @@ fn module(compilation_env: &mut CompilationEnv, mname: ModuleIdent, module: &T:: petgraph_scc(&graph) .into_iter() .filter(|scc| scc.len() > 1 || graph.contains_edge(scc[0], scc[0])) - .for_each(|scc| compilation_env.add_diag(cycle_error(context, &graph, scc[0]))) + .for_each(|scc| compilation_env.add_error_diag(cycle_error(context, &graph, scc[0]))) } fn struct_def(context: &mut Context, sname: DatatypeName, sdef: &N::StructDefinition) { diff --git a/external-crates/move/crates/move-compiler/src/typing/syntax_methods.rs b/external-crates/move/crates/move-compiler/src/typing/syntax_methods.rs index d1ba995249756..6e8b839c068de 100644 --- a/external-crates/move/crates/move-compiler/src/typing/syntax_methods.rs +++ b/external-crates/move/crates/move-compiler/src/typing/syntax_methods.rs @@ -73,7 +73,7 @@ fn validate_index_syntax_methods( diag.add_note( "Index operations on the same type must take the name number of type arguments", ); - context.env.add_diag(diag); + context.add_diag(diag); return false; } @@ -92,7 +92,7 @@ fn validate_index_syntax_methods( (index_mut.loc, index_mut_msg), ); diag.add_note("Index operations on the same type must take the name number of parameters"); - context.env.add_diag(diag); + context.add_diag(diag); return false; } @@ -121,7 +121,7 @@ fn validate_index_syntax_methods( diag.add_note( "Index operations on use the same abilities for their type parameters", ); - context.env.add_diag(diag); + context.add_diag(diag); valid = false; } } @@ -142,7 +142,7 @@ fn validate_index_syntax_methods( diag.add_note( "Index operations on use the same abilities for their type parameters", ); - context.env.add_diag(diag); + context.add_diag(diag); valid = false; } } @@ -200,7 +200,7 @@ fn validate_index_syntax_methods( let N::Type_::Ref(false, inner) = core::ready_tvars(&subst, subject_ref_type.clone()).value else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( index_finfo.signature.return_type.loc, "This index function got to type verification with an invalid type" ))); @@ -228,7 +228,7 @@ fn validate_index_syntax_methods( diag.add_note( "These functions must take the same subject type, differing only by mutability", ); - context.env.add_diag(diag); + context.add_diag(diag); valid = false; } } else { @@ -262,7 +262,7 @@ fn validate_index_syntax_methods( &mut_finfo.signature.type_parameters, ); diag.add_note("Index operation non-subject parameter types must match exactly"); - context.env.add_diag(diag); + context.add_diag(diag); valid = false; } } @@ -282,7 +282,7 @@ fn validate_index_syntax_methods( let index_msg = format!("This index function returns type {}", ty_str(index_type)); let N::Type_::Ref(false, inner) = core::ready_tvars(&subst, index_ty.return_.clone()).value else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( index_finfo.signature.return_type.loc, "This index function got to type verification with an invalid type" ))); @@ -308,7 +308,7 @@ fn validate_index_syntax_methods( &mut_finfo.signature.type_parameters, ); diag.add_note("These functions must return the same type, differing only by mutability"); - context.env.add_diag(diag); + context.add_diag(diag); valid = false; } diff --git a/external-crates/move/crates/move-compiler/src/typing/translate.rs b/external-crates/move/crates/move-compiler/src/typing/translate.rs index fd5c3cd6167d0..ba75d91516ec4 100644 --- a/external-crates/move/crates/move-compiler/src/typing/translate.rs +++ b/external-crates/move/crates/move-compiler/src/typing/translate.rs @@ -53,7 +53,7 @@ use std::{ //************************************************************************************************** pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: N::Program, ) -> T::Program { @@ -226,7 +226,7 @@ fn module( } = mdef; context.current_module = Some(ident); context.current_package = package_name; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); context.add_use_funs_scope(use_funs); structs .iter_mut() @@ -238,7 +238,7 @@ fn module( assert!(context.constraints.is_empty()); context.current_package = None; let use_funs = context.pop_use_funs_scope(); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); let typed_module = T::ModuleDefinition { loc, warning_filter, @@ -270,7 +270,7 @@ fn finalize_ide_info(context: &mut Context) { for (_loc, ann) in info.iter_mut() { expand::ide_annotation(context, ann); } - context.env.extend_ide_info(info); + context.extend_ide_info(info); } //************************************************************************************************** @@ -289,7 +289,7 @@ fn function(context: &mut Context, name: FunctionName, f: N::Function) -> T::Fun mut signature, body: n_body, } = f; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); assert!(context.constraints.is_empty()); context.reset_for_module_item(name.loc()); context.current_function = Some(name); @@ -310,7 +310,7 @@ fn function(context: &mut Context, name: FunctionName, f: N::Function) -> T::Fun finalize_ide_info(context); context.current_function = None; context.in_macro_function = false; - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); T::Function { warning_filter, index, @@ -394,7 +394,7 @@ fn constant(context: &mut Context, name: ConstantName, nconstant: N::Constant) - signature, value: nvalue, } = nconstant; - context.env.add_warning_filter_scope(warning_filter.clone()); + context.push_warning_filter_scope(warning_filter.clone()); process_attributes(context, &attributes); @@ -426,7 +426,7 @@ fn constant(context: &mut Context, name: ConstantName, nconstant: N::Constant) - if context.env.ide_mode() { finalize_ide_info(context); } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); T::Constant { warning_filter, @@ -503,9 +503,7 @@ mod check_valid_constant { core::error_format(ty, &Subst::empty()), format_comma(tys), ); - context - .env - .add_diag(diag!(code, (sloc, fmsg()), (loc, tmsg))) + context.add_diag(diag!(code, (sloc, fmsg()), (loc, tmsg))) } pub fn exp(context: &mut Context, e: &T::Exp) { @@ -591,7 +589,7 @@ mod check_valid_constant { "'match' expressions are" } E::VariantMatch(_subject, _, _arms) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( *loc, "shouldn't find variant match before match compilation" ))); @@ -644,7 +642,7 @@ mod check_valid_constant { "Enum variants are" } }; - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::UnsupportedConstant, (*loc, format!("{} not supported in constants", error_case)) )); @@ -691,9 +689,7 @@ mod check_valid_constant { } }; let msg = format!("{} are not supported in constants", error_case); - context - .env - .add_diag(diag!(TypeSafety::UnsupportedConstant, (*loc, msg),)) + context.add_diag(diag!(TypeSafety::UnsupportedConstant, (*loc, msg),)) } } @@ -704,9 +700,7 @@ mod check_valid_constant { fn struct_def(context: &mut Context, sloc: Loc, s: &mut N::StructDefinition) { assert!(context.constraints.is_empty()); context.reset_for_module_item(sloc); - context - .env - .add_warning_filter_scope(s.warning_filter.clone()); + context.push_warning_filter_scope(s.warning_filter.clone()); let field_map = match &mut s.fields { N::StructFields::Native(_) => return, @@ -749,15 +743,13 @@ fn struct_def(context: &mut Context, sloc: Loc, s: &mut N::StructDefinition) { expand::type_(context, &mut idx_ty.1); } check_type_params_usage(context, &s.type_parameters, field_map); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } fn enum_def(context: &mut Context, enum_: &mut N::EnumDefinition) { assert!(context.constraints.is_empty()); - context - .env - .add_warning_filter_scope(enum_.warning_filter.clone()); + context.push_warning_filter_scope(enum_.warning_filter.clone()); let enum_abilities = &enum_.abilities; let enum_type_params = &enum_.type_parameters; @@ -770,7 +762,7 @@ fn enum_def(context: &mut Context, enum_: &mut N::EnumDefinition) { } check_variant_type_params_usage(context, enum_type_params, field_types); - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } fn variant_def( @@ -1031,7 +1023,7 @@ fn invalid_phantom_use_error( } }; let decl_msg = format!("'{}' declared here as phantom", ¶m.user_specified_name); - context.env.add_diag(diag!( + context.add_diag(diag!( Declarations::InvalidPhantomUse, (ty_loc, msg), (param.user_specified_name.loc, decl_msg), @@ -1050,9 +1042,7 @@ fn check_non_phantom_param_usage( "Unused type parameter '{}'. Consider declaring it as phantom", name ); - context - .env - .add_diag(diag!(UnusedItem::StructTypeParam, (name.loc, msg))) + context.add_diag(diag!(UnusedItem::StructTypeParam, (name.loc, msg))) } Some(false) => { let msg = format!( @@ -1060,9 +1050,7 @@ fn check_non_phantom_param_usage( adding a phantom declaration here", name ); - context - .env - .add_diag(diag!(Declarations::InvalidNonPhantomUse, (name.loc, msg))) + context.add_diag(diag!(Declarations::InvalidNonPhantomUse, (name.loc, msg))) } Some(true) => {} } @@ -1248,7 +1236,7 @@ fn subtype_impl T>( Err(e) => { context.subst = subst; let diag = typing_error(context, /* from_subtype */ true, loc, msg, e); - context.env.add_diag(diag); + context.add_diag(diag); Err(rhs) } Ok((next_subst, ty)) => { @@ -1298,7 +1286,7 @@ fn join_opt T>( Err(e) => { context.subst = subst; let diag = typing_error(context, /* from_subtype */ false, loc, msg, e); - context.env.add_diag(diag); + context.add_diag(diag); None } Ok((next_subst, ty)) => { @@ -1350,7 +1338,7 @@ fn invariant_impl T>( Err(e) => { context.subst = subst; let diag = typing_error(context, /* from_subtype */ false, loc, msg, e); - context.env.add_diag(diag); + context.add_diag(diag); Err(rhs) } Ok((next_subst, ty)) => { @@ -1681,9 +1669,7 @@ fn exp(context: &mut Context, ne: Box) -> Box { .check_feature(context.current_package, FeatureGate::Lambda, eloc) { let msg = "Lambdas can only be used directly as arguments to 'macro' functions"; - context - .env - .add_diag(diag!(TypeSafety::UnexpectedLambda, (eloc, msg))) + context.add_diag(diag!(TypeSafety::UnexpectedLambda, (eloc, msg))) } (context.error_type(eloc), TE::UnresolvedError) } @@ -2043,9 +2029,7 @@ fn binop( } Range | Implies | Iff => { - context - .env - .add_diag(ice!((loc, "ICE unexpect specification operator"))); + context.add_diag(ice!((loc, "ICE unexpect specification operator"))); (context.error_type(loc), context.error_type(loc)) } }; @@ -2323,9 +2307,7 @@ fn match_pattern_( matched in the module in which they are declared", &m, &struct_, ); - context - .env - .add_diag(diag!(TypeSafety::Visibility, (loc, msg))); + context.add_diag(diag!(TypeSafety::Visibility, (loc, msg))); } let bt = rtype!(bt); let pat_ = if field_error { @@ -2808,7 +2790,7 @@ fn resolve_field(context: &mut Context, loc: Loc, ty: Type, field: &Field) -> Ty match core::ready_tvars(&context.subst, ty) { sp!(_, UnresolvedError) => context.error_type(loc), sp!(tloc, Anything) => { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::UninferredType, (loc, msg()), (tloc, UNINFERRED_MSG), @@ -2816,7 +2798,7 @@ fn resolve_field(context: &mut Context, loc: Loc, ty: Type, field: &Field) -> Ty context.error_type(loc) } sp!(tloc, Var(i)) if !context.subst.is_num_var(i) => { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::UninferredType, (loc, msg()), (tloc, UNINFERRED_MSG), @@ -2829,9 +2811,7 @@ fn resolve_field(context: &mut Context, loc: Loc, ty: Type, field: &Field) -> Ty "Invalid access of field '{field}' on the struct '{m}::{n}'. The field '{field}' can only \ be accessed within the module '{m}' since it defines '{n}'" ); - context - .env - .add_diag(diag!(TypeSafety::Visibility, (loc, msg))); + context.add_diag(diag!(TypeSafety::Visibility, (loc, msg))); } match context.datatype_kind(&m, &n) { DatatypeKind::Struct => { @@ -2843,9 +2823,7 @@ fn resolve_field(context: &mut Context, loc: Loc, ty: Type, field: &Field) -> Ty structs, not enums", field, &m, &n ); - context - .env - .add_diag(diag!(TypeSafety::ExpectedSpecificType, (loc, msg))); + context.add_diag(diag!(TypeSafety::ExpectedSpecificType, (loc, msg))); context.error_type(loc) } } @@ -2855,7 +2833,7 @@ fn resolve_field(context: &mut Context, loc: Loc, ty: Type, field: &Field) -> Ty "Expected a struct type in the current module but got: {}", core::error_format(&t, &context.subst) ); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::ExpectedSpecificType, (loc, msg()), (t.loc, smsg), @@ -2883,7 +2861,7 @@ fn add_struct_field_types( constructed/deconstructed, and their fields cannot be dirctly accessed", verb, m, n ); - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidNativeUsage, (loc, msg), (nloc, "Struct declared 'native' here") @@ -2894,15 +2872,13 @@ fn add_struct_field_types( for (_, f_, _) in &fields_ty { if fields.get_(f_).is_none() { let msg = format!("Missing {} for field '{}' in '{}::{}'", verb, f_, m, n); - context - .env - .add_diag(diag!(TypeSafety::TooFewArguments, (loc, msg))) + context.add_diag(diag!(TypeSafety::TooFewArguments, (loc, msg))) } } fields.map(|f, (idx, x)| { let fty = match fields_ty.remove(&f) { None => { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundField, (loc, format!("Unbound field '{}' in '{}::{}'", &f, m, n)) )); @@ -2947,15 +2923,13 @@ fn add_variant_field_types( "Missing {} for field '{}' in '{}::{}::{}'", verb, f_, m, n, v ); - context - .env - .add_diag(diag!(TypeSafety::TooFewArguments, (loc, msg))) + context.add_diag(diag!(TypeSafety::TooFewArguments, (loc, msg))) } } fields.map(|f, (idx, x)| { let fty = match fields_ty.remove(&f) { None => { - context.env.add_diag(diag!( + context.add_diag(diag!( NameResolution::UnboundField, ( loc, @@ -2992,7 +2966,7 @@ fn find_index_funs(context: &mut Context, loc: Loc, ty: &Type) -> Option None, sp!(tloc, T::Anything) => { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::UninferredType, (loc, msg()), (*tloc, UNINFERRED_MSG), @@ -3000,7 +2974,7 @@ fn find_index_funs(context: &mut Context, loc: Loc, ty: &Type) -> Option { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::UninferredType, (loc, msg()), (*tloc, UNINFERRED_MSG), @@ -3010,9 +2984,7 @@ fn find_index_funs(context: &mut Context, loc: Loc, ty: &Type) -> Option { let index_opt = core::find_index_funs(context, type_name); if index_opt.is_none() { - context - .env - .add_diag(diag!(Declarations::MissingSyntaxMethod, (loc, msg()),)); + context.add_diag(diag!(Declarations::MissingSyntaxMethod, (loc, msg()),)); } index_opt } @@ -3021,7 +2993,7 @@ fn find_index_funs(context: &mut Context, loc: Loc, ty: &Type) -> Option *base, ty @ sp!(_, Type_::UnresolvedError) => ty, _ => { - context - .env - .add_diag(ice!((dloc, "Index should have failed in naming"))); + context.add_diag(ice!((dloc, "Index should have failed in naming"))); sp(dloc, Type_::UnresolvedError) } }; @@ -3242,9 +3210,7 @@ fn process_exp_dotted( inner } N::ExpDotted_::DotAutocomplete(_loc, ndot) => { - context - .env - .add_diag(ice!((dloc, "Found a dot autocomplete where unsupported"))); + context.add_diag(ice!((dloc, "Found a dot autocomplete where unsupported"))); // Keep going after the ICE. process_exp_dotted_inner(context, constraint_verb, *ndot) } @@ -3342,7 +3308,7 @@ fn resolve_exp_dotted( }, ), TE::Constant(_, _) if edotted.accessors.is_empty() => { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidMoveOp, (loc, "Invalid 'move'. Cannot 'move' constants") )); @@ -3350,7 +3316,7 @@ fn resolve_exp_dotted( } TE::UnresolvedError => make_exp(edotted.base.ty, TE::UnresolvedError), _ if edotted.accessors.is_empty() => { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidMoveOp, (loc, "Invalid 'move'. Expected a variable or path.") )); @@ -3366,9 +3332,7 @@ fn resolve_exp_dotted( borrow_exp_dotted(context, error_loc, false, edotted); let msg = "Invalid 'move'. 'move' works only with \ variables, e.g. 'move x'. 'move' on a path access is not supported"; - context - .env - .add_diag(diag!(TypeSafety::InvalidMoveOp, (loc, msg))); + context.add_diag(diag!(TypeSafety::InvalidMoveOp, (loc, msg))); make_error(context) } else { make_error(context) @@ -3397,9 +3361,7 @@ fn resolve_exp_dotted( TE::UnresolvedError => make_exp(edotted.base.ty, TE::UnresolvedError), _ => { let msg = "Invalid 'copy'. Expected a variable or path.".to_owned(); - context - .env - .add_diag(diag!(TypeSafety::InvalidCopyOp, (loc, msg))); + context.add_diag(diag!(TypeSafety::InvalidCopyOp, (loc, msg))); make_error(context) } } @@ -3484,7 +3446,7 @@ fn borrow_exp_dotted( }; // lhs is immutable and current borrow is mutable if !cur_mut && expected_mut { - context.env.add_diag(diag!( + context.add_diag(diag!( ReferenceSafety::RefTrans, (loc, "Invalid mutable borrow from an immutable reference"), (tyloc, "Immutable because of this position"), @@ -3550,7 +3512,6 @@ fn borrow_exp_dotted( } else { let msg = "Could not find a mutable index 'syntax' method"; context - .env .add_diag(diag!(Declarations::MissingSyntaxMethod, (index_loc, msg),)); exp = make_error_exp(context, index_loc); break; @@ -3559,9 +3520,7 @@ fn borrow_exp_dotted( index.target_function } else { let msg = "Could not find an immutable index 'syntax' method"; - context - .env - .add_diag(diag!(Declarations::MissingSyntaxMethod, (index_loc, msg),)); + context.add_diag(diag!(Declarations::MissingSyntaxMethod, (index_loc, msg),)); exp = make_error_exp(context, index_loc); break; }; @@ -3577,7 +3536,7 @@ fn borrow_exp_dotted( core::error_format(&ret_ty, &context.subst), core::error_format(&mut_type, &context.subst) ); - context.env.add_diag(ice!((loc, msg))); + context.add_diag(ice!((loc, msg))); exp = make_error_exp(context, index_loc); break; } @@ -3619,7 +3578,7 @@ fn exp_dotted_to_owned( } } } else { - context.env.add_diag(ice!(( + context.add_diag(ice!(( ed.loc, "Attempted to make a dotted path with no dots" ))); @@ -3627,15 +3586,11 @@ fn exp_dotted_to_owned( }; let case = match usage { DottedUsage::Move(_) => { - context - .env - .add_diag(ice!((ed.loc, "Invalid dotted usage 'move' in to_owned"))); + context.add_diag(ice!((ed.loc, "Invalid dotted usage 'move' in to_owned"))); return make_error_exp(context, ed.loc); } DottedUsage::Borrow(_) => { - context - .env - .add_diag(ice!((ed.loc, "Invalid dotted usage 'borrow' in to_owned"))); + context.add_diag(ice!((ed.loc, "Invalid dotted usage 'borrow' in to_owned"))); return make_error_exp(context, ed.loc); } DottedUsage::Use => "implicit copy", @@ -3726,9 +3681,7 @@ fn warn_on_constant_borrow(context: &mut Context, loc: Loc, e: &T::Exp) { if matches!(&e.exp.value, TE::Constant(_, _)) { let msg = "This access will make a new copy of the constant. \ Consider binding the value to a variable first to make this copy explicit"; - context - .env - .add_diag(diag!(TypeSafety::ImplicitConstantCopy, (loc, msg))) + context.add_diag(diag!(TypeSafety::ImplicitConstantCopy, (loc, msg))) } } @@ -3875,7 +3828,7 @@ fn type_to_type_name_( return None; } Ty::Ref(_, _) | Ty::Var(_) => { - context.env.add_diag(ice!(( + context.add_diag(ice!(( loc, "Typing did not unfold type before resolving type name" ))); @@ -3884,7 +3837,7 @@ fn type_to_type_name_( Ty::Apply(_, _, _) => unreachable!(), }; if report_error { - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidMethodCall, (loc, format!("Invalid {error_msg}")), (ty.loc, msg), @@ -4022,7 +3975,7 @@ fn annotated_error_const(context: &mut Context, e: &mut T::Exp, abort_or_assert_ the '#[error]' attribute is added to them." .to_string(), ); - context.env.add_diag(err); + context.add_diag(err); e.ty = context.error_type(e.ty.loc); e.exp = sp(e.exp.loc, T::UnannotatedExp_::UnresolvedError); @@ -4272,7 +4225,7 @@ fn check_call_target( } else { "Normal (non-'macro') function is declared here" }; - context.env.add_diag(diag!( + context.add_diag(diag!( TypeSafety::InvalidCallTarget, (macro_call_loc, call_msg), (decl_loc, decl_msg), @@ -4496,7 +4449,7 @@ fn expand_macro( { None => { if !(context.env.has_errors() || context.env.ide_mode()) { - context.env.add_diag(ice!(( + context.add_diag(ice!(( call_loc, "No macro found, but name resolution passed." ))); @@ -4625,24 +4578,18 @@ fn unused_module_members(context: &mut Context, mident: &ModuleIdent_, mdef: &T: } let is_sui_mode = context.env.package_config(mdef.package_name).flavor == Flavor::Sui; - context - .env - .add_warning_filter_scope(mdef.warning_filter.clone()); + context.push_warning_filter_scope(mdef.warning_filter.clone()); for (loc, name, c) in &mdef.constants { - context - .env - .add_warning_filter_scope(c.warning_filter.clone()); + context.push_warning_filter_scope(c.warning_filter.clone()); let members = context.used_module_members.get(mident); if members.is_none() || !members.unwrap().contains(name) { let msg = format!("The constant '{name}' is never used. Consider removing it."); - context - .env - .add_diag(diag!(UnusedItem::Constant, (loc, msg))) + context.add_diag(diag!(UnusedItem::Constant, (loc, msg))) } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } for (loc, name, fun) in &mdef.functions { @@ -4658,9 +4605,7 @@ fn unused_module_members(context: &mut Context, mident: &ModuleIdent_, mdef: &T: // a Sui-specific filter to avoid signaling that the init function is unused continue; } - context - .env - .add_warning_filter_scope(fun.warning_filter.clone()); + context.push_warning_filter_scope(fun.warning_filter.clone()); let members = context.used_module_members.get(mident); if fun.entry.is_none() @@ -4673,12 +4618,10 @@ fn unused_module_members(context: &mut Context, mident: &ModuleIdent_, mdef: &T: "The non-'public', non-'entry' function '{name}' is never called. \ Consider removing it." ); - context - .env - .add_diag(diag!(UnusedItem::Function, (loc, msg))) + context.add_diag(diag!(UnusedItem::Function, (loc, msg))) } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } - context.env.pop_warning_filter_scope(); + context.pop_warning_filter_scope(); } diff --git a/external-crates/move/crates/move-compiler/src/typing/visitor.rs b/external-crates/move/crates/move-compiler/src/typing/visitor.rs index 3883684af87ff..44e8790761b56 100644 --- a/external-crates/move/crates/move-compiler/src/typing/visitor.rs +++ b/external-crates/move/crates/move-compiler/src/typing/visitor.rs @@ -17,7 +17,7 @@ use move_proc_macros::growing_stack; pub type TypingVisitorObj = Box; pub trait TypingVisitor: Send + Sync { - fn visit(&self, env: &mut CompilationEnv, program: &T::Program); + fn visit(&self, env: &CompilationEnv, program: &T::Program); fn visitor(self) -> Visitor where @@ -30,9 +30,9 @@ pub trait TypingVisitor: Send + Sync { pub trait TypingVisitorConstructor: Send + Sync { type Context<'a>: Sized + TypingVisitorContext; - fn context<'a>(env: &'a mut CompilationEnv, program: &T::Program) -> Self::Context<'a>; + fn context<'a>(env: &'a CompilationEnv, program: &T::Program) -> Self::Context<'a>; - fn visit(env: &mut CompilationEnv, program: &T::Program) { + fn visit(env: &CompilationEnv, program: &T::Program) { let mut context = Self::context(env, program); context.visit(program); } @@ -44,7 +44,7 @@ pub enum LValueKind { } pub trait TypingVisitorContext { - fn add_warning_filter_scope(&mut self, filters: WarningFilters); + fn push_warning_filter_scope(&mut self, filters: WarningFilters); fn pop_warning_filter_scope(&mut self); /// Indicates if types should be visited during the traversal of other forms (struct and enum @@ -75,7 +75,7 @@ pub trait TypingVisitorContext { } fn visit_module(&mut self, ident: ModuleIdent, mdef: &T::ModuleDefinition) { - self.add_warning_filter_scope(mdef.warning_filter.clone()); + self.push_warning_filter_scope(mdef.warning_filter.clone()); if self.visit_module_custom(ident, mdef) { self.pop_warning_filter_scope(); return; @@ -116,7 +116,7 @@ pub trait TypingVisitorContext { struct_name: DatatypeName, sdef: &N::StructDefinition, ) { - self.add_warning_filter_scope(sdef.warning_filter.clone()); + self.push_warning_filter_scope(sdef.warning_filter.clone()); if self.visit_struct_custom(module, struct_name, sdef) { self.pop_warning_filter_scope(); return; @@ -149,7 +149,7 @@ pub trait TypingVisitorContext { enum_name: DatatypeName, edef: &N::EnumDefinition, ) { - self.add_warning_filter_scope(edef.warning_filter.clone()); + self.push_warning_filter_scope(edef.warning_filter.clone()); if self.visit_enum_custom(module, enum_name, edef) { self.pop_warning_filter_scope(); return; @@ -209,7 +209,7 @@ pub trait TypingVisitorContext { constant_name: ConstantName, cdef: &T::Constant, ) { - self.add_warning_filter_scope(cdef.warning_filter.clone()); + self.push_warning_filter_scope(cdef.warning_filter.clone()); if self.visit_constant_custom(module, constant_name, cdef) { self.pop_warning_filter_scope(); return; @@ -233,7 +233,7 @@ pub trait TypingVisitorContext { function_name: FunctionName, fdef: &T::Function, ) { - self.add_warning_filter_scope(fdef.warning_filter.clone()); + self.push_warning_filter_scope(fdef.warning_filter.clone()); if self.visit_function_custom(module, function_name, fdef) { self.pop_warning_filter_scope(); return; @@ -567,7 +567,7 @@ impl From for TypingVisitorObj { } impl TypingVisitor for V { - fn visit(&self, env: &mut CompilationEnv, program: &T::Program) { + fn visit(&self, env: &CompilationEnv, program: &T::Program) { Self::visit(env, program) } } @@ -577,38 +577,41 @@ macro_rules! simple_visitor { pub struct $visitor; pub struct Context<'a> { - env: &'a mut crate::shared::CompilationEnv, + env: &'a crate::shared::CompilationEnv, + warning_filters_scope: crate::shared::WarningFiltersScope, } impl crate::typing::visitor::TypingVisitorConstructor for $visitor { type Context<'a> = Context<'a>; - fn context<'a>(env: &'a mut crate::shared::CompilationEnv, _program: &crate::typing::ast::Program) -> Self::Context<'a> { + fn context<'a>(env: &'a crate::shared::CompilationEnv, _program: &crate::typing::ast::Program) -> Self::Context<'a> { + let warning_filters_scope = env.top_level_warning_filter_scope().clone(); Context { env, + warning_filters_scope, } } } impl Context<'_> { #[allow(unused)] - fn add_diag(&mut self, diag: crate::diagnostics::Diagnostic) { - self.env.add_diag(diag); + fn add_diag(&self, diag: crate::diagnostics::Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); } #[allow(unused)] - fn add_diags(&mut self, diags: crate::diagnostics::Diagnostics) { - self.env.add_diags(diags); + fn add_diags(&self, diags: crate::diagnostics::Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); } } impl crate::typing::visitor::TypingVisitorContext for Context<'_> { - fn add_warning_filter_scope(&mut self, filters: crate::diagnostics::WarningFilters) { - self.env.add_warning_filter_scope(filters) + fn push_warning_filter_scope(&mut self, filters: crate::diagnostics::WarningFilters) { + self.warning_filters_scope.push(filters) } fn pop_warning_filter_scope(&mut self) { - self.env.pop_warning_filter_scope() + self.warning_filters_scope.pop() } $($overrides)* @@ -637,7 +640,7 @@ pub trait TypingMutVisitorConstructor: Send + Sync { } pub trait TypingMutVisitorContext { - fn add_warning_filter_scope(&mut self, filter: WarningFilters); + fn push_warning_filter_scope(&mut self, filter: WarningFilters); fn pop_warning_filter_scope(&mut self); /// Indicates if types should be visited during the traversal of other forms (struct and enum @@ -672,7 +675,7 @@ pub trait TypingMutVisitorContext { } fn visit_module(&mut self, ident: ModuleIdent, mdef: &mut T::ModuleDefinition) { - self.add_warning_filter_scope(mdef.warning_filter.clone()); + self.push_warning_filter_scope(mdef.warning_filter.clone()); if self.visit_module_custom(ident, mdef) { self.pop_warning_filter_scope(); return; @@ -713,7 +716,7 @@ pub trait TypingMutVisitorContext { struct_name: DatatypeName, sdef: &mut N::StructDefinition, ) { - self.add_warning_filter_scope(sdef.warning_filter.clone()); + self.push_warning_filter_scope(sdef.warning_filter.clone()); if self.visit_struct_custom(module, struct_name, sdef) { self.pop_warning_filter_scope(); return; @@ -746,7 +749,7 @@ pub trait TypingMutVisitorContext { enum_name: DatatypeName, edef: &mut N::EnumDefinition, ) { - self.add_warning_filter_scope(edef.warning_filter.clone()); + self.push_warning_filter_scope(edef.warning_filter.clone()); if self.visit_enum_custom(module, enum_name, edef) { self.pop_warning_filter_scope(); return; @@ -804,7 +807,7 @@ pub trait TypingMutVisitorContext { constant_name: ConstantName, cdef: &mut T::Constant, ) { - self.add_warning_filter_scope(cdef.warning_filter.clone()); + self.push_warning_filter_scope(cdef.warning_filter.clone()); if self.visit_constant_custom(module, constant_name, cdef) { self.pop_warning_filter_scope(); return; @@ -828,7 +831,7 @@ pub trait TypingMutVisitorContext { function_name: FunctionName, fdef: &mut T::Function, ) { - self.add_warning_filter_scope(fdef.warning_filter.clone()); + self.push_warning_filter_scope(fdef.warning_filter.clone()); if self.visit_function_custom(module, function_name, fdef) { self.pop_warning_filter_scope(); return; diff --git a/external-crates/move/crates/move-compiler/src/unit_test/filter_test_members.rs b/external-crates/move/crates/move-compiler/src/unit_test/filter_test_members.rs index 225b4f91628b5..2fb22b66b4b30 100644 --- a/external-crates/move/crates/move-compiler/src/unit_test/filter_test_members.rs +++ b/external-crates/move/crates/move-compiler/src/unit_test/filter_test_members.rs @@ -18,13 +18,13 @@ use crate::{ use std::sync::Arc; struct Context<'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, is_source_def: bool, current_package: Option, } impl<'env> Context<'env> { - fn new(env: &'env mut CompilationEnv) -> Self { + fn new(env: &'env CompilationEnv) -> Self { Self { env, is_source_def: false, @@ -92,7 +92,7 @@ pub const UNIT_TEST_POISON_FUN_NAME: Symbol = symbol!("unit_test_poison"); // in `compilation_env` is not set. If the test flag is set, no filtering is performed, and instead // a test plan is created for use by the testing framework. pub fn program( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: P::Program, ) -> P::Program { @@ -127,7 +127,7 @@ fn has_unit_test_module(prog: &P::Program) -> bool { } fn check_has_unit_test_module( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, pre_compiled_lib: Option>, prog: &P::Program, ) -> bool { @@ -145,7 +145,7 @@ fn check_has_unit_test_module( P::Definition::Module(P::ModuleDefinition { name, .. }) => name.0.loc, P::Definition::Address(P::AddressDefinition { loc, .. }) => *loc, }; - compilation_env.add_diag(diag!( + compilation_env.add_error_diag(diag!( Attributes::InvalidTest, ( loc, diff --git a/external-crates/move/crates/move-compiler/src/unit_test/plan_builder.rs b/external-crates/move/crates/move-compiler/src/unit_test/plan_builder.rs index 7aab1a163d71d..53e0c97885894 100644 --- a/external-crates/move/crates/move-compiler/src/unit_test/plan_builder.rs +++ b/external-crates/move/crates/move-compiler/src/unit_test/plan_builder.rs @@ -5,6 +5,7 @@ use crate::{ cfgir::ast as G, diag, + diagnostics::{Diagnostic, Diagnostics, WarningFilters}, expansion::ast::{ self as E, Address, Attribute, AttributeValue, Attributes, ModuleAccess_, ModuleIdent, ModuleIdent_, @@ -15,7 +16,7 @@ use crate::{ shared::{ known_attributes::{self, TestingAttribute}, unique_map::UniqueMap, - CompilationEnv, Identifier, NumericalAddress, + CompilationEnv, Identifier, NumericalAddress, WarningFiltersScope, }, unit_test::{ ExpectedFailure, ExpectedMoveError, ModuleTestPlan, MoveErrorType, TestArgument, TestCase, @@ -33,12 +34,13 @@ use move_symbol_pool::Symbol; use std::collections::BTreeMap; struct Context<'env> { - env: &'env mut CompilationEnv, + env: &'env CompilationEnv, + warning_filters_scope: WarningFiltersScope, constants: UniqueMap, Attributes)>>, } impl<'env> Context<'env> { - fn new(compilation_env: &'env mut CompilationEnv, prog: &G::Program) -> Self { + fn new(compilation_env: &'env CompilationEnv, prog: &G::Program) -> Self { let constants = prog.modules.ref_map(|_mident, module| { module.constants.ref_map(|_name, constant| { let v_opt = constant.value.as_ref().and_then(|v| match v { @@ -48,12 +50,31 @@ impl<'env> Context<'env> { (constant.loc, v_opt, constant.attributes.clone()) }) }); + let warning_filters_scope = compilation_env.top_level_warning_filter_scope().clone(); Self { env: compilation_env, + warning_filters_scope, constants, } } + pub fn add_diag(&self, diag: Diagnostic) { + self.env.add_diag(&self.warning_filters_scope, diag); + } + + #[allow(unused)] + pub fn add_diags(&self, diags: Diagnostics) { + self.env.add_diags(&self.warning_filters_scope, diags); + } + + pub fn push_warning_filter_scope(&mut self, filters: WarningFilters) { + self.warning_filters_scope.push(filters) + } + + pub fn pop_warning_filter_scope(&mut self) { + self.warning_filters_scope.pop() + } + fn resolve_address(&self, addr: &Address) -> NumericalAddress { (*addr).into_addr_bytes() } @@ -72,7 +93,7 @@ impl<'env> Context<'env> { // Constructs a test plan for each module in `prog`. This also validates the structure of the // attributes as the test plan is constructed. pub fn construct_test_plan( - compilation_env: &mut CompilationEnv, + compilation_env: &CompilationEnv, package_filter: Option, prog: &G::Program, ) -> Option> { @@ -85,7 +106,15 @@ pub fn construct_test_plan( prog.modules .key_cloned_iter() .flat_map(|(module_ident, module_def)| { - construct_module_test_plan(&mut context, package_filter, module_ident, module_def) + context.push_warning_filter_scope(module_def.warning_filter.clone()); + let plan = construct_module_test_plan( + &mut context, + package_filter, + module_ident, + module_def, + ); + context.pop_warning_filter_scope(); + plan }) .collect(), ) @@ -104,8 +133,11 @@ fn construct_module_test_plan( .functions .iter() .filter_map(|(loc, fn_name, func)| { - build_test_info(context, loc, fn_name, func) - .map(|test_case| (fn_name.to_string(), test_case)) + context.push_warning_filter_scope(func.warning_filter.clone()); + let info = build_test_info(context, loc, fn_name, func) + .map(|test_case| (fn_name.to_string(), test_case)); + context.pop_warning_filter_scope(); + info }) .collect(); @@ -143,7 +175,7 @@ fn build_test_info<'func>( let fn_msg = "Only functions defined as a test with #[test] can also have an \ #[expected_failure] attribute"; let abort_msg = "Attributed as #[expected_failure] here"; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidUsage, (fn_loc, fn_msg), (abort_attribute.loc, abort_msg), @@ -154,7 +186,7 @@ fn build_test_info<'func>( (Some(test_attribute), Some(random_test_attribute)) => { let msg = "Function annotated as both #[test] and #[random_test]. You need to declare \ it as either one or the other"; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidUsage, (random_test_attribute.loc, msg), (test_attribute.loc, PREVIOUSLY_ANNOTATED_MSG), @@ -170,7 +202,7 @@ fn build_test_info<'func>( if let Some(test_only_attribute) = test_only_attribute_opt { let msg = "Function annotated as both #[test] and #[test_only]. You need to declare \ it as either one or the other"; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidUsage, (test_only_attribute.loc, msg), (test_attribute.loc, PREVIOUSLY_ANNOTATED_MSG), @@ -205,7 +237,7 @@ fn build_test_info<'func>( "Supported builti-in types are: bool, u8, u16, u32, u64, \ u128, u256, address, and vector where T is a built-in type", ); - context.env.add_diag(diag); + context.add_diag(diag); return None; } }; @@ -214,7 +246,7 @@ fn build_test_info<'func>( None => { let missing_param_msg = "Missing test parameter assignment in test. Expected a \ parameter to be assigned in this attribute"; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidTest, (test_attribute.loc, missing_param_msg), (vloc, "Corresponding to this parameter"), @@ -227,7 +259,7 @@ fn build_test_info<'func>( if is_random_test && arguments.is_empty() { let msg = "No parameters to generate for random test. A #[random_test] function must \ have at least one parameter to generate."; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidTest, (test_attribute.loc, msg), (fn_loc, IN_THIS_TEST_MSG), @@ -266,7 +298,7 @@ fn parse_test_attribute( match test_attribute { EA::Name(_) | EA::Parameterized(_, _) if depth > 0 => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidTest, (*aloc, "Unexpected nested attribute in test declaration"), )); @@ -281,7 +313,7 @@ fn parse_test_attribute( } EA::Assigned(nm, attr_value) => { if depth != 1 { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidTest, (*aloc, "Unexpected nested attribute in test declaration"), )); @@ -291,7 +323,7 @@ fn parse_test_attribute( let value = match convert_attribute_value_to_move_value(context, attr_value) { Some(move_value) => move_value, None => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (*assign_loc, "Unsupported attribute value"), (*aloc, "Assigned in this attribute"), @@ -338,7 +370,7 @@ fn parse_failure_attribute( let invalid_assignment_msg = "Invalid expected failure code assignment"; let expected_msg = "Expect an #[expected_failure(...)] attribute for error specification"; - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (assign_loc, invalid_assignment_msg), (*aloc, expected_msg), @@ -369,9 +401,7 @@ fn parse_failure_attribute( expected_failure_kind_vec.len(), TestingAttribute::expected_failure_cases().to_vec().join(", ") ); - context - .env - .add_diag(diag!(Attributes::InvalidValue, (*aloc, invalid_attr_msg))); + context.add_diag(diag!(Attributes::InvalidValue, (*aloc, invalid_attr_msg))); return None; } let (expected_failure_kind, (attr_loc, attr)) = @@ -400,7 +430,7 @@ fn parse_failure_attribute( attribute.", TestingAttribute::ERROR_LOCATION ); - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::ValueWarning, (attr_loc, BAD_ABORT_VALUE_WARNING), (value_loc, tip) @@ -500,7 +530,7 @@ fn parse_failure_attribute( ); let no_code = format!("No status code associated with value '{move_error_type}'"); - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (value_name_loc, bad_value), (major_value_loc, no_code) @@ -541,9 +571,7 @@ fn parse_failure_attribute( "Unused attribute for {}", TestingAttribute::ExpectedFailure.name() ); - context - .env - .add_diag(diag!(UnusedItem::Attribute, (loc, msg))); + context.add_diag(diag!(UnusedItem::Attribute, (loc, msg))); } Some(ExpectedFailure::ExpectedWithError(ExpectedMoveError( status_code, @@ -571,7 +599,7 @@ fn check_attribute_unassigned( "Expected no assigned value, e.g. '{}', for expected failure attribute", kind ); - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (attr_loc, "Unsupported attribute in this location"), (loc, msg) @@ -598,7 +626,7 @@ fn get_assigned_attribute( "Expected assigned value, e.g. '{}=...', for expected failure attribute", kind ); - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (attr_loc, "Unsupported attribute in this location"), (loc, msg) @@ -615,7 +643,7 @@ fn convert_location(context: &mut Context, attr_loc: Loc, attr: Attribute) -> Op match value { sp!(vloc, EAV::Module(module)) => convert_module_id(context, vloc, &module), sp!(vloc, _) => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (loc, INVALID_VALUE), (vloc, "Expected a module identifier, e.g. 'std::vector'") @@ -645,7 +673,7 @@ fn convert_constant_value_u64_constant_or_value( let modules_constants = context.constants().get(module).unwrap(); let constant = match modules_constants.get_(&member.value) { None => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (vloc, INVALID_VALUE), ( @@ -667,7 +695,7 @@ fn convert_constant_value_u64_constant_or_value( "Constant '{module}::{member}' has a non-u64 value. \ Only 'u64' values are permitted" ); - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (vloc, INVALID_VALUE), (*cloc, msg), @@ -680,7 +708,7 @@ fn convert_constant_value_u64_constant_or_value( fn convert_module_id(context: &mut Context, vloc: Loc, module: &ModuleIdent) -> Option { if !context.constants.contains_key(module) { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (vloc, INVALID_VALUE), (module.loc, format!("Unbound module '{module}'")), @@ -693,7 +721,7 @@ fn convert_module_id(context: &mut Context, vloc: Loc, module: &ModuleIdent) -> value: sp!(_, a), .. } => a.into_inner(), Address::NamedUnassigned(addr) => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (vloc, INVALID_VALUE), (*mloc, format!("Unbound address '{addr}'")), @@ -722,7 +750,7 @@ fn convert_attribute_value_u64( | sp!(vloc, EAV::Value(sp!(_, EV::U32(_)))) | sp!(vloc, EAV::Value(sp!(_, EV::U128(_)))) | sp!(vloc, EAV::Value(sp!(_, EV::U256(_)))) => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (loc, INVALID_VALUE), (*vloc, "Annotated non-u64 literals are not permitted"), @@ -730,7 +758,7 @@ fn convert_attribute_value_u64( None } sp!(vloc, _) => { - context.env.add_diag(diag!( + context.add_diag(diag!( Attributes::InvalidValue, (loc, INVALID_VALUE), (*vloc, "Unsupported value in this assignment"), @@ -765,9 +793,7 @@ fn check_location( "Expected '{}' following '{attr}'", TestingAttribute::ERROR_LOCATION ); - context - .env - .add_diag(diag!(Attributes::InvalidUsage, (loc, msg))); + context.add_diag(diag!(Attributes::InvalidUsage, (loc, msg))); } location } diff --git a/external-crates/move/crates/move-unit-test/src/lib.rs b/external-crates/move/crates/move-unit-test/src/lib.rs index 00d42c0219885..496782ee916b9 100644 --- a/external-crates/move/crates/move-unit-test/src/lib.rs +++ b/external-crates/move/crates/move-unit-test/src/lib.rs @@ -187,7 +187,7 @@ impl UnitTestingConfig { let (_, compiler) = diagnostics::unwrap_or_report_pass_diagnostics(&files, comments_and_compiler_res); - let (mut compiler, cfgir) = compiler.into_ast(); + let (compiler, cfgir) = compiler.into_ast(); let compilation_env = compiler.compilation_env(); let test_plan = unit_test::plan_builder::construct_test_plan(compilation_env, None, &cfgir); let mapped_files = compilation_env.mapped_files().clone();