From e2ffa9be9e2be57d4c5fabca3c69c2a794e84f69 Mon Sep 17 00:00:00 2001 From: tritao Date: Sun, 5 Oct 2025 13:30:32 +0100 Subject: [PATCH 1/6] Introduce `ty::TyStatement`. --- .../analyze_return_paths.rs | 4 +- .../dead_code_analysis.rs | 14 ++- sway-core/src/ir_generation/const_eval.rs | 8 +- sway-core/src/ir_generation/function.rs | 4 +- sway-core/src/language/ty/ast_node.rs | 31 +++++- sway-core/src/language/ty/mod.rs | 2 + sway-core/src/language/ty/statement/mod.rs | 105 ++++++++++++++++++ .../ast_node/statement/mod.rs | 0 .../semantic_analysis/cei_pattern_analysis.rs | 8 +- sway-lsp/src/core/token.rs | 1 + sway-lsp/src/traverse/typed_tree.rs | 21 ++++ sway-lsp/src/utils/debug.rs | 1 + 12 files changed, 186 insertions(+), 13 deletions(-) create mode 100644 sway-core/src/language/ty/statement/mod.rs create mode 100644 sway-core/src/semantic_analysis/ast_node/statement/mod.rs diff --git a/sway-core/src/control_flow_analysis/analyze_return_paths.rs b/sway-core/src/control_flow_analysis/analyze_return_paths.rs index 4186bc91b26..e6fb960fd10 100644 --- a/sway-core/src/control_flow_analysis/analyze_return_paths.rs +++ b/sway-core/src/control_flow_analysis/analyze_return_paths.rs @@ -191,7 +191,9 @@ fn connect_node<'eng: 'cfg, 'cfg>( } Ok(NodeConnection::NextStep(Some(entry))) } - ty::TyAstNodeContent::SideEffect(_) => Ok(NodeConnection::NextStep(leaf_opt)), + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { + Ok(NodeConnection::NextStep(leaf_opt)) + } ty::TyAstNodeContent::Declaration(decl) => Ok(NodeConnection::NextStep( connect_declaration(engines, node, decl, graph, leaf_opt)?, )), diff --git a/sway-core/src/control_flow_analysis/dead_code_analysis.rs b/sway-core/src/control_flow_analysis/dead_code_analysis.rs index f0f5e60460c..1250cd1b8e9 100644 --- a/sway-core/src/control_flow_analysis/dead_code_analysis.rs +++ b/sway-core/src/control_flow_analysis/dead_code_analysis.rs @@ -465,7 +465,9 @@ fn connect_node<'eng: 'cfg, 'cfg>( }, ) } - ty::TyAstNodeContent::SideEffect(_) => (leaves.to_vec(), exit_node), + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { + (leaves.to_vec(), exit_node) + } ty::TyAstNodeContent::Declaration(decl) => { // all leaves connect to this node, then this node is the singular leaf let cfg_node: ControlFlowGraphNode = @@ -2435,6 +2437,10 @@ fn construct_dead_code_warning_from_node( content: ty::TyAstNodeContent::Declaration(ty::TyDecl::AbiDecl(_)), .. } => return None, + ty::TyAstNode { + content: ty::TyAstNodeContent::Statement(_), + .. + } => return None, // We handle storage fields individually. There is no need to emit any warnings for the // storage declaration itself. ty::TyAstNode { @@ -2456,7 +2462,9 @@ fn construct_dead_code_warning_from_node( // Otherwise, this is unreachable. ty::TyAstNode { span, - content: ty::TyAstNodeContent::Expression(_) | ty::TyAstNodeContent::SideEffect(_), + content: + ty::TyAstNodeContent::Expression(_) + | ty::TyAstNodeContent::SideEffect(_), } => CompileWarning { span: span.clone(), warning_content: Warning::UnreachableCode, @@ -2629,7 +2637,7 @@ fn allow_dead_code_ast_node(decl_engine: &DeclEngine, node: &ty::TyAstNode) -> b ty::TyDecl::StorageDecl { .. } => false, }, ty::TyAstNodeContent::Expression(_) => false, - ty::TyAstNodeContent::SideEffect(_) => false, + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => false, ty::TyAstNodeContent::Error(_, _) => false, } } diff --git a/sway-core/src/ir_generation/const_eval.rs b/sway-core/src/ir_generation/const_eval.rs index ac9fc35f657..eae88429412 100644 --- a/sway-core/src/ir_generation/const_eval.rs +++ b/sway-core/src/ir_generation/const_eval.rs @@ -875,9 +875,11 @@ fn const_eval_codeblock( } } }, - ty::TyAstNodeContent::SideEffect(_) => Err(ConstEvalError::CannotBeEvaluatedToConst { - span: ast_node.span.clone(), - }), + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { + Err(ConstEvalError::CannotBeEvaluatedToConst { + span: ast_node.span.clone(), + }) + } ty::TyAstNodeContent::Error(_, _) => Err(ConstEvalError::CannotBeEvaluatedToConst { span: ast_node.span.clone(), }), diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index 374895a2559..0c75fe5fc5e 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -387,6 +387,7 @@ impl<'a> FnCompiler<'a> { ty::TyDecl::EnumVariantDecl { .. } => unexpected_decl("enum variant"), ty::TyDecl::TraitTypeDecl { .. } => unexpected_decl("trait type"), }, + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => Ok(None), ty::TyAstNodeContent::Expression(te) => { match &te.expression { TyExpressionVariant::ImplicitReturn(exp) => self @@ -404,9 +405,6 @@ impl<'a> FnCompiler<'a> { } } } - // a side effect can be () because it just impacts the type system/namespacing. - // There should be no new IR generated. - ty::TyAstNodeContent::SideEffect(_) => Ok(None), ty::TyAstNodeContent::Error(_, _) => { unreachable!("error node found when generating IR"); } diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index 416328f3512..d2dcd9d1916 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -53,6 +53,7 @@ impl DebugWithEngines for TyAstNode { use TyAstNodeContent::*; match &self.content { Declaration(typed_decl) => DebugWithEngines::fmt(typed_decl, f, engines), + Statement(stmt) => Debug::fmt(stmt, f), Expression(exp) => DebugWithEngines::fmt(exp, f, engines), SideEffect(_) => f.write_str(""), Error(_, _) => f.write_str("error"), @@ -64,6 +65,7 @@ impl SubstTypes for TyAstNode { fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { match self.content { TyAstNodeContent::Declaration(ref mut decl) => decl.subst(ctx), + TyAstNodeContent::Statement(ref mut statement) => statement.subst(ctx), TyAstNodeContent::Expression(ref mut expr) => expr.subst(ctx), TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => HasChanges::No, } @@ -82,6 +84,9 @@ impl ReplaceDecls for TyAstNode { decl.body.replace_decls(decl_mapping, handler, ctx) } TyAstNodeContent::Declaration(_) => Ok(false), + TyAstNodeContent::Statement(ref mut statement) => { + statement.replace_decls(decl_mapping, handler, ctx) + } TyAstNodeContent::Expression(ref mut expr) => { expr.replace_decls(decl_mapping, handler, ctx) } @@ -95,6 +100,13 @@ impl UpdateConstantExpression for TyAstNode { fn update_constant_expression(&mut self, engines: &Engines, implementing_type: &TyDecl) { match self.content { TyAstNodeContent::Declaration(_) => {} + TyAstNodeContent::Statement(ref mut statement) => match statement { + TyStatement::Let(binding) => { + binding + .value + .update_constant_expression(engines, implementing_type); + } + }, TyAstNodeContent::Expression(ref mut expr) => { expr.update_constant_expression(engines, implementing_type) } @@ -178,6 +190,9 @@ impl MaterializeConstGenerics for TyAstNode { } Ok(()) } + TyAstNodeContent::Statement(statement) => { + statement.materialize_const_generics(engines, handler, name, value) + } TyAstNodeContent::Expression(expr) => { expr.materialize_const_generics(engines, handler, name, value) } @@ -192,6 +207,7 @@ impl TyAstNode { match &self.content { TyAstNodeContent::Declaration(decl) => decl.visibility(decl_engine).is_public(), TyAstNodeContent::Expression(_) + | TyAstNodeContent::Statement(_) | TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => false, } @@ -244,6 +260,7 @@ impl TyAstNode { TyAstNodeContent::Expression(TyExpression { return_type, .. }) => { (*type_engine.get(*return_type)).clone() } + TyAstNodeContent::Statement(_) => TypeInfo::Tuple(Vec::new()), TyAstNodeContent::SideEffect(_) => TypeInfo::Tuple(Vec::new()), TyAstNodeContent::Error(_, error) => TypeInfo::ErrorRecovery(*error), } @@ -320,6 +337,8 @@ impl TyAstNode { TyAstNodeContent::Expression(node) => { node.check_deprecated(engines, handler, allow_deprecated); } + TyAstNodeContent::Statement(statement) => match statement { + }, TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {} } } @@ -364,7 +383,8 @@ impl TyAstNode { | TyDecl::TypeAliasDecl(_) => {} }, TyAstNodeContent::Expression(_node) => {} - TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {} + TyAstNodeContent::Statement(_) | TyAstNodeContent::SideEffect(_) => {} + TyAstNodeContent::Error(_, _) => {} }; Ok(()) }) @@ -409,6 +429,7 @@ impl TyAstNode { #[allow(clippy::large_enum_variant)] pub enum TyAstNodeContent { Declaration(TyDecl), + Statement(TyStatement), Expression(TyExpression), // a no-op node used for something that just issues a side effect, like an import statement. SideEffect(TySideEffect), @@ -420,6 +441,7 @@ impl PartialEqWithEngines for TyAstNodeContent { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { match (self, other) { (Self::Declaration(x), Self::Declaration(y)) => x.eq(y, ctx), + (Self::Statement(x), Self::Statement(y)) => x.eq(y, ctx), (Self::Expression(x), Self::Expression(y)) => x.eq(y, ctx), (Self::SideEffect(_), Self::SideEffect(_)) => true, _ => false, @@ -435,6 +457,9 @@ impl HashWithEngines for TyAstNodeContent { Declaration(decl) => { decl.hash(state, engines); } + Statement(stmt) => { + stmt.hash(state, engines); + } Expression(exp) => { exp.hash(state, engines); } @@ -454,6 +479,7 @@ impl TypeCheckAnalysis for TyAstNodeContent { ) -> Result<(), ErrorEmitted> { match self { TyAstNodeContent::Declaration(node) => node.type_check_analyze(handler, ctx)?, + TyAstNodeContent::Statement(node) => node.type_check_analyze(handler, ctx)?, TyAstNodeContent::Expression(node) => node.type_check_analyze(handler, ctx)?, TyAstNodeContent::SideEffect(_) => {} TyAstNodeContent::Error(_, _) => {} @@ -470,6 +496,7 @@ impl TypeCheckFinalization for TyAstNodeContent { ) -> Result<(), ErrorEmitted> { match self { TyAstNodeContent::Declaration(node) => node.type_check_finalize(handler, ctx)?, + TyAstNodeContent::Statement(node) => node.type_check_finalize(handler, ctx)?, TyAstNodeContent::Expression(node) => node.type_check_finalize(handler, ctx)?, TyAstNodeContent::SideEffect(_) => {} TyAstNodeContent::Error(_, _) => {} @@ -487,6 +514,7 @@ impl CollectTypesMetadata for TyAstNodeContent { use TyAstNodeContent::*; match self { Declaration(decl) => decl.collect_types_metadata(handler, ctx), + Statement(stmt) => stmt.collect_types_metadata(handler, ctx), Expression(expr) => expr.collect_types_metadata(handler, ctx), SideEffect(_) => Ok(vec![]), Error(_, _) => Ok(vec![]), @@ -499,6 +527,7 @@ impl GetDeclIdent for TyAstNodeContent { match self { TyAstNodeContent::Declaration(decl) => decl.get_decl_ident(engines), TyAstNodeContent::Expression(_expr) => None, //expr.get_decl_ident(), + TyAstNodeContent::Statement(_) => None, TyAstNodeContent::SideEffect(_) => None, TyAstNodeContent::Error(_, _) => None, } diff --git a/sway-core/src/language/ty/mod.rs b/sway-core/src/language/ty/mod.rs index f48713d6656..9d79eb9bf97 100644 --- a/sway-core/src/language/ty/mod.rs +++ b/sway-core/src/language/ty/mod.rs @@ -5,6 +5,7 @@ mod expression; mod module; mod program; mod side_effect; +mod statement; mod variable_mutability; pub use ast_node::*; @@ -14,4 +15,5 @@ pub use expression::*; pub use module::*; pub use program::*; pub use side_effect::*; +pub use statement::*; pub use variable_mutability::*; diff --git a/sway-core/src/language/ty/statement/mod.rs b/sway-core/src/language/ty/statement/mod.rs new file mode 100644 index 00000000000..42c72f9d76d --- /dev/null +++ b/sway-core/src/language/ty/statement/mod.rs @@ -0,0 +1,105 @@ +use crate::{ + decl_engine::{DeclMapping, MaterializeConstGenerics, ReplaceDecls}, + engine_threading::*, + language::ty::{TyExpression, TyVariableDecl, VariableMutability}, + semantic_analysis::{ + TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization, + TypeCheckFinalizationContext, + }, + type_system::*, + types::*, + GenericArgument, +}; +use ast_elements::type_parameter::ConstGenericExpr; +use serde::{Deserialize, Serialize}; +use std::hash::{Hash, Hasher}; +use sway_error::handler::{ErrorEmitted, Handler}; +use sway_types::{Ident, Named, Span, Spanned}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[allow(clippy::large_enum_variant)] +pub enum TyStatement { +} + +impl EqWithEngines for TyStatement {} +impl PartialEqWithEngines for TyStatement { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + } + } +} + +impl HashWithEngines for TyStatement { + fn hash(&self, state: &mut H, engines: &Engines) { + match self { + } + } +} + +impl SubstTypes for TyStatement { + fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { + match self { + } + } +} + +impl ReplaceDecls for TyStatement { + fn replace_decls_inner( + &mut self, + decl_mapping: &DeclMapping, + handler: &Handler, + ctx: &mut TypeCheckContext, + ) -> Result { + match self { + } + } +} + +impl TypeCheckAnalysis for TyStatement { + fn type_check_analyze( + &self, + handler: &Handler, + ctx: &mut TypeCheckAnalysisContext, + ) -> Result<(), ErrorEmitted> { + match self { + } + Ok(()) + } +} + +impl TypeCheckFinalization for TyStatement { + fn type_check_finalize( + &mut self, + handler: &Handler, + ctx: &mut TypeCheckFinalizationContext, + ) -> Result<(), ErrorEmitted> { + match self { + } + Ok(()) + } +} + +impl CollectTypesMetadata for TyStatement { + fn collect_types_metadata( + &self, + handler: &Handler, + ctx: &mut CollectTypesMetadataContext, + ) -> Result, ErrorEmitted> { + match self { + } + } +} + +impl MaterializeConstGenerics for TyStatement { + fn materialize_const_generics( + &mut self, + engines: &Engines, + handler: &Handler, + name: &str, + value: &TyExpression, + ) -> Result<(), ErrorEmitted> { + match self { + } + } +} + diff --git a/sway-core/src/semantic_analysis/ast_node/statement/mod.rs b/sway-core/src/semantic_analysis/ast_node/statement/mod.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sway-core/src/semantic_analysis/cei_pattern_analysis.rs b/sway-core/src/semantic_analysis/cei_pattern_analysis.rs index 9cc4dc7a736..3d4e63bfe6a 100644 --- a/sway-core/src/semantic_analysis/cei_pattern_analysis.rs +++ b/sway-core/src/semantic_analysis/cei_pattern_analysis.rs @@ -193,7 +193,9 @@ fn analyze_code_block_entry( ty::TyAstNodeContent::Expression(expr) => { analyze_expression(engines, expr, block_name, warnings) } - ty::TyAstNodeContent::SideEffect(_) | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), + ty::TyAstNodeContent::Statement(_) + | ty::TyAstNodeContent::SideEffect(_) + | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), } } @@ -495,7 +497,9 @@ fn effects_of_codeblock_entry(engines: &Engines, ast_node: &ty::TyAstNode) -> Ha match &ast_node.content { ty::TyAstNodeContent::Declaration(decl) => effects_of_codeblock_decl(engines, decl), ty::TyAstNodeContent::Expression(expr) => effects_of_expression(engines, expr), - ty::TyAstNodeContent::SideEffect(_) | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), + ty::TyAstNodeContent::Statement(_) + | ty::TyAstNodeContent::SideEffect(_) + | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), } } diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index ffb18aec9bb..68d43c48c51 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -86,6 +86,7 @@ pub enum TypedAstToken { TypedModuleName, TypedIncludeStatement(ty::TyIncludeStatement), TypedUseStatement(ty::TyUseStatement), + TypedStatement(ty::TyStatement), Ident(Ident), } diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index 5f28b93500a..a2ae429f34f 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -66,6 +66,7 @@ impl Parse for ty::TyAstNode { fn parse(&self, ctx: &ParseContext) { match &self.content { ty::TyAstNodeContent::Declaration(declaration) => declaration.parse(ctx), + ty::TyAstNodeContent::Statement(statement) => statement.parse(ctx), ty::TyAstNodeContent::Expression(expression) => expression.parse(ctx), ty::TyAstNodeContent::SideEffect(side_effect) => side_effect.parse(ctx), ty::TyAstNodeContent::Error(_, _) => {} @@ -662,6 +663,26 @@ impl Parse for ty::TyVariableDecl { } } +impl Parse for ty::TyStatement { + fn parse(&self, ctx: &ParseContext) { + match self { + ty::TyStatement::Let(binding) => { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&binding.name)) + { + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedStatement( + self.clone(), + )); + token.type_def = Some(TypeDefinition::Ident(binding.name.clone())); + } + if let Some(call_path_tree) = &binding.type_ascription.call_path_tree() { + collect_call_path_tree(ctx, call_path_tree, &binding.type_ascription); + } + binding.value.parse(ctx); + } + } + } +} + impl Parse for ty::ConstantDecl { fn parse(&self, ctx: &ParseContext) { let const_decl = ctx.engines.de().get_constant(&self.decl_id); diff --git a/sway-lsp/src/utils/debug.rs b/sway-lsp/src/utils/debug.rs index e98390d6694..bbc448c4d69 100644 --- a/sway-lsp/src/utils/debug.rs +++ b/sway-lsp/src/utils/debug.rs @@ -114,6 +114,7 @@ pub(crate) fn print_decl_engine_types( ty::TyAstNodeContent::Expression(expression) => { format!("{expression:#?}") } + ty::TyAstNodeContent::Statement(statement) => format!("{statement:#?}"), ty::TyAstNodeContent::SideEffect(side_effect) => format!("{side_effect:#?}"), ty::TyAstNodeContent::Error(_, _) => "error".to_string(), }) From c7532f0db0e3cc8f01b7a0948d1c1bd6df0588fa Mon Sep 17 00:00:00 2001 From: tritao Date: Tue, 7 Oct 2025 21:28:36 +0100 Subject: [PATCH 2/6] Introduce `ty::TyLetBinding`. --- sway-core/src/language/ty/ast_node.rs | 5 + sway-core/src/language/ty/statement/mod.rs | 131 ++++++++++++++++++ .../ast_node/statement/let_binding.rs | 52 +++++++ .../ast_node/statement/mod.rs | 3 + 4 files changed, 191 insertions(+) create mode 100644 sway-core/src/semantic_analysis/ast_node/statement/let_binding.rs diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index d2dcd9d1916..86c334c65b4 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -338,6 +338,11 @@ impl TyAstNode { node.check_deprecated(engines, handler, allow_deprecated); } TyAstNodeContent::Statement(statement) => match statement { + TyStatement::Let(binding) => { + binding + .value + .check_deprecated(engines, handler, allow_deprecated); + } }, TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {} } diff --git a/sway-core/src/language/ty/statement/mod.rs b/sway-core/src/language/ty/statement/mod.rs index 42c72f9d76d..cd26ee9004a 100644 --- a/sway-core/src/language/ty/statement/mod.rs +++ b/sway-core/src/language/ty/statement/mod.rs @@ -19,12 +19,35 @@ use sway_types::{Ident, Named, Span, Spanned}; #[derive(Clone, Debug, Serialize, Deserialize)] #[allow(clippy::large_enum_variant)] pub enum TyStatement { + Let(TyLetBinding), +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TyLetBinding { + pub name: Ident, + pub value: TyExpression, + pub mutability: VariableMutability, + pub return_type: TypeId, + pub type_ascription: GenericArgument, +} + +impl Named for TyLetBinding { + fn name(&self) -> &sway_types::BaseIdent { + &self.name + } +} + +impl Spanned for TyLetBinding { + fn span(&self) -> Span { + self.name.span() + } } impl EqWithEngines for TyStatement {} impl PartialEqWithEngines for TyStatement { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { match (self, other) { + (TyStatement::Let(lhs), TyStatement::Let(rhs)) => lhs.eq(rhs, ctx), } } } @@ -32,6 +55,7 @@ impl PartialEqWithEngines for TyStatement { impl HashWithEngines for TyStatement { fn hash(&self, state: &mut H, engines: &Engines) { match self { + TyStatement::Let(binding) => binding.hash(state, engines), } } } @@ -39,6 +63,7 @@ impl HashWithEngines for TyStatement { impl SubstTypes for TyStatement { fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { match self { + TyStatement::Let(binding) => binding.subst(ctx), } } } @@ -51,6 +76,7 @@ impl ReplaceDecls for TyStatement { ctx: &mut TypeCheckContext, ) -> Result { match self { + TyStatement::Let(binding) => binding.value.replace_decls(decl_mapping, handler, ctx), } } } @@ -62,6 +88,7 @@ impl TypeCheckAnalysis for TyStatement { ctx: &mut TypeCheckAnalysisContext, ) -> Result<(), ErrorEmitted> { match self { + TyStatement::Let(binding) => binding.value.type_check_analyze(handler, ctx)?, } Ok(()) } @@ -74,6 +101,7 @@ impl TypeCheckFinalization for TyStatement { ctx: &mut TypeCheckFinalizationContext, ) -> Result<(), ErrorEmitted> { match self { + TyStatement::Let(binding) => binding.value.type_check_finalize(handler, ctx)?, } Ok(()) } @@ -86,6 +114,16 @@ impl CollectTypesMetadata for TyStatement { ctx: &mut CollectTypesMetadataContext, ) -> Result, ErrorEmitted> { match self { + TyStatement::Let(binding) => { + let mut metadata = binding.value.collect_types_metadata(handler, ctx)?; + metadata.append( + &mut binding + .type_ascription + .type_id() + .collect_types_metadata(handler, ctx)?, + ); + Ok(metadata) + } } } } @@ -99,7 +137,100 @@ impl MaterializeConstGenerics for TyStatement { value: &TyExpression, ) -> Result<(), ErrorEmitted> { match self { + TyStatement::Let(binding) => { + binding + .value + .materialize_const_generics(engines, handler, name, value)?; + binding + .return_type + .materialize_const_generics(engines, handler, name, value)?; + match &mut binding.type_ascription { + GenericArgument::Type(arg) => arg + .type_id + .materialize_const_generics(engines, handler, name, value)?, + GenericArgument::Const(arg) => { + if matches!( + &arg.expr, + ConstGenericExpr::AmbiguousVariableExpression { ident, .. } + if ident.as_str() == name + ) { + arg.expr = ConstGenericExpr::from_ty_expression(handler, value)?; + } + } + } + Ok(()) + } + } + } +} + +impl EqWithEngines for TyLetBinding {} +impl PartialEqWithEngines for TyLetBinding { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + let type_engine = ctx.engines().te(); + self.name == other.name + && self.value.eq(&other.value, ctx) + && self.mutability == other.mutability + && type_engine + .get(self.return_type) + .eq(&type_engine.get(other.return_type), ctx) + && self.type_ascription.eq(&other.type_ascription, ctx) + } +} + +impl HashWithEngines for TyLetBinding { + fn hash(&self, state: &mut H, engines: &Engines) { + let TyLetBinding { + name, + value, + mutability, + return_type, + type_ascription, + } = self; + let type_engine = engines.te(); + name.hash(state); + value.hash(state, engines); + type_engine.get(*return_type).hash(state, engines); + type_ascription.hash(state, engines); + mutability.hash(state); + } +} + +impl SubstTypes for TyLetBinding { + fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { + self.return_type.subst(ctx); + self.type_ascription.subst(ctx); + self.value.subst(ctx) + } +} + +impl From for TyLetBinding { + fn from(decl: TyVariableDecl) -> Self { + let TyVariableDecl { + name, + body, + mutability, + return_type, + type_ascription, + } = decl; + TyLetBinding { + name, + value: body, + mutability, + return_type, + type_ascription, } } } +impl TyLetBinding { + pub fn to_variable_decl(&self) -> TyVariableDecl { + TyVariableDecl { + name: self.name.clone(), + body: self.value.clone(), + mutability: self.mutability, + return_type: self.return_type, + type_ascription: self.type_ascription.clone(), + } + } +} diff --git a/sway-core/src/semantic_analysis/ast_node/statement/let_binding.rs b/sway-core/src/semantic_analysis/ast_node/statement/let_binding.rs new file mode 100644 index 00000000000..99abe10450f --- /dev/null +++ b/sway-core/src/semantic_analysis/ast_node/statement/let_binding.rs @@ -0,0 +1,52 @@ +use crate::{ + decl_engine::parsed_id::ParsedDeclId, + language::{ + parsed::{Declaration, VariableDeclaration}, + ty::{self, TyLetBinding, TyStatement, TyVariableDecl}, + }, + semantic_analysis::{ + symbol_collection_context::SymbolCollectionContext, TypeCheckContext, + }, + type_system::*, + Engines, +}; +use sway_error::handler::{ErrorEmitted, Handler}; +use sway_types::Spanned; + +impl TyLetBinding { + pub(crate) fn collect( + handler: &Handler, + engines: &Engines, + ctx: &mut SymbolCollectionContext, + decl_id: &ParsedDeclId, + ) -> Result<(), ErrorEmitted> { + TyVariableDecl::collect(handler, engines, ctx, decl_id) + } + + pub(crate) fn type_check( + handler: &Handler, + ctx: &mut TypeCheckContext, + var_decl: VariableDeclaration, + ) -> Result<(TyStatement, ty::TyDecl), ErrorEmitted> { + let span = var_decl.name.span(); + let name = var_decl.name.clone(); + let typed_var_decl = TyVariableDecl::type_check(handler, ctx.by_ref(), var_decl)?; + let ty_decl = ty::TyDecl::VariableDecl(Box::new(typed_var_decl.clone())); + ctx.insert_symbol(handler, name, ty_decl.clone())?; + let statement = TyStatement::Let(typed_var_decl.into()); + Ok((statement, ty_decl)) + } +} + +pub(crate) fn parsed_statement_from_decl( + engines: &Engines, + decl_id: &ParsedDeclId, +) -> VariableDeclaration { + engines.pe().get_variable(decl_id).as_ref().clone() +} + +pub(crate) fn declaration_from_statement(statement: &TyStatement) -> Option { + match statement { + TyStatement::Let(binding) => Some(binding.to_variable_decl()), + } +} diff --git a/sway-core/src/semantic_analysis/ast_node/statement/mod.rs b/sway-core/src/semantic_analysis/ast_node/statement/mod.rs index e69de29bb2d..b7c432d708c 100644 --- a/sway-core/src/semantic_analysis/ast_node/statement/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/statement/mod.rs @@ -0,0 +1,3 @@ +mod let_binding; + +pub(crate) use let_binding::*; From 013dc1a355f952932e5ac3e64b1aa8c550bb3722 Mon Sep 17 00:00:00 2001 From: tritao Date: Tue, 7 Oct 2025 21:48:10 +0100 Subject: [PATCH 3/6] Collapse `TySideEffectVariant `into `TySideEffect` enum. --- forc-plugins/forc-migrate/src/visiting/mod.rs | 32 ++++++++++------- .../language/ty/side_effect/side_effect.rs | 7 +--- .../src/semantic_analysis/ast_node/mod.rs | 24 ++++++------- sway-lsp/src/capabilities/document_symbol.rs | 13 +++---- sway-lsp/src/traverse/typed_tree.rs | 36 ++++++++----------- 5 files changed, 50 insertions(+), 62 deletions(-) diff --git a/forc-plugins/forc-migrate/src/visiting/mod.rs b/forc-plugins/forc-migrate/src/visiting/mod.rs index 3f493ac06ee..195aec19988 100644 --- a/forc-plugins/forc-migrate/src/visiting/mod.rs +++ b/forc-plugins/forc-migrate/src/visiting/mod.rs @@ -23,7 +23,7 @@ use sway_core::{ ty::{ TyAbiDecl, TyAstNodeContent, TyCodeBlock, TyDecl, TyExpression, TyExpressionVariant, TyFunctionDecl, TyImplSelfOrTrait, TyIntrinsicFunctionKind, TyModule, - TyReassignmentTarget, TySideEffect, TySideEffectVariant, TyStorageDecl, TyStorageField, + TyReassignmentTarget, TySideEffect, TyStorageDecl, TyStorageField, TyStructDecl, TyTraitDecl, TyTraitItem, TyUseStatement, TyVariableDecl, }, CallPath, @@ -369,9 +369,11 @@ impl __ProgramVisitor { .all_nodes .iter() .find_map(|node| match &node.content { - TyAstNodeContent::SideEffect(TySideEffect { - side_effect: TySideEffectVariant::UseStatement(ty_use), - }) if ty_use.span == item_use.span() => Some(ty_use), + TyAstNodeContent::SideEffect(TySideEffect::UseStatement(ty_use)) + if ty_use.span == item_use.span() => + { + Some(ty_use) + } _ => None, }) }); @@ -818,15 +820,19 @@ impl __ProgramVisitor { // TODO: Implement visiting `annotations`. match __ref([annotated.value]) { ItemKind::Use(item_use) => { - let ty_use = ty_node.map(|ty_node| - match &ty_node.content { - TyAstNodeContent::SideEffect(ty_side_effect) => match &ty_side_effect.side_effect { - TySideEffectVariant::UseStatement(ty_use) => Ok(ty_use), - _ => bail!(internal_error("`ItemKind::Use` must correspond to a `TySideEffectVariant::UseStatement`.")), - }, - _ => bail!(internal_error("`ItemKind::Use` must correspond to a `TyAstNodeContent::SideEffect`.")), - } - ).transpose()?; + let ty_use = ty_node + .map(|ty_node| match &ty_node.content { + TyAstNodeContent::SideEffect(TySideEffect::UseStatement(ty_use)) => { + Ok(ty_use) + } + TyAstNodeContent::SideEffect(_) => bail!(internal_error( + "`ItemKind::Use` must correspond to a `TySideEffect::UseStatement`.", + )), + _ => bail!(internal_error( + "`ItemKind::Use` must correspond to a `TyAstNodeContent::SideEffect`.", + )), + }) + .transpose()?; visitor.visit_use(ctx, item_use, ty_use, output)?; } diff --git a/sway-core/src/language/ty/side_effect/side_effect.rs b/sway-core/src/language/ty/side_effect/side_effect.rs index 9e8e672c5fa..444c320f00c 100644 --- a/sway-core/src/language/ty/side_effect/side_effect.rs +++ b/sway-core/src/language/ty/side_effect/side_effect.rs @@ -2,12 +2,7 @@ use super::{TyIncludeStatement, TyUseStatement}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TySideEffect { - pub side_effect: TySideEffectVariant, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum TySideEffectVariant { +pub enum TySideEffect { IncludeStatement(TyIncludeStatement), UseStatement(TyUseStatement), } diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 81262068cb6..0e5093cb9b3 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -56,26 +56,24 @@ impl ty::TyAstNode { content: match node.content.clone() { AstNodeContent::UseStatement(stmt) => { handle_use_statement(&mut ctx, &stmt, handler); - ty::TyAstNodeContent::SideEffect(ty::TySideEffect { - side_effect: ty::TySideEffectVariant::UseStatement(ty::TyUseStatement { + ty::TyAstNodeContent::SideEffect(ty::TySideEffect::UseStatement( + ty::TyUseStatement { alias: stmt.alias, call_path: stmt.call_path, span: stmt.span, is_relative_to_package_root: stmt.is_relative_to_package_root, import_type: stmt.import_type, - }), - }) + }, + )) } AstNodeContent::IncludeStatement(i) => { - ty::TyAstNodeContent::SideEffect(ty::TySideEffect { - side_effect: ty::TySideEffectVariant::IncludeStatement( - ty::TyIncludeStatement { - mod_name: i.mod_name, - span: i.span, - visibility: i.visibility, - }, - ), - }) + ty::TyAstNodeContent::SideEffect(ty::TySideEffect::IncludeStatement( + ty::TyIncludeStatement { + mod_name: i.mod_name, + span: i.span, + visibility: i.visibility, + }, + )) } AstNodeContent::Declaration(decl) => ty::TyAstNodeContent::Declaration( ty::TyDecl::type_check(handler, &mut ctx, decl)?, diff --git a/sway-lsp/src/capabilities/document_symbol.rs b/sway-lsp/src/capabilities/document_symbol.rs index 40b8f5f55f1..820db71f0e2 100644 --- a/sway-lsp/src/capabilities/document_symbol.rs +++ b/sway-lsp/src/capabilities/document_symbol.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use sway_core::{ language::ty::{ TyAbiDecl, TyAstNodeContent, TyConstantDecl, TyDecl, TyEnumDecl, TyFunctionDecl, - TyFunctionParameter, TyIncludeStatement, TyProgram, TySideEffectVariant, TyStorageDecl, + TyFunctionParameter, TyIncludeStatement, TyProgram, TySideEffect, TyStorageDecl, TyStructDecl, TyTraitInterfaceItem, TyTraitItem, TyTraitType, }, Engines, GenericArgument, @@ -51,15 +51,10 @@ pub fn to_document_symbols( .flatten() .filter_map(|node| { match &node.content { - TyAstNodeContent::SideEffect(side_effect) => { - if let TySideEffectVariant::IncludeStatement(include_statement) = - &side_effect.side_effect - { - Some(build_include_symbol(include_statement)) - } else { - None - } + TyAstNodeContent::SideEffect(TySideEffect::IncludeStatement(include_statement)) => { + Some(build_include_symbol(include_statement)) } + TyAstNodeContent::SideEffect(_) => None, TyAstNodeContent::Declaration(decl) => match decl { TyDecl::TypeAliasDecl(decl) => { let type_alias_decl = engines.de().get_type_alias(&decl.decl_id); diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index a2ae429f34f..9e828f950ba 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -99,19 +99,13 @@ impl Parse for ty::TyDecl { impl Parse for ty::TySideEffect { fn parse(&self, ctx: &ParseContext) { - use ty::TySideEffectVariant::{IncludeStatement, UseStatement}; - match &self.side_effect { - UseStatement( - use_statement @ ty::TyUseStatement { - call_path, - span: _, - import_type, - alias, - is_relative_to_package_root, - }, - ) => { - let full_path = - mod_path_to_full_path(call_path, *is_relative_to_package_root, ctx.namespace); + match self { + ty::TySideEffect::UseStatement(use_statement) => { + let full_path = mod_path_to_full_path( + &use_statement.call_path, + use_statement.is_relative_to_package_root, + ctx.namespace, + ); for (mod_path, ident) in iter_prefixes(&full_path).zip(&full_path) { if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( @@ -127,9 +121,10 @@ impl Parse for ty::TySideEffect { } } } - match &import_type { + match &use_statement.import_type { ImportType::Item(item) => { - if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(item)) + if let Some(mut token) = + ctx.tokens.try_get_mut_with_retry(&ctx.ident(item)) { token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( use_statement.clone(), @@ -148,7 +143,6 @@ impl Parse for ty::TySideEffect { decl.expect_typed_ref().get_decl_ident(ctx.engines) }) { - // Update the symbol kind to match the declarations symbol kind if let Some(decl) = ctx.tokens.try_get(&ctx.ident(&decl_ident)).try_unwrap() { @@ -158,10 +152,10 @@ impl Parse for ty::TySideEffect { } token.kind = symbol_kind.clone(); token.type_def.clone_from(&type_def); - // the alias should take on the same symbol kind and type definition - if let Some(alias) = alias { - if let Some(mut token) = - ctx.tokens.try_get_mut_with_retry(&ctx.ident(alias)) + if let Some(alias) = &use_statement.alias { + if let Some(mut token) = ctx + .tokens + .try_get_mut_with_retry(&ctx.ident(alias)) { token.ast_node = TokenAstNode::Typed( TypedAstToken::TypedUseStatement(use_statement.clone()), @@ -192,7 +186,7 @@ impl Parse for ty::TySideEffect { ImportType::Star => {} } } - IncludeStatement( + ty::TySideEffect::IncludeStatement( include_statement @ ty::TyIncludeStatement { span: _, mod_name, From 9507034ffc833862ee019cabbc4a6714678408f8 Mon Sep 17 00:00:00 2001 From: tritao Date: Tue, 7 Oct 2025 22:10:10 +0100 Subject: [PATCH 4/6] Merge `TySideEffect` into `TyStatement`. --- forc-plugins/forc-migrate/src/visiting/mod.rs | 14 +- .../analyze_return_paths.rs | 4 +- .../dead_code_analysis.rs | 12 +- sway-core/src/ir_generation/const_eval.rs | 8 +- sway-core/src/ir_generation/function.rs | 2 +- sway-core/src/language/ty/ast_node.rs | 23 +- sway-core/src/language/ty/mod.rs | 2 - .../ty/side_effect/include_statement.rs | 16 -- sway-core/src/language/ty/side_effect/mod.rs | 8 - .../language/ty/side_effect/side_effect.rs | 8 - .../language/ty/side_effect/use_statement.rs | 27 --- sway-core/src/language/ty/statement/mod.rs | 54 ++++- .../src/semantic_analysis/ast_node/mod.rs | 32 ++- .../semantic_analysis/cei_pattern_analysis.rs | 8 +- sway-lsp/src/capabilities/document_symbol.rs | 6 +- sway-lsp/src/traverse/typed_tree.rs | 228 +++++++++--------- sway-lsp/src/utils/debug.rs | 1 - 17 files changed, 201 insertions(+), 252 deletions(-) delete mode 100644 sway-core/src/language/ty/side_effect/include_statement.rs delete mode 100644 sway-core/src/language/ty/side_effect/mod.rs delete mode 100644 sway-core/src/language/ty/side_effect/side_effect.rs delete mode 100644 sway-core/src/language/ty/side_effect/use_statement.rs diff --git a/forc-plugins/forc-migrate/src/visiting/mod.rs b/forc-plugins/forc-migrate/src/visiting/mod.rs index 195aec19988..bba2c5683c0 100644 --- a/forc-plugins/forc-migrate/src/visiting/mod.rs +++ b/forc-plugins/forc-migrate/src/visiting/mod.rs @@ -23,8 +23,8 @@ use sway_core::{ ty::{ TyAbiDecl, TyAstNodeContent, TyCodeBlock, TyDecl, TyExpression, TyExpressionVariant, TyFunctionDecl, TyImplSelfOrTrait, TyIntrinsicFunctionKind, TyModule, - TyReassignmentTarget, TySideEffect, TyStorageDecl, TyStorageField, - TyStructDecl, TyTraitDecl, TyTraitItem, TyUseStatement, TyVariableDecl, + TyReassignmentTarget, TyStatement, TyStorageDecl, TyStorageField, TyStructDecl, + TyTraitDecl, TyTraitItem, TyUseStatement, TyVariableDecl, }, CallPath, }, @@ -369,7 +369,7 @@ impl __ProgramVisitor { .all_nodes .iter() .find_map(|node| match &node.content { - TyAstNodeContent::SideEffect(TySideEffect::UseStatement(ty_use)) + TyAstNodeContent::Statement(TyStatement::Use(ty_use)) if ty_use.span == item_use.span() => { Some(ty_use) @@ -822,14 +822,14 @@ impl __ProgramVisitor { ItemKind::Use(item_use) => { let ty_use = ty_node .map(|ty_node| match &ty_node.content { - TyAstNodeContent::SideEffect(TySideEffect::UseStatement(ty_use)) => { + TyAstNodeContent::Statement(TyStatement::Use(ty_use)) => { Ok(ty_use) } - TyAstNodeContent::SideEffect(_) => bail!(internal_error( - "`ItemKind::Use` must correspond to a `TySideEffect::UseStatement`.", + TyAstNodeContent::Statement(_) => bail!(internal_error( + "`ItemKind::Use` must correspond to a `TyStatement::Use`.", )), _ => bail!(internal_error( - "`ItemKind::Use` must correspond to a `TyAstNodeContent::SideEffect`.", + "`ItemKind::Use` must correspond to a `TyAstNodeContent::Statement`.", )), }) .transpose()?; diff --git a/sway-core/src/control_flow_analysis/analyze_return_paths.rs b/sway-core/src/control_flow_analysis/analyze_return_paths.rs index e6fb960fd10..7987490f073 100644 --- a/sway-core/src/control_flow_analysis/analyze_return_paths.rs +++ b/sway-core/src/control_flow_analysis/analyze_return_paths.rs @@ -191,9 +191,7 @@ fn connect_node<'eng: 'cfg, 'cfg>( } Ok(NodeConnection::NextStep(Some(entry))) } - ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { - Ok(NodeConnection::NextStep(leaf_opt)) - } + ty::TyAstNodeContent::Statement(_) => Ok(NodeConnection::NextStep(leaf_opt)), ty::TyAstNodeContent::Declaration(decl) => Ok(NodeConnection::NextStep( connect_declaration(engines, node, decl, graph, leaf_opt)?, )), diff --git a/sway-core/src/control_flow_analysis/dead_code_analysis.rs b/sway-core/src/control_flow_analysis/dead_code_analysis.rs index 1250cd1b8e9..65051fd56e9 100644 --- a/sway-core/src/control_flow_analysis/dead_code_analysis.rs +++ b/sway-core/src/control_flow_analysis/dead_code_analysis.rs @@ -465,9 +465,7 @@ fn connect_node<'eng: 'cfg, 'cfg>( }, ) } - ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { - (leaves.to_vec(), exit_node) - } + ty::TyAstNodeContent::Statement(_) => (leaves.to_vec(), exit_node), ty::TyAstNodeContent::Declaration(decl) => { // all leaves connect to this node, then this node is the singular leaf let cfg_node: ControlFlowGraphNode = @@ -2438,7 +2436,7 @@ fn construct_dead_code_warning_from_node( .. } => return None, ty::TyAstNode { - content: ty::TyAstNodeContent::Statement(_), + content: ty::TyAstNodeContent::Statement(ty::TyStatement::Let(_)), .. } => return None, // We handle storage fields individually. There is no need to emit any warnings for the @@ -2462,9 +2460,7 @@ fn construct_dead_code_warning_from_node( // Otherwise, this is unreachable. ty::TyAstNode { span, - content: - ty::TyAstNodeContent::Expression(_) - | ty::TyAstNodeContent::SideEffect(_), + content: ty::TyAstNodeContent::Expression(_) | ty::TyAstNodeContent::Statement(_), } => CompileWarning { span: span.clone(), warning_content: Warning::UnreachableCode, @@ -2637,7 +2633,7 @@ fn allow_dead_code_ast_node(decl_engine: &DeclEngine, node: &ty::TyAstNode) -> b ty::TyDecl::StorageDecl { .. } => false, }, ty::TyAstNodeContent::Expression(_) => false, - ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => false, + ty::TyAstNodeContent::Statement(_) => false, ty::TyAstNodeContent::Error(_, _) => false, } } diff --git a/sway-core/src/ir_generation/const_eval.rs b/sway-core/src/ir_generation/const_eval.rs index eae88429412..7dce4bce626 100644 --- a/sway-core/src/ir_generation/const_eval.rs +++ b/sway-core/src/ir_generation/const_eval.rs @@ -875,11 +875,9 @@ fn const_eval_codeblock( } } }, - ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => { - Err(ConstEvalError::CannotBeEvaluatedToConst { - span: ast_node.span.clone(), - }) - } + ty::TyAstNodeContent::Statement(_) => Err(ConstEvalError::CannotBeEvaluatedToConst { + span: ast_node.span.clone(), + }), ty::TyAstNodeContent::Error(_, _) => Err(ConstEvalError::CannotBeEvaluatedToConst { span: ast_node.span.clone(), }), diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index 0c75fe5fc5e..db134f85c26 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -387,7 +387,7 @@ impl<'a> FnCompiler<'a> { ty::TyDecl::EnumVariantDecl { .. } => unexpected_decl("enum variant"), ty::TyDecl::TraitTypeDecl { .. } => unexpected_decl("trait type"), }, - ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::SideEffect(_) => Ok(None), + ty::TyAstNodeContent::Statement(_) => Ok(None), ty::TyAstNodeContent::Expression(te) => { match &te.expression { TyExpressionVariant::ImplicitReturn(exp) => self diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index 86c334c65b4..4953af39db7 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -55,7 +55,6 @@ impl DebugWithEngines for TyAstNode { Declaration(typed_decl) => DebugWithEngines::fmt(typed_decl, f, engines), Statement(stmt) => Debug::fmt(stmt, f), Expression(exp) => DebugWithEngines::fmt(exp, f, engines), - SideEffect(_) => f.write_str(""), Error(_, _) => f.write_str("error"), } } @@ -67,7 +66,7 @@ impl SubstTypes for TyAstNode { TyAstNodeContent::Declaration(ref mut decl) => decl.subst(ctx), TyAstNodeContent::Statement(ref mut statement) => statement.subst(ctx), TyAstNodeContent::Expression(ref mut expr) => expr.subst(ctx), - TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => HasChanges::No, + TyAstNodeContent::Error(_, _) => HasChanges::No, } } } @@ -90,7 +89,6 @@ impl ReplaceDecls for TyAstNode { TyAstNodeContent::Expression(ref mut expr) => { expr.replace_decls(decl_mapping, handler, ctx) } - TyAstNodeContent::SideEffect(_) => Ok(false), TyAstNodeContent::Error(_, _) => Ok(false), } } @@ -106,11 +104,11 @@ impl UpdateConstantExpression for TyAstNode { .value .update_constant_expression(engines, implementing_type); } + TyStatement::Use(_) | TyStatement::Include(_) => {} }, TyAstNodeContent::Expression(ref mut expr) => { expr.update_constant_expression(engines, implementing_type) } - TyAstNodeContent::SideEffect(_) => (), TyAstNodeContent::Error(_, _) => (), } } @@ -208,7 +206,6 @@ impl TyAstNode { TyAstNodeContent::Declaration(decl) => decl.visibility(decl_engine).is_public(), TyAstNodeContent::Expression(_) | TyAstNodeContent::Statement(_) - | TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => false, } } @@ -261,7 +258,6 @@ impl TyAstNode { (*type_engine.get(*return_type)).clone() } TyAstNodeContent::Statement(_) => TypeInfo::Tuple(Vec::new()), - TyAstNodeContent::SideEffect(_) => TypeInfo::Tuple(Vec::new()), TyAstNodeContent::Error(_, error) => TypeInfo::ErrorRecovery(*error), } } @@ -343,8 +339,9 @@ impl TyAstNode { .value .check_deprecated(engines, handler, allow_deprecated); } + TyStatement::Use(_) | TyStatement::Include(_) => {} }, - TyAstNodeContent::SideEffect(_) | TyAstNodeContent::Error(_, _) => {} + TyAstNodeContent::Error(_, _) => {} } } @@ -388,7 +385,7 @@ impl TyAstNode { | TyDecl::TypeAliasDecl(_) => {} }, TyAstNodeContent::Expression(_node) => {} - TyAstNodeContent::Statement(_) | TyAstNodeContent::SideEffect(_) => {} + TyAstNodeContent::Statement(_) => {} TyAstNodeContent::Error(_, _) => {} }; Ok(()) @@ -436,8 +433,6 @@ pub enum TyAstNodeContent { Declaration(TyDecl), Statement(TyStatement), Expression(TyExpression), - // a no-op node used for something that just issues a side effect, like an import statement. - SideEffect(TySideEffect), Error(Box<[Span]>, #[serde(skip)] ErrorEmitted), } @@ -448,7 +443,6 @@ impl PartialEqWithEngines for TyAstNodeContent { (Self::Declaration(x), Self::Declaration(y)) => x.eq(y, ctx), (Self::Statement(x), Self::Statement(y)) => x.eq(y, ctx), (Self::Expression(x), Self::Expression(y)) => x.eq(y, ctx), - (Self::SideEffect(_), Self::SideEffect(_)) => true, _ => false, } } @@ -468,9 +462,6 @@ impl HashWithEngines for TyAstNodeContent { Expression(exp) => { exp.hash(state, engines); } - SideEffect(effect) => { - effect.hash(state); - } Error(_, _) => {} } } @@ -486,7 +477,6 @@ impl TypeCheckAnalysis for TyAstNodeContent { TyAstNodeContent::Declaration(node) => node.type_check_analyze(handler, ctx)?, TyAstNodeContent::Statement(node) => node.type_check_analyze(handler, ctx)?, TyAstNodeContent::Expression(node) => node.type_check_analyze(handler, ctx)?, - TyAstNodeContent::SideEffect(_) => {} TyAstNodeContent::Error(_, _) => {} } Ok(()) @@ -503,7 +493,6 @@ impl TypeCheckFinalization for TyAstNodeContent { TyAstNodeContent::Declaration(node) => node.type_check_finalize(handler, ctx)?, TyAstNodeContent::Statement(node) => node.type_check_finalize(handler, ctx)?, TyAstNodeContent::Expression(node) => node.type_check_finalize(handler, ctx)?, - TyAstNodeContent::SideEffect(_) => {} TyAstNodeContent::Error(_, _) => {} } Ok(()) @@ -521,7 +510,6 @@ impl CollectTypesMetadata for TyAstNodeContent { Declaration(decl) => decl.collect_types_metadata(handler, ctx), Statement(stmt) => stmt.collect_types_metadata(handler, ctx), Expression(expr) => expr.collect_types_metadata(handler, ctx), - SideEffect(_) => Ok(vec![]), Error(_, _) => Ok(vec![]), } } @@ -533,7 +521,6 @@ impl GetDeclIdent for TyAstNodeContent { TyAstNodeContent::Declaration(decl) => decl.get_decl_ident(engines), TyAstNodeContent::Expression(_expr) => None, //expr.get_decl_ident(), TyAstNodeContent::Statement(_) => None, - TyAstNodeContent::SideEffect(_) => None, TyAstNodeContent::Error(_, _) => None, } } diff --git a/sway-core/src/language/ty/mod.rs b/sway-core/src/language/ty/mod.rs index 9d79eb9bf97..f0650aa1000 100644 --- a/sway-core/src/language/ty/mod.rs +++ b/sway-core/src/language/ty/mod.rs @@ -4,7 +4,6 @@ mod declaration; mod expression; mod module; mod program; -mod side_effect; mod statement; mod variable_mutability; @@ -14,6 +13,5 @@ pub use declaration::*; pub use expression::*; pub use module::*; pub use program::*; -pub use side_effect::*; pub use statement::*; pub use variable_mutability::*; diff --git a/sway-core/src/language/ty/side_effect/include_statement.rs b/sway-core/src/language/ty/side_effect/include_statement.rs deleted file mode 100644 index 666e5b63a58..00000000000 --- a/sway-core/src/language/ty/side_effect/include_statement.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::language::Visibility; -use serde::{Deserialize, Serialize}; -use sway_types::{ident::Ident, Span, Spanned}; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TyIncludeStatement { - pub span: Span, - pub visibility: Visibility, - pub mod_name: Ident, -} - -impl Spanned for TyIncludeStatement { - fn span(&self) -> Span { - self.span.clone() - } -} diff --git a/sway-core/src/language/ty/side_effect/mod.rs b/sway-core/src/language/ty/side_effect/mod.rs deleted file mode 100644 index e70b040de37..00000000000 --- a/sway-core/src/language/ty/side_effect/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod include_statement; -#[allow(clippy::module_inception)] -mod side_effect; -mod use_statement; - -pub use include_statement::*; -pub use side_effect::*; -pub use use_statement::*; diff --git a/sway-core/src/language/ty/side_effect/side_effect.rs b/sway-core/src/language/ty/side_effect/side_effect.rs deleted file mode 100644 index 444c320f00c..00000000000 --- a/sway-core/src/language/ty/side_effect/side_effect.rs +++ /dev/null @@ -1,8 +0,0 @@ -use super::{TyIncludeStatement, TyUseStatement}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum TySideEffect { - IncludeStatement(TyIncludeStatement), - UseStatement(TyUseStatement), -} diff --git a/sway-core/src/language/ty/side_effect/use_statement.rs b/sway-core/src/language/ty/side_effect/use_statement.rs deleted file mode 100644 index 9e1cfc554a3..00000000000 --- a/sway-core/src/language/ty/side_effect/use_statement.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::language::parsed; -use serde::{Deserialize, Serialize}; -use sway_types::{ident::Ident, Span, Spanned}; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TyUseStatement { - pub call_path: Vec, - pub span: Span, - pub import_type: parsed::ImportType, - // If `is_relative_to_package_root` is true, then this use statement is a path relative to the - // project root. For example, if the path is `::X::Y` and occurs in package `P`, then the path - // refers to the full path `P::X::Y`. - // If `is_relative_to_package_root` is false, then there are two options: - // - The path refers to a path relative to the current namespace. For example, if the path is - // `X::Y` and it occurs in a module whose path is `P::M`, then the path refers to the full - // path `P::M::X::Y`. - // - The path refers to a path in an external package. For example, the path `X::Y` refers to an - // entity `Y` in the external package `X`. - pub is_relative_to_package_root: bool, - pub alias: Option, -} - -impl Spanned for TyUseStatement { - fn span(&self) -> Span { - self.span.clone() - } -} diff --git a/sway-core/src/language/ty/statement/mod.rs b/sway-core/src/language/ty/statement/mod.rs index cd26ee9004a..fa311bef849 100644 --- a/sway-core/src/language/ty/statement/mod.rs +++ b/sway-core/src/language/ty/statement/mod.rs @@ -1,7 +1,7 @@ use crate::{ decl_engine::{DeclMapping, MaterializeConstGenerics, ReplaceDecls}, engine_threading::*, - language::ty::{TyExpression, TyVariableDecl, VariableMutability}, + language::{parsed, Visibility, ty::{TyExpression, TyVariableDecl}}, semantic_analysis::{ TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization, TypeCheckFinalizationContext, @@ -14,12 +14,51 @@ use ast_elements::type_parameter::ConstGenericExpr; use serde::{Deserialize, Serialize}; use std::hash::{Hash, Hasher}; use sway_error::handler::{ErrorEmitted, Handler}; -use sway_types::{Ident, Named, Span, Spanned}; +use sway_types::{ident::Ident as BaseIdent, Ident, Named, Span, Spanned}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct TyIncludeStatement { + pub span: Span, + pub visibility: Visibility, + pub mod_name: BaseIdent, +} + +impl Spanned for TyIncludeStatement { + fn span(&self) -> Span { + self.span.clone() + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct TyUseStatement { + pub call_path: Vec, + pub span: Span, + pub import_type: parsed::ImportType, + // If `is_relative_to_package_root` is true, then this use statement is a path relative to the + // project root. For example, if the path is `::X::Y` and occurs in package `P`, then the path + // refers to the full path `P::X::Y`. + // If `is_relative_to_package_root` is false, then there are two options: + // - The path refers to a path relative to the current namespace. For example, if the path is + // `X::Y` and it occurs in a module whose path is `P::M`, then the path refers to the full + // path `P::M::X::Y`. + // - The path refers to a path in an external package. For example, the path `X::Y` refers to an + // entity `Y` in the external package `X`. + pub is_relative_to_package_root: bool, + pub alias: Option, +} + +impl Spanned for TyUseStatement { + fn span(&self) -> Span { + self.span.clone() + } +} #[derive(Clone, Debug, Serialize, Deserialize)] #[allow(clippy::large_enum_variant)] pub enum TyStatement { Let(TyLetBinding), + Use(TyUseStatement), + Include(TyIncludeStatement), } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -48,6 +87,9 @@ impl PartialEqWithEngines for TyStatement { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { match (self, other) { (TyStatement::Let(lhs), TyStatement::Let(rhs)) => lhs.eq(rhs, ctx), + (TyStatement::Use(lhs), TyStatement::Use(rhs)) => lhs == rhs, + (TyStatement::Include(lhs), TyStatement::Include(rhs)) => lhs == rhs, + _ => false, } } } @@ -56,6 +98,8 @@ impl HashWithEngines for TyStatement { fn hash(&self, state: &mut H, engines: &Engines) { match self { TyStatement::Let(binding) => binding.hash(state, engines), + TyStatement::Use(stmt) => stmt.hash(state), + TyStatement::Include(stmt) => stmt.hash(state), } } } @@ -64,6 +108,7 @@ impl SubstTypes for TyStatement { fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { match self { TyStatement::Let(binding) => binding.subst(ctx), + TyStatement::Use(_) | TyStatement::Include(_) => HasChanges::No, } } } @@ -77,6 +122,7 @@ impl ReplaceDecls for TyStatement { ) -> Result { match self { TyStatement::Let(binding) => binding.value.replace_decls(decl_mapping, handler, ctx), + TyStatement::Use(_) | TyStatement::Include(_) => Ok(false), } } } @@ -89,6 +135,7 @@ impl TypeCheckAnalysis for TyStatement { ) -> Result<(), ErrorEmitted> { match self { TyStatement::Let(binding) => binding.value.type_check_analyze(handler, ctx)?, + TyStatement::Use(_) | TyStatement::Include(_) => {} } Ok(()) } @@ -102,6 +149,7 @@ impl TypeCheckFinalization for TyStatement { ) -> Result<(), ErrorEmitted> { match self { TyStatement::Let(binding) => binding.value.type_check_finalize(handler, ctx)?, + TyStatement::Use(_) | TyStatement::Include(_) => {} } Ok(()) } @@ -124,6 +172,7 @@ impl CollectTypesMetadata for TyStatement { ); Ok(metadata) } + TyStatement::Use(_) | TyStatement::Include(_) => Ok(vec![]), } } } @@ -160,6 +209,7 @@ impl MaterializeConstGenerics for TyStatement { } Ok(()) } + TyStatement::Use(_) | TyStatement::Include(_) => Ok(()), } } } diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 0e5093cb9b3..66de5d42280 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -56,25 +56,21 @@ impl ty::TyAstNode { content: match node.content.clone() { AstNodeContent::UseStatement(stmt) => { handle_use_statement(&mut ctx, &stmt, handler); - ty::TyAstNodeContent::SideEffect(ty::TySideEffect::UseStatement( - ty::TyUseStatement { - alias: stmt.alias, - call_path: stmt.call_path, - span: stmt.span, - is_relative_to_package_root: stmt.is_relative_to_package_root, - import_type: stmt.import_type, - }, - )) - } - AstNodeContent::IncludeStatement(i) => { - ty::TyAstNodeContent::SideEffect(ty::TySideEffect::IncludeStatement( - ty::TyIncludeStatement { - mod_name: i.mod_name, - span: i.span, - visibility: i.visibility, - }, - )) + ty::TyAstNodeContent::Statement(ty::TyStatement::Use(ty::TyUseStatement { + alias: stmt.alias, + call_path: stmt.call_path, + span: stmt.span, + is_relative_to_package_root: stmt.is_relative_to_package_root, + import_type: stmt.import_type, + })) } + AstNodeContent::IncludeStatement(i) => ty::TyAstNodeContent::Statement( + ty::TyStatement::Include(ty::TyIncludeStatement { + mod_name: i.mod_name, + span: i.span, + visibility: i.visibility, + }), + ), AstNodeContent::Declaration(decl) => ty::TyAstNodeContent::Declaration( ty::TyDecl::type_check(handler, &mut ctx, decl)?, ), diff --git a/sway-core/src/semantic_analysis/cei_pattern_analysis.rs b/sway-core/src/semantic_analysis/cei_pattern_analysis.rs index 3d4e63bfe6a..a4a77604b93 100644 --- a/sway-core/src/semantic_analysis/cei_pattern_analysis.rs +++ b/sway-core/src/semantic_analysis/cei_pattern_analysis.rs @@ -193,9 +193,7 @@ fn analyze_code_block_entry( ty::TyAstNodeContent::Expression(expr) => { analyze_expression(engines, expr, block_name, warnings) } - ty::TyAstNodeContent::Statement(_) - | ty::TyAstNodeContent::SideEffect(_) - | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), } } @@ -497,9 +495,7 @@ fn effects_of_codeblock_entry(engines: &Engines, ast_node: &ty::TyAstNode) -> Ha match &ast_node.content { ty::TyAstNodeContent::Declaration(decl) => effects_of_codeblock_decl(engines, decl), ty::TyAstNodeContent::Expression(expr) => effects_of_expression(engines, expr), - ty::TyAstNodeContent::Statement(_) - | ty::TyAstNodeContent::SideEffect(_) - | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), + ty::TyAstNodeContent::Statement(_) | ty::TyAstNodeContent::Error(_, _) => HashSet::new(), } } diff --git a/sway-lsp/src/capabilities/document_symbol.rs b/sway-lsp/src/capabilities/document_symbol.rs index 820db71f0e2..3b1ea618bb9 100644 --- a/sway-lsp/src/capabilities/document_symbol.rs +++ b/sway-lsp/src/capabilities/document_symbol.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use sway_core::{ language::ty::{ TyAbiDecl, TyAstNodeContent, TyConstantDecl, TyDecl, TyEnumDecl, TyFunctionDecl, - TyFunctionParameter, TyIncludeStatement, TyProgram, TySideEffect, TyStorageDecl, + TyFunctionParameter, TyIncludeStatement, TyProgram, TyStatement, TyStorageDecl, TyStructDecl, TyTraitInterfaceItem, TyTraitItem, TyTraitType, }, Engines, GenericArgument, @@ -51,10 +51,10 @@ pub fn to_document_symbols( .flatten() .filter_map(|node| { match &node.content { - TyAstNodeContent::SideEffect(TySideEffect::IncludeStatement(include_statement)) => { + TyAstNodeContent::Statement(TyStatement::Include(include_statement)) => { Some(build_include_symbol(include_statement)) } - TyAstNodeContent::SideEffect(_) => None, + TyAstNodeContent::Statement(_) => None, TyAstNodeContent::Declaration(decl) => match decl { TyDecl::TypeAliasDecl(decl) => { let type_alias_decl = engines.de().get_type_alias(&decl.decl_id); diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index 9e828f950ba..dd1940d7c5d 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -68,7 +68,6 @@ impl Parse for ty::TyAstNode { ty::TyAstNodeContent::Declaration(declaration) => declaration.parse(ctx), ty::TyAstNodeContent::Statement(statement) => statement.parse(ctx), ty::TyAstNodeContent::Expression(expression) => expression.parse(ctx), - ty::TyAstNodeContent::SideEffect(side_effect) => side_effect.parse(ctx), ty::TyAstNodeContent::Error(_, _) => {} }; } @@ -97,120 +96,6 @@ impl Parse for ty::TyDecl { } } -impl Parse for ty::TySideEffect { - fn parse(&self, ctx: &ParseContext) { - match self { - ty::TySideEffect::UseStatement(use_statement) => { - let full_path = mod_path_to_full_path( - &use_statement.call_path, - use_statement.is_relative_to_package_root, - ctx.namespace, - ); - for (mod_path, ident) in iter_prefixes(&full_path).zip(&full_path) { - if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( - use_statement.clone(), - )); - - if let Some(span) = ctx - .namespace - .module_from_absolute_path(mod_path) - .and_then(|tgt_submod| tgt_submod.span().clone()) - { - token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); - } - } - } - match &use_statement.import_type { - ImportType::Item(item) => { - if let Some(mut token) = - ctx.tokens.try_get_mut_with_retry(&ctx.ident(item)) - { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( - use_statement.clone(), - )); - let mut symbol_kind = SymbolKind::Unknown; - let mut type_def = None; - if let Some(decl_ident) = ctx - .namespace - .module_from_absolute_path(&full_path) - .and_then(|module| { - module - .resolve_symbol(&Handler::default(), ctx.engines, item) - .ok() - }) - .and_then(|(decl, _)| { - decl.expect_typed_ref().get_decl_ident(ctx.engines) - }) - { - if let Some(decl) = - ctx.tokens.try_get(&ctx.ident(&decl_ident)).try_unwrap() - { - symbol_kind = decl.value().kind.clone(); - } - type_def = Some(TypeDefinition::Ident(decl_ident)); - } - token.kind = symbol_kind.clone(); - token.type_def.clone_from(&type_def); - if let Some(alias) = &use_statement.alias { - if let Some(mut token) = ctx - .tokens - .try_get_mut_with_retry(&ctx.ident(alias)) - { - token.ast_node = TokenAstNode::Typed( - TypedAstToken::TypedUseStatement(use_statement.clone()), - ); - token.kind = symbol_kind; - token.type_def = type_def; - } - } - } - } - ImportType::SelfImport(span) => { - if let Some(mut token) = ctx - .tokens - .try_get_mut_with_retry(&ctx.ident(&Ident::new(span.clone()))) - { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( - use_statement.clone(), - )); - if let Some(span) = ctx - .namespace - .module_from_absolute_path(&full_path) - .and_then(|tgt_submod| tgt_submod.span().clone()) - { - token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); - } - } - } - ImportType::Star => {} - } - } - ty::TySideEffect::IncludeStatement( - include_statement @ ty::TyIncludeStatement { - span: _, - mod_name, - visibility: _, - }, - ) => { - if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(mod_name)) { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedIncludeStatement( - include_statement.clone(), - )); - if let Some(span) = ctx - .namespace - .root_module() - .submodule(std::slice::from_ref(mod_name)) - .and_then(|tgt_submod| tgt_submod.span().clone()) - { - token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); - } - } - } - } - } -} - impl Parse for ty::TyExpression { fn parse(&self, ctx: &ParseContext) { match &self.expression { @@ -661,11 +546,11 @@ impl Parse for ty::TyStatement { fn parse(&self, ctx: &ParseContext) { match self { ty::TyStatement::Let(binding) => { - if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(&binding.name)) + if let Some(mut token) = + ctx.tokens.try_get_mut_with_retry(&ctx.ident(&binding.name)) { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedStatement( - self.clone(), - )); + token.ast_node = + TokenAstNode::Typed(TypedAstToken::TypedStatement(self.clone())); token.type_def = Some(TypeDefinition::Ident(binding.name.clone())); } if let Some(call_path_tree) = &binding.type_ascription.call_path_tree() { @@ -673,6 +558,111 @@ impl Parse for ty::TyStatement { } binding.value.parse(ctx); } + ty::TyStatement::Use(use_statement) => { + let full_path = mod_path_to_full_path( + &use_statement.call_path, + use_statement.is_relative_to_package_root, + ctx.namespace, + ); + for (mod_path, ident) in iter_prefixes(&full_path).zip(&full_path) { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(ident)) { + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( + use_statement.clone(), + )); + + if let Some(span) = ctx + .namespace + .module_from_absolute_path(mod_path) + .and_then(|tgt_submod| tgt_submod.span().clone()) + { + token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); + } + } + } + match &use_statement.import_type { + ImportType::Item(item) => { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(item)) + { + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( + use_statement.clone(), + )); + let mut symbol_kind = SymbolKind::Unknown; + let mut type_def = None; + if let Some(decl_ident) = ctx + .namespace + .module_from_absolute_path(&full_path) + .and_then(|module| { + module + .resolve_symbol(&Handler::default(), ctx.engines, item) + .ok() + }) + .and_then(|(decl, _)| { + decl.expect_typed_ref().get_decl_ident(ctx.engines) + }) + { + if let Some(decl) = + ctx.tokens.try_get(&ctx.ident(&decl_ident)).try_unwrap() + { + symbol_kind = decl.value().kind.clone(); + } + type_def = Some(TypeDefinition::Ident(decl_ident)); + } + token.kind = symbol_kind.clone(); + token.type_def.clone_from(&type_def); + if let Some(alias) = &use_statement.alias { + if let Some(mut token) = + ctx.tokens.try_get_mut_with_retry(&ctx.ident(alias)) + { + token.ast_node = TokenAstNode::Typed( + TypedAstToken::TypedUseStatement(use_statement.clone()), + ); + token.kind = symbol_kind; + token.type_def = type_def; + } + } + } + } + ImportType::SelfImport(span) => { + if let Some(mut token) = ctx + .tokens + .try_get_mut_with_retry(&ctx.ident(&Ident::new(span.clone()))) + { + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedUseStatement( + use_statement.clone(), + )); + if let Some(span) = ctx + .namespace + .module_from_absolute_path(&full_path) + .and_then(|tgt_submod| tgt_submod.span().clone()) + { + token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); + } + } + } + ImportType::Star => {} + } + } + ty::TyStatement::Include( + include_statement @ ty::TyIncludeStatement { + span: _, + mod_name, + visibility: _, + }, + ) => { + if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(mod_name)) { + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedIncludeStatement( + include_statement.clone(), + )); + if let Some(span) = ctx + .namespace + .root_module() + .submodule(std::slice::from_ref(mod_name)) + .and_then(|tgt_submod| tgt_submod.span().clone()) + { + token.type_def = Some(TypeDefinition::Ident(Ident::new(span))); + } + } + } } } } diff --git a/sway-lsp/src/utils/debug.rs b/sway-lsp/src/utils/debug.rs index bbc448c4d69..9ab4a7e7dac 100644 --- a/sway-lsp/src/utils/debug.rs +++ b/sway-lsp/src/utils/debug.rs @@ -115,7 +115,6 @@ pub(crate) fn print_decl_engine_types( format!("{expression:#?}") } ty::TyAstNodeContent::Statement(statement) => format!("{statement:#?}"), - ty::TyAstNodeContent::SideEffect(side_effect) => format!("{side_effect:#?}"), ty::TyAstNodeContent::Error(_, _) => "error".to_string(), }) .fold(String::new(), |output, s| format!("{output}{s}\n")) From b9c5d5e8c049f9a9748b1c081b4c9ac890540c6f Mon Sep 17 00:00:00 2001 From: tritao Date: Tue, 7 Oct 2025 22:22:29 +0100 Subject: [PATCH 5/6] Rename `IncludeStatement` to `ModStatement`. --- sway-core/src/language/parsed/mod.rs | 8 ++-- ...{include_statement.rs => mod_statement.rs} | 2 +- sway-core/src/language/ty/ast_node.rs | 4 +- sway-core/src/language/ty/statement/mod.rs | 24 +++++----- .../src/semantic_analysis/ast_node/mod.rs | 6 +-- sway-core/src/semantic_analysis/module.rs | 2 +- .../semantic_analysis/node_dependencies.rs | 10 ++-- .../src/semantic_analysis/symbol_resolve.rs | 2 +- .../to_parsed_lang/convert_parse_tree.rs | 8 ++-- .../code_actions/diagnostic/auto_import.rs | 46 +++++++++---------- sway-lsp/src/capabilities/document_symbol.rs | 10 ++-- sway-lsp/src/core/token.rs | 6 +-- sway-lsp/src/traverse/parsed_tree.rs | 8 ++-- sway-lsp/src/traverse/typed_tree.rs | 8 ++-- 14 files changed, 72 insertions(+), 72 deletions(-) rename sway-core/src/language/parsed/{include_statement.rs => mod_statement.rs} (90%) diff --git a/sway-core/src/language/parsed/mod.rs b/sway-core/src/language/parsed/mod.rs index bf19ed600c3..45f8203c6ec 100644 --- a/sway-core/src/language/parsed/mod.rs +++ b/sway-core/src/language/parsed/mod.rs @@ -2,7 +2,7 @@ mod code_block; pub mod declaration; mod expression; -mod include_statement; +mod mod_statement; mod module; mod program; mod use_statement; @@ -10,7 +10,7 @@ mod use_statement; pub use code_block::*; pub use declaration::*; pub use expression::*; -pub use include_statement::IncludeStatement; +pub use mod_statement::ModStatement; pub use module::{ModuleEvaluationOrder, ParseModule, ParseSubmodule}; pub use program::{ParseProgram, TreeType}; use sway_error::handler::ErrorEmitted; @@ -62,7 +62,7 @@ pub enum AstNodeContent { /// Any type of expression, of which there are quite a few. See [Expression] for more details. Expression(Expression), /// A statement of the form `mod foo::bar;` which imports/includes another source file. - IncludeStatement(IncludeStatement), + ModStatement(ModStatement), /// A malformed statement. /// /// Used for parser recovery when we cannot form a more specific node. @@ -80,7 +80,7 @@ impl PartialEqWithEngines for AstNodeContent { lhs.eq(rhs, ctx) } (AstNodeContent::Expression(lhs), AstNodeContent::Expression(rhs)) => lhs.eq(rhs, ctx), - (AstNodeContent::IncludeStatement(lhs), AstNodeContent::IncludeStatement(rhs)) => { + (AstNodeContent::ModStatement(lhs), AstNodeContent::ModStatement(rhs)) => { lhs.eq(rhs) } (AstNodeContent::Error(lhs, ..), AstNodeContent::Error(rhs, ..)) => lhs.eq(rhs), diff --git a/sway-core/src/language/parsed/include_statement.rs b/sway-core/src/language/parsed/mod_statement.rs similarity index 90% rename from sway-core/src/language/parsed/include_statement.rs rename to sway-core/src/language/parsed/mod_statement.rs index c52ce3d3269..2925723b050 100644 --- a/sway-core/src/language/parsed/include_statement.rs +++ b/sway-core/src/language/parsed/mod_statement.rs @@ -3,7 +3,7 @@ use sway_types::{span::Span, Ident}; use crate::language::Visibility; #[derive(Clone, Debug, PartialEq)] -pub struct IncludeStatement { +pub struct ModStatement { // this span may be used for errors in the future, although it is not right now. pub span: Span, pub mod_name: Ident, diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index 4953af39db7..398cc803a5c 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -104,7 +104,7 @@ impl UpdateConstantExpression for TyAstNode { .value .update_constant_expression(engines, implementing_type); } - TyStatement::Use(_) | TyStatement::Include(_) => {} + TyStatement::Use(_) | TyStatement::Mod(_) => {} }, TyAstNodeContent::Expression(ref mut expr) => { expr.update_constant_expression(engines, implementing_type) @@ -339,7 +339,7 @@ impl TyAstNode { .value .check_deprecated(engines, handler, allow_deprecated); } - TyStatement::Use(_) | TyStatement::Include(_) => {} + TyStatement::Use(_) | TyStatement::Mod(_) => {} }, TyAstNodeContent::Error(_, _) => {} } diff --git a/sway-core/src/language/ty/statement/mod.rs b/sway-core/src/language/ty/statement/mod.rs index fa311bef849..2c6f9d3c0b8 100644 --- a/sway-core/src/language/ty/statement/mod.rs +++ b/sway-core/src/language/ty/statement/mod.rs @@ -1,7 +1,7 @@ use crate::{ decl_engine::{DeclMapping, MaterializeConstGenerics, ReplaceDecls}, engine_threading::*, - language::{parsed, Visibility, ty::{TyExpression, TyVariableDecl}}, + language::{parsed, Visibility, ty::{TyExpression, TyVariableDecl, VariableMutability}}, semantic_analysis::{ TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization, TypeCheckFinalizationContext, @@ -17,13 +17,13 @@ use sway_error::handler::{ErrorEmitted, Handler}; use sway_types::{ident::Ident as BaseIdent, Ident, Named, Span, Spanned}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TyIncludeStatement { +pub struct TyModStatement { pub span: Span, pub visibility: Visibility, pub mod_name: BaseIdent, } -impl Spanned for TyIncludeStatement { +impl Spanned for TyModStatement { fn span(&self) -> Span { self.span.clone() } @@ -58,7 +58,7 @@ impl Spanned for TyUseStatement { pub enum TyStatement { Let(TyLetBinding), Use(TyUseStatement), - Include(TyIncludeStatement), + Mod(TyModStatement), } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -88,7 +88,7 @@ impl PartialEqWithEngines for TyStatement { match (self, other) { (TyStatement::Let(lhs), TyStatement::Let(rhs)) => lhs.eq(rhs, ctx), (TyStatement::Use(lhs), TyStatement::Use(rhs)) => lhs == rhs, - (TyStatement::Include(lhs), TyStatement::Include(rhs)) => lhs == rhs, + (TyStatement::Mod(lhs), TyStatement::Mod(rhs)) => lhs == rhs, _ => false, } } @@ -99,7 +99,7 @@ impl HashWithEngines for TyStatement { match self { TyStatement::Let(binding) => binding.hash(state, engines), TyStatement::Use(stmt) => stmt.hash(state), - TyStatement::Include(stmt) => stmt.hash(state), + TyStatement::Mod(stmt) => stmt.hash(state), } } } @@ -108,7 +108,7 @@ impl SubstTypes for TyStatement { fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { match self { TyStatement::Let(binding) => binding.subst(ctx), - TyStatement::Use(_) | TyStatement::Include(_) => HasChanges::No, + TyStatement::Use(_) | TyStatement::Mod(_) => HasChanges::No, } } } @@ -122,7 +122,7 @@ impl ReplaceDecls for TyStatement { ) -> Result { match self { TyStatement::Let(binding) => binding.value.replace_decls(decl_mapping, handler, ctx), - TyStatement::Use(_) | TyStatement::Include(_) => Ok(false), + TyStatement::Use(_) | TyStatement::Mod(_) => Ok(false), } } } @@ -135,7 +135,7 @@ impl TypeCheckAnalysis for TyStatement { ) -> Result<(), ErrorEmitted> { match self { TyStatement::Let(binding) => binding.value.type_check_analyze(handler, ctx)?, - TyStatement::Use(_) | TyStatement::Include(_) => {} + TyStatement::Use(_) | TyStatement::Mod(_) => {} } Ok(()) } @@ -149,7 +149,7 @@ impl TypeCheckFinalization for TyStatement { ) -> Result<(), ErrorEmitted> { match self { TyStatement::Let(binding) => binding.value.type_check_finalize(handler, ctx)?, - TyStatement::Use(_) | TyStatement::Include(_) => {} + TyStatement::Use(_) | TyStatement::Mod(_) => {} } Ok(()) } @@ -172,7 +172,7 @@ impl CollectTypesMetadata for TyStatement { ); Ok(metadata) } - TyStatement::Use(_) | TyStatement::Include(_) => Ok(vec![]), + TyStatement::Use(_) | TyStatement::Mod(_) => Ok(vec![]), } } } @@ -209,7 +209,7 @@ impl MaterializeConstGenerics for TyStatement { } Ok(()) } - TyStatement::Use(_) | TyStatement::Include(_) => Ok(()), + TyStatement::Use(_) | TyStatement::Mod(_) => Ok(()), } } } diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 66de5d42280..6793aab6723 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -32,7 +32,7 @@ impl ty::TyAstNode { AstNodeContent::UseStatement(stmt) => { collect_use_statement(handler, engines, ctx, &stmt); } - AstNodeContent::IncludeStatement(_i) => (), + AstNodeContent::ModStatement(_i) => (), AstNodeContent::Declaration(decl) => ty::TyDecl::collect(handler, engines, ctx, decl)?, AstNodeContent::Expression(expr) => { ty::TyExpression::collect(handler, engines, ctx, &expr)? @@ -64,8 +64,8 @@ impl ty::TyAstNode { import_type: stmt.import_type, })) } - AstNodeContent::IncludeStatement(i) => ty::TyAstNodeContent::Statement( - ty::TyStatement::Include(ty::TyIncludeStatement { + AstNodeContent::ModStatement(i) => ty::TyAstNodeContent::Statement( + ty::TyStatement::Mod(ty::TyModStatement { mod_name: i.mod_name, span: i.span, visibility: i.visibility, diff --git a/sway-core/src/semantic_analysis/module.rs b/sway-core/src/semantic_analysis/module.rs index fa635a57cd7..e728fdae7df 100644 --- a/sway-core/src/semantic_analysis/module.rs +++ b/sway-core/src/semantic_analysis/module.rs @@ -832,7 +832,7 @@ impl ty::TySubmodule { } AstNodeContent::Declaration(_) => {} AstNodeContent::Expression(_) => {} - AstNodeContent::IncludeStatement(_) => {} + AstNodeContent::ModStatement(_) => {} AstNodeContent::Error(_, _) => {} } } diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 8e34d58d685..3c8a8318855 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -268,16 +268,16 @@ fn depends_on( ) -> bool { match (&dependant_node.content, &dependee_node.content) { // Include statements first. - (AstNodeContent::IncludeStatement(_), AstNodeContent::IncludeStatement(_)) => false, - (_, AstNodeContent::IncludeStatement(_)) => true, + (AstNodeContent::ModStatement(_), AstNodeContent::ModStatement(_)) => false, + (_, AstNodeContent::ModStatement(_)) => true, // Use statements next. - (AstNodeContent::IncludeStatement(_), AstNodeContent::UseStatement(_)) => false, + (AstNodeContent::ModStatement(_), AstNodeContent::UseStatement(_)) => false, (AstNodeContent::UseStatement(_), AstNodeContent::UseStatement(_)) => false, (_, AstNodeContent::UseStatement(_)) => true, // Then declarations, ordered using the dependencies list. - (AstNodeContent::IncludeStatement(_), AstNodeContent::Declaration(_)) => false, + (AstNodeContent::ModStatement(_), AstNodeContent::Declaration(_)) => false, (AstNodeContent::UseStatement(_), AstNodeContent::Declaration(_)) => false, (AstNodeContent::Declaration(dependant), AstNodeContent::Declaration(dependee)) => { match (decl_name(engines, dependant), decl_name(engines, dependee)) { @@ -769,7 +769,7 @@ impl Dependencies { // No deps from these guys. AstNodeContent::UseStatement(_) - | AstNodeContent::IncludeStatement(_) + | AstNodeContent::ModStatement(_) | AstNodeContent::Error(_, _) => self, } } diff --git a/sway-core/src/semantic_analysis/symbol_resolve.rs b/sway-core/src/semantic_analysis/symbol_resolve.rs index 8dd038066de..b5221d56504 100644 --- a/sway-core/src/semantic_analysis/symbol_resolve.rs +++ b/sway-core/src/semantic_analysis/symbol_resolve.rs @@ -64,7 +64,7 @@ impl ResolveSymbols for AstNode { AstNodeContent::UseStatement(_) => {} AstNodeContent::Declaration(decl) => decl.resolve_symbols(handler, ctx), AstNodeContent::Expression(expr) => expr.resolve_symbols(handler, ctx), - AstNodeContent::IncludeStatement(_) => {} + AstNodeContent::ModStatement(_) => {} AstNodeContent::Error(_, _) => {} } } diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 8ef4662e9ef..1564022c441 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -122,8 +122,8 @@ pub fn item_to_ast_nodes( )); } - let incl_stmt = submodule_to_include_statement(&submodule); - vec![AstNodeContent::IncludeStatement(incl_stmt)] + let mod_stmt = submodule_to_mod_statement(&submodule); + vec![AstNodeContent::ModStatement(mod_stmt)] } ItemKind::Use(item_use) => item_use_to_use_statements(context, handler, item_use)? .into_iter() @@ -4647,8 +4647,8 @@ fn statement_let_to_ast_nodes_unfold( Ok(ast_nodes) } -fn submodule_to_include_statement(submodule: &Submodule) -> IncludeStatement { - IncludeStatement { +fn submodule_to_mod_statement(submodule: &Submodule) -> ModStatement { + ModStatement { span: submodule.span(), mod_name: submodule.name.clone(), visibility: pub_token_opt_to_visibility(submodule.visibility.clone()), diff --git a/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs b/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs index 593ed808bce..e7c2ac38cdf 100644 --- a/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs +++ b/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs @@ -18,7 +18,7 @@ use std::{ use sway_core::language::{ parsed::ImportType, ty::{ - TyConstantDecl, TyDecl, TyFunctionDecl, TyIncludeStatement, TyTypeAliasDecl, TyUseStatement, + TyConstantDecl, TyDecl, TyFunctionDecl, TyModStatement, TyTypeAliasDecl, TyUseStatement, }, CallPath, }; @@ -37,16 +37,16 @@ pub(crate) fn import_code_action( // Collect the tokens we need to determine where to insert the import statement. let mut use_statements = Vec::::new(); - let mut include_statements = Vec::::new(); + let mut mod_statements = Vec::::new(); let mut program_type_keyword = None; ctx.tokens.tokens_for_file(ctx.temp_uri).for_each(|item| { if let Some(TypedAstToken::TypedUseStatement(use_stmt)) = &item.value().as_typed() { use_statements.push(use_stmt.clone()); - } else if let Some(TypedAstToken::TypedIncludeStatement(include_stmt)) = + } else if let Some(TypedAstToken::TypedModStatement(mod_stmt)) = &item.value().as_typed() { - include_statements.push(include_stmt.clone()); + mod_statements.push(mod_stmt.clone()); } else if item.value().kind == SymbolKind::ProgramTypeKeyword { if let Some(ParsedAstToken::Keyword(ident)) = &item.value().as_parsed() { program_type_keyword = Some(ident.clone()); @@ -60,7 +60,7 @@ pub(crate) fn import_code_action( let text_edit = get_text_edit( &call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); let changes = HashMap::from([(ctx.uri.clone(), vec![text_edit])]); @@ -179,14 +179,14 @@ pub(crate) fn get_call_paths_for_name<'s>( fn get_text_edit( call_path: &CallPath, use_statements: &[TyUseStatement], - include_statements: &[TyIncludeStatement], + mod_statements: &[TyModStatement], program_type_keyword: &Option, ) -> TextEdit { get_text_edit_for_group(call_path, use_statements) .or_else(|| get_text_edit_in_use_block(call_path, use_statements)) .unwrap_or(get_text_edit_fallback( call_path, - include_statements, + mod_statements, program_type_keyword, )) } @@ -286,10 +286,10 @@ fn get_text_edit_in_use_block( /// type statement, or at the beginning of the file. fn get_text_edit_fallback( call_path: &CallPath, - include_statements: &[TyIncludeStatement], + mod_statements: &[TyModStatement], program_type_keyword: &Option, ) -> TextEdit { - let range_line = include_statements + let range_line = mod_statements .iter() .map(|stmt| stmt.span()) .reduce(|acc, span| { @@ -371,8 +371,8 @@ mod tests { } } - fn get_incl_stmt_from_src(src: &Source, mod_name: &str, text: &str) -> TyIncludeStatement { - TyIncludeStatement { + fn get_mod_stmt_from_src(src: &Source, mod_name: &str, text: &str) -> TyModStatement { + TyModStatement { span: get_span_from_src(src, text).unwrap(), mod_name: get_ident_from_src(src, mod_name).unwrap(), visibility: Visibility::Private, @@ -399,7 +399,7 @@ use b:c:*; get_use_stmt_from_src(&src, Vec::from(["b", "c"]), ImportType::Star, "use b:c:*;"), ]; - let include_statements = vec![]; + let mod_statements = vec![]; let program_type_keyword = get_ident_from_src(&src, "contract"); let expected_range = Range::new(Position::new(2, 0), Position::new(2, 10)); @@ -408,7 +408,7 @@ use b:c:*; let text_edit = get_text_edit( &new_call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); assert_text_edit(text_edit, expected_range, expected_text); @@ -430,7 +430,7 @@ use b:c:*; "use b:c:*;", )]; - let include_statements = vec![]; + let mod_statements = vec![]; let program_type_keyword = get_ident_from_src(&src, "predicate"); let expected_range = Range::new(Position::new(2, 0), Position::new(2, 0)); @@ -439,7 +439,7 @@ use b:c:*; let text_edit = get_text_edit( &new_call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); assert_text_edit(text_edit, expected_range, expected_text); @@ -469,7 +469,7 @@ use b:c:{D, F}; ), ]; - let include_statements = vec![]; + let mod_statements = vec![]; let program_type_keyword = get_ident_from_src(&src, "contract"); let expected_range = Range::new(Position::new(2, 0), Position::new(2, 15)); @@ -478,7 +478,7 @@ use b:c:{D, F}; let text_edit = get_text_edit( &new_call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); assert_text_edit(text_edit, expected_range, expected_text); @@ -496,9 +496,9 @@ pub mod zz_module; let new_call_path = get_mock_call_path(vec!["b", "c"], "D"); let use_statements = vec![]; - let include_statements = vec![ - get_incl_stmt_from_src(&src, "my_module", "mod my_module;"), - get_incl_stmt_from_src(&src, "zz_module", "pub mod zz_module"), + let mod_statements = vec![ + get_mod_stmt_from_src(&src, "my_module", "mod my_module;"), + get_mod_stmt_from_src(&src, "zz_module", "pub mod zz_module"), ]; let program_type_keyword = get_ident_from_src(&src, "library"); @@ -508,7 +508,7 @@ pub mod zz_module; let text_edit = get_text_edit( &new_call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); assert_text_edit(text_edit, expected_range, expected_text); @@ -525,7 +525,7 @@ const HI: u8 = 0; let new_call_path = get_mock_call_path(vec!["b", "c"], "D"); let use_statements = vec![]; - let include_statements = vec![]; + let mod_statements = vec![]; let program_type_keyword = get_ident_from_src(&src, "script"); let expected_range = Range::new(Position::new(1, 0), Position::new(1, 0)); @@ -534,7 +534,7 @@ const HI: u8 = 0; let text_edit = get_text_edit( &new_call_path, &use_statements, - &include_statements, + &mod_statements, &program_type_keyword, ); assert_text_edit(text_edit, expected_range, expected_text); diff --git a/sway-lsp/src/capabilities/document_symbol.rs b/sway-lsp/src/capabilities/document_symbol.rs index 3b1ea618bb9..9564b6eeda1 100644 --- a/sway-lsp/src/capabilities/document_symbol.rs +++ b/sway-lsp/src/capabilities/document_symbol.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use sway_core::{ language::ty::{ TyAbiDecl, TyAstNodeContent, TyConstantDecl, TyDecl, TyEnumDecl, TyFunctionDecl, - TyFunctionParameter, TyIncludeStatement, TyProgram, TyStatement, TyStorageDecl, + TyFunctionParameter, TyModStatement, TyProgram, TyStatement, TyStorageDecl, TyStructDecl, TyTraitInterfaceItem, TyTraitItem, TyTraitType, }, Engines, GenericArgument, @@ -51,8 +51,8 @@ pub fn to_document_symbols( .flatten() .filter_map(|node| { match &node.content { - TyAstNodeContent::Statement(TyStatement::Include(include_statement)) => { - Some(build_include_symbol(include_statement)) + TyAstNodeContent::Statement(TyStatement::Mod(mod_statement)) => { + Some(build_mod_symbol(mod_statement)) } TyAstNodeContent::Statement(_) => None, TyAstNodeContent::Declaration(decl) => match decl { @@ -223,8 +223,8 @@ pub fn to_document_symbols( nodes } -fn build_include_symbol(include_statement: &TyIncludeStatement) -> DocumentSymbol { - let span = include_statement.span(); +fn build_mod_symbol(mod_statement: &TyModStatement) -> DocumentSymbol { + let span = mod_statement.span(); let range = get_range_from_span(&span); DocumentSymbolBuilder::new() .name(span.str().to_string()) diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index 68d43c48c51..a61da239858 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -7,7 +7,7 @@ use sway_core::{ parsed::{ AbiCastExpression, AmbiguousPathExpression, Declaration, DelineatedPathExpression, EnumVariant, Expression, FunctionApplicationExpression, FunctionParameter, - IncludeStatement, MethodApplicationExpression, Scrutinee, StorageField, + ModStatement, MethodApplicationExpression, Scrutinee, StorageField, StorageNamespace, StructExpression, StructExpressionField, StructField, StructScrutineeField, Supertrait, TraitFn, UseStatement, }, @@ -37,7 +37,7 @@ pub enum ParsedAstToken { FunctionParameter(FunctionParameter), Ident(Ident), ModuleName, - IncludeStatement(IncludeStatement), + ModStatement(ModStatement), Intrinsic(Intrinsic), Keyword(Ident), LibrarySpan(Span), @@ -84,7 +84,7 @@ pub enum TypedAstToken { TypedParameter(TypeParameter), TypedTraitConstraint(TraitConstraint), TypedModuleName, - TypedIncludeStatement(ty::TyIncludeStatement), + TypedModStatement(ty::TyModStatement), TypedUseStatement(ty::TyUseStatement), TypedStatement(ty::TyStatement), Ident(Ident), diff --git a/sway-lsp/src/traverse/parsed_tree.rs b/sway-lsp/src/traverse/parsed_tree.rs index 04ceb89b841..ee62678b026 100644 --- a/sway-lsp/src/traverse/parsed_tree.rs +++ b/sway-lsp/src/traverse/parsed_tree.rs @@ -24,7 +24,7 @@ use sway_core::{ ConstGenericDeclaration, ConstantDeclaration, Declaration, DelineatedPathExpression, EnumDeclaration, EnumVariant, Expression, ExpressionKind, ForLoopExpression, FunctionApplicationExpression, FunctionDeclaration, FunctionParameter, IfExpression, - ImplItem, ImplSelfOrTrait, ImportType, IncludeStatement, IntrinsicFunctionExpression, + ImplItem, ImplSelfOrTrait, ImportType, ModStatement, IntrinsicFunctionExpression, LazyOperatorExpression, MatchExpression, MethodApplicationExpression, MethodName, ParseModule, ParseProgram, ParseSubmodule, QualifiedPathType, ReassignmentExpression, ReassignmentTarget, RefExpression, Scrutinee, StorageAccessExpression, @@ -112,7 +112,7 @@ impl Parse for AstNode { expression.parse(ctx); } AstNodeContent::UseStatement(use_statement) => use_statement.parse(ctx), - AstNodeContent::IncludeStatement(include_statement) => include_statement.parse(ctx), + AstNodeContent::ModStatement(mod_statement) => mod_statement.parse(ctx), AstNodeContent::Error(_, _) => {} } } @@ -184,12 +184,12 @@ impl Parse for UseStatement { } } -impl Parse for IncludeStatement { +impl Parse for ModStatement { fn parse(&self, ctx: &ParseContext) { ctx.tokens.insert( ctx.ident(&self.mod_name), Token::from_parsed( - ParsedAstToken::IncludeStatement(self.clone()), + ParsedAstToken::ModStatement(self.clone()), SymbolKind::Unknown, ), ); diff --git a/sway-lsp/src/traverse/typed_tree.rs b/sway-lsp/src/traverse/typed_tree.rs index dd1940d7c5d..9a606189b77 100644 --- a/sway-lsp/src/traverse/typed_tree.rs +++ b/sway-lsp/src/traverse/typed_tree.rs @@ -642,16 +642,16 @@ impl Parse for ty::TyStatement { ImportType::Star => {} } } - ty::TyStatement::Include( - include_statement @ ty::TyIncludeStatement { + ty::TyStatement::Mod( + mod_statement @ ty::TyModStatement { span: _, mod_name, visibility: _, }, ) => { if let Some(mut token) = ctx.tokens.try_get_mut_with_retry(&ctx.ident(mod_name)) { - token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedIncludeStatement( - include_statement.clone(), + token.ast_node = TokenAstNode::Typed(TypedAstToken::TypedModStatement( + mod_statement.clone(), )); if let Some(span) = ctx .namespace From a1a3e008d2a5ee5d392ea1b080f13369df425d9a Mon Sep 17 00:00:00 2001 From: tritao Date: Tue, 7 Oct 2025 22:42:09 +0100 Subject: [PATCH 6/6] Introduce `AstNodeContent::Statement`. --- sway-core/src/language/parsed/mod.rs | 31 +++++++++---- sway-core/src/language/ty/statement/mod.rs | 6 ++- .../src/semantic_analysis/ast_node/mod.rs | 46 ++++++++++--------- sway-core/src/semantic_analysis/module.rs | 29 ++++++------ .../semantic_analysis/node_dependencies.rs | 27 +++++++---- .../src/semantic_analysis/symbol_resolve.rs | 3 +- .../to_parsed_lang/convert_parse_tree.rs | 9 ++-- .../code_actions/diagnostic/auto_import.rs | 8 +--- sway-lsp/src/capabilities/document_symbol.rs | 4 +- sway-lsp/src/core/token.rs | 6 +-- sway-lsp/src/traverse/parsed_tree.rs | 28 +++++++---- 11 files changed, 117 insertions(+), 80 deletions(-) diff --git a/sway-core/src/language/parsed/mod.rs b/sway-core/src/language/parsed/mod.rs index 45f8203c6ec..0bf7bedd6a9 100644 --- a/sway-core/src/language/parsed/mod.rs +++ b/sway-core/src/language/parsed/mod.rs @@ -54,15 +54,13 @@ impl PartialEqWithEngines for AstNode { #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone)] pub enum AstNodeContent { - /// A statement of the form `use foo::bar;` or `use ::foo::bar;` - UseStatement(UseStatement), + /// Any statement node. + Statement(Statement), /// Any type of declaration, of which there are quite a few. See [Declaration] for more details /// on the possible variants. Declaration(Declaration), /// Any type of expression, of which there are quite a few. See [Expression] for more details. Expression(Expression), - /// A statement of the form `mod foo::bar;` which imports/includes another source file. - ModStatement(ModStatement), /// A malformed statement. /// /// Used for parser recovery when we cannot form a more specific node. @@ -75,20 +73,37 @@ impl EqWithEngines for AstNodeContent {} impl PartialEqWithEngines for AstNodeContent { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { match (self, other) { - (AstNodeContent::UseStatement(lhs), AstNodeContent::UseStatement(rhs)) => lhs.eq(rhs), + (AstNodeContent::Statement(lhs), AstNodeContent::Statement(rhs)) => lhs.eq(rhs, ctx), (AstNodeContent::Declaration(lhs), AstNodeContent::Declaration(rhs)) => { lhs.eq(rhs, ctx) } (AstNodeContent::Expression(lhs), AstNodeContent::Expression(rhs)) => lhs.eq(rhs, ctx), - (AstNodeContent::ModStatement(lhs), AstNodeContent::ModStatement(rhs)) => { - lhs.eq(rhs) - } (AstNodeContent::Error(lhs, ..), AstNodeContent::Error(rhs, ..)) => lhs.eq(rhs), _ => false, } } } +/// Statements that can appear in the parse tree. +#[derive(Debug, Clone)] +pub enum Statement { + /// A statement of the form `use foo::bar;` or `use ::foo::bar;` + Use(UseStatement), + /// A statement of the form `mod foo::bar;` which imports/includes another source file. + Mod(ModStatement), +} + +impl EqWithEngines for Statement {} +impl PartialEqWithEngines for Statement { + fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (Statement::Use(lhs), Statement::Use(rhs)) => lhs.eq(rhs), + (Statement::Mod(lhs), Statement::Mod(rhs)) => lhs.eq(rhs), + _ => false, + } + } +} + impl ParseTree { /// Excludes all test functions from the parse tree. pub(crate) fn exclude_tests(&mut self, engines: &Engines) { diff --git a/sway-core/src/language/ty/statement/mod.rs b/sway-core/src/language/ty/statement/mod.rs index 2c6f9d3c0b8..cc96b723d40 100644 --- a/sway-core/src/language/ty/statement/mod.rs +++ b/sway-core/src/language/ty/statement/mod.rs @@ -1,7 +1,11 @@ use crate::{ decl_engine::{DeclMapping, MaterializeConstGenerics, ReplaceDecls}, engine_threading::*, - language::{parsed, Visibility, ty::{TyExpression, TyVariableDecl, VariableMutability}}, + language::{ + parsed, + ty::{TyExpression, TyVariableDecl, VariableMutability}, + Visibility, + }, semantic_analysis::{ TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckContext, TypeCheckFinalization, TypeCheckFinalizationContext, diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 6793aab6723..4d26c43de7f 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -29,10 +29,12 @@ impl ty::TyAstNode { node: &AstNode, ) -> Result<(), ErrorEmitted> { match node.content.clone() { - AstNodeContent::UseStatement(stmt) => { - collect_use_statement(handler, engines, ctx, &stmt); - } - AstNodeContent::ModStatement(_i) => (), + AstNodeContent::Statement(statement) => match statement { + Statement::Use(stmt) => { + collect_use_statement(handler, engines, ctx, &stmt); + } + Statement::Mod(_mod_stmt) => (), + }, AstNodeContent::Declaration(decl) => ty::TyDecl::collect(handler, engines, ctx, decl)?, AstNodeContent::Expression(expr) => { ty::TyExpression::collect(handler, engines, ctx, &expr)? @@ -54,23 +56,25 @@ impl ty::TyAstNode { let node = ty::TyAstNode { content: match node.content.clone() { - AstNodeContent::UseStatement(stmt) => { - handle_use_statement(&mut ctx, &stmt, handler); - ty::TyAstNodeContent::Statement(ty::TyStatement::Use(ty::TyUseStatement { - alias: stmt.alias, - call_path: stmt.call_path, - span: stmt.span, - is_relative_to_package_root: stmt.is_relative_to_package_root, - import_type: stmt.import_type, - })) - } - AstNodeContent::ModStatement(i) => ty::TyAstNodeContent::Statement( - ty::TyStatement::Mod(ty::TyModStatement { - mod_name: i.mod_name, - span: i.span, - visibility: i.visibility, - }), - ), + AstNodeContent::Statement(statement) => match statement { + Statement::Use(stmt) => { + handle_use_statement(&mut ctx, &stmt, handler); + ty::TyAstNodeContent::Statement(ty::TyStatement::Use(ty::TyUseStatement { + alias: stmt.alias, + call_path: stmt.call_path, + span: stmt.span, + is_relative_to_package_root: stmt.is_relative_to_package_root, + import_type: stmt.import_type, + })) + } + Statement::Mod(i) => { + ty::TyAstNodeContent::Statement(ty::TyStatement::Mod(ty::TyModStatement { + mod_name: i.mod_name, + span: i.span, + visibility: i.visibility, + })) + } + }, AstNodeContent::Declaration(decl) => ty::TyAstNodeContent::Declaration( ty::TyDecl::type_check(handler, &mut ctx, decl)?, ), diff --git a/sway-core/src/semantic_analysis/module.rs b/sway-core/src/semantic_analysis/module.rs index e728fdae7df..e203461c98f 100644 --- a/sway-core/src/semantic_analysis/module.rs +++ b/sway-core/src/semantic_analysis/module.rs @@ -813,26 +813,27 @@ impl ty::TySubmodule { let sub_mod_node = module_dep_graph.get_node_id_for_module(&mod_name).unwrap(); for node in module.tree.root_nodes.iter() { match &node.content { - AstNodeContent::UseStatement(use_stmt) => { - if let Some(use_mod_ident) = use_stmt.call_path.first() { - if let Some(mod_name_node) = - module_dep_graph.get_node_id_for_module(use_mod_ident) - { - // Prevent adding edge loops between the same node as that will throw off - // the cyclic dependency analysis. - if sub_mod_node != mod_name_node { - module_dep_graph.dep_graph.add_edge( - sub_mod_node, - mod_name_node, - ModuleDepGraphEdge {}, - ); + AstNodeContent::Statement(statement) => { + if let Statement::Use(use_stmt) = statement { + if let Some(use_mod_ident) = use_stmt.call_path.first() { + if let Some(mod_name_node) = + module_dep_graph.get_node_id_for_module(use_mod_ident) + { + // Prevent adding edge loops between the same node as that will throw off + // the cyclic dependency analysis. + if sub_mod_node != mod_name_node { + module_dep_graph.dep_graph.add_edge( + sub_mod_node, + mod_name_node, + ModuleDepGraphEdge {}, + ); + } } } } } AstNodeContent::Declaration(_) => {} AstNodeContent::Expression(_) => {} - AstNodeContent::ModStatement(_) => {} AstNodeContent::Error(_, _) => {} } } diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 3c8a8318855..173ad20bd08 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -268,17 +268,26 @@ fn depends_on( ) -> bool { match (&dependant_node.content, &dependee_node.content) { // Include statements first. - (AstNodeContent::ModStatement(_), AstNodeContent::ModStatement(_)) => false, - (_, AstNodeContent::ModStatement(_)) => true, + ( + AstNodeContent::Statement(Statement::Mod(_)), + AstNodeContent::Statement(Statement::Mod(_)), + ) => false, + (_, AstNodeContent::Statement(Statement::Mod(_))) => true, // Use statements next. - (AstNodeContent::ModStatement(_), AstNodeContent::UseStatement(_)) => false, - (AstNodeContent::UseStatement(_), AstNodeContent::UseStatement(_)) => false, - (_, AstNodeContent::UseStatement(_)) => true, + ( + AstNodeContent::Statement(Statement::Mod(_)), + AstNodeContent::Statement(Statement::Use(_)), + ) => false, + ( + AstNodeContent::Statement(Statement::Use(_)), + AstNodeContent::Statement(Statement::Use(_)), + ) => false, + (_, AstNodeContent::Statement(Statement::Use(_))) => true, // Then declarations, ordered using the dependencies list. - (AstNodeContent::ModStatement(_), AstNodeContent::Declaration(_)) => false, - (AstNodeContent::UseStatement(_), AstNodeContent::Declaration(_)) => false, + (AstNodeContent::Statement(Statement::Mod(_)), AstNodeContent::Declaration(_)) => false, + (AstNodeContent::Statement(Statement::Use(_)), AstNodeContent::Declaration(_)) => false, (AstNodeContent::Declaration(dependant), AstNodeContent::Declaration(dependee)) => { match (decl_name(engines, dependant), decl_name(engines, dependee)) { (Some(dependant_name), Some(dependee_name)) => decl_dependencies @@ -768,9 +777,7 @@ impl Dependencies { AstNodeContent::Declaration(decl) => self.gather_from_decl(engines, decl), // No deps from these guys. - AstNodeContent::UseStatement(_) - | AstNodeContent::ModStatement(_) - | AstNodeContent::Error(_, _) => self, + AstNodeContent::Statement(_) | AstNodeContent::Error(_, _) => self, } } diff --git a/sway-core/src/semantic_analysis/symbol_resolve.rs b/sway-core/src/semantic_analysis/symbol_resolve.rs index b5221d56504..6c41ca7e9fb 100644 --- a/sway-core/src/semantic_analysis/symbol_resolve.rs +++ b/sway-core/src/semantic_analysis/symbol_resolve.rs @@ -61,10 +61,9 @@ impl ResolveSymbols for ParseModule { impl ResolveSymbols for AstNode { fn resolve_symbols(&mut self, handler: &Handler, ctx: SymbolResolveContext) { match &mut self.content { - AstNodeContent::UseStatement(_) => {} + AstNodeContent::Statement(_) => {} AstNodeContent::Declaration(decl) => decl.resolve_symbols(handler, ctx), AstNodeContent::Expression(expr) => expr.resolve_symbols(handler, ctx), - AstNodeContent::ModStatement(_) => {} AstNodeContent::Error(_, _) => {} } } diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 1564022c441..db8f04f1f24 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -6,7 +6,10 @@ use crate::{ generate_tuple_var_name, }, decl_engine::{parsed_engine::ParsedDeclEngineInsert, parsed_id::ParsedDeclId}, - language::{parsed::*, *}, + language::{ + parsed::{self, *}, + *, + }, transform::{attribute::*, to_parsed_lang::context::Context}, type_system::*, BuildTarget, Engines, @@ -123,11 +126,11 @@ pub fn item_to_ast_nodes( } let mod_stmt = submodule_to_mod_statement(&submodule); - vec![AstNodeContent::ModStatement(mod_stmt)] + vec![AstNodeContent::Statement(parsed::Statement::Mod(mod_stmt))] } ItemKind::Use(item_use) => item_use_to_use_statements(context, handler, item_use)? .into_iter() - .map(AstNodeContent::UseStatement) + .map(|use_stmt| AstNodeContent::Statement(parsed::Statement::Use(use_stmt))) .collect(), ItemKind::Struct(item_struct) => { let struct_decl = Declaration::StructDeclaration(item_struct_to_struct_declaration( diff --git a/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs b/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs index e7c2ac38cdf..694260b97c2 100644 --- a/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs +++ b/sway-lsp/src/capabilities/code_actions/diagnostic/auto_import.rs @@ -17,9 +17,7 @@ use std::{ }; use sway_core::language::{ parsed::ImportType, - ty::{ - TyConstantDecl, TyDecl, TyFunctionDecl, TyModStatement, TyTypeAliasDecl, TyUseStatement, - }, + ty::{TyConstantDecl, TyDecl, TyFunctionDecl, TyModStatement, TyTypeAliasDecl, TyUseStatement}, CallPath, }; use sway_types::{Ident, Spanned}; @@ -43,9 +41,7 @@ pub(crate) fn import_code_action( ctx.tokens.tokens_for_file(ctx.temp_uri).for_each(|item| { if let Some(TypedAstToken::TypedUseStatement(use_stmt)) = &item.value().as_typed() { use_statements.push(use_stmt.clone()); - } else if let Some(TypedAstToken::TypedModStatement(mod_stmt)) = - &item.value().as_typed() - { + } else if let Some(TypedAstToken::TypedModStatement(mod_stmt)) = &item.value().as_typed() { mod_statements.push(mod_stmt.clone()); } else if item.value().kind == SymbolKind::ProgramTypeKeyword { if let Some(ParsedAstToken::Keyword(ident)) = &item.value().as_parsed() { diff --git a/sway-lsp/src/capabilities/document_symbol.rs b/sway-lsp/src/capabilities/document_symbol.rs index 9564b6eeda1..c38292edf03 100644 --- a/sway-lsp/src/capabilities/document_symbol.rs +++ b/sway-lsp/src/capabilities/document_symbol.rs @@ -4,8 +4,8 @@ use std::path::PathBuf; use sway_core::{ language::ty::{ TyAbiDecl, TyAstNodeContent, TyConstantDecl, TyDecl, TyEnumDecl, TyFunctionDecl, - TyFunctionParameter, TyModStatement, TyProgram, TyStatement, TyStorageDecl, - TyStructDecl, TyTraitInterfaceItem, TyTraitItem, TyTraitType, + TyFunctionParameter, TyModStatement, TyProgram, TyStatement, TyStorageDecl, TyStructDecl, + TyTraitInterfaceItem, TyTraitItem, TyTraitType, }, Engines, GenericArgument, }; diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index a61da239858..517dc426e39 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -7,9 +7,9 @@ use sway_core::{ parsed::{ AbiCastExpression, AmbiguousPathExpression, Declaration, DelineatedPathExpression, EnumVariant, Expression, FunctionApplicationExpression, FunctionParameter, - ModStatement, MethodApplicationExpression, Scrutinee, StorageField, - StorageNamespace, StructExpression, StructExpressionField, StructField, - StructScrutineeField, Supertrait, TraitFn, UseStatement, + MethodApplicationExpression, ModStatement, Scrutinee, StorageField, StorageNamespace, + StructExpression, StructExpressionField, StructField, StructScrutineeField, Supertrait, + TraitFn, UseStatement, }, ty, }, diff --git a/sway-lsp/src/traverse/parsed_tree.rs b/sway-lsp/src/traverse/parsed_tree.rs index ee62678b026..b31bd3c0e36 100644 --- a/sway-lsp/src/traverse/parsed_tree.rs +++ b/sway-lsp/src/traverse/parsed_tree.rs @@ -24,15 +24,15 @@ use sway_core::{ ConstGenericDeclaration, ConstantDeclaration, Declaration, DelineatedPathExpression, EnumDeclaration, EnumVariant, Expression, ExpressionKind, ForLoopExpression, FunctionApplicationExpression, FunctionDeclaration, FunctionParameter, IfExpression, - ImplItem, ImplSelfOrTrait, ImportType, ModStatement, IntrinsicFunctionExpression, + ImplItem, ImplSelfOrTrait, ImportType, IntrinsicFunctionExpression, LazyOperatorExpression, MatchExpression, MethodApplicationExpression, MethodName, - ParseModule, ParseProgram, ParseSubmodule, QualifiedPathType, ReassignmentExpression, - ReassignmentTarget, RefExpression, Scrutinee, StorageAccessExpression, - StorageDeclaration, StorageEntry, StorageField, StorageNamespace, StructDeclaration, - StructExpression, StructExpressionField, StructField, StructScrutineeField, - SubfieldExpression, Supertrait, TraitDeclaration, TraitFn, TraitItem, - TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, UseStatement, - VariableDeclaration, WhileLoopExpression, + ModStatement, ParseModule, ParseProgram, ParseSubmodule, QualifiedPathType, + ReassignmentExpression, ReassignmentTarget, RefExpression, Scrutinee, Statement, + StorageAccessExpression, StorageDeclaration, StorageEntry, StorageField, + StorageNamespace, StructDeclaration, StructExpression, StructExpressionField, + StructField, StructScrutineeField, SubfieldExpression, Supertrait, TraitDeclaration, + TraitFn, TraitItem, TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, + UseStatement, VariableDeclaration, WhileLoopExpression, }, CallPathTree, HasSubmodules, Literal, }, @@ -111,13 +111,21 @@ impl Parse for AstNode { AstNodeContent::Expression(expression) => { expression.parse(ctx); } - AstNodeContent::UseStatement(use_statement) => use_statement.parse(ctx), - AstNodeContent::ModStatement(mod_statement) => mod_statement.parse(ctx), + AstNodeContent::Statement(statement) => statement.parse(ctx), AstNodeContent::Error(_, _) => {} } } } +impl Parse for Statement { + fn parse(&self, ctx: &ParseContext) { + match self { + Statement::Use(use_statement) => use_statement.parse(ctx), + Statement::Mod(mod_statement) => mod_statement.parse(ctx), + } + } +} + impl Parse for Declaration { fn parse(&self, ctx: &ParseContext) { match self {