From 05834808bd3a15250116d2531ed58f4d009210ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Matos?= Date: Mon, 11 Mar 2024 14:20:55 +0000 Subject: [PATCH] Use an explicit module id when generating auto impl declarations (#5712) ## Description This PR makes sure we assign specific module ids to the generated auto impl decls. Helps with https://github.com/FuelLabs/sway/issues/5698. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: IGI-111 --- .../ast_node/declaration/auto_impl.rs | 91 ++++++++++++++++--- sway-types/src/source_engine.rs | 20 +++- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs index 470778228c0..55946de0d8e 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs @@ -11,7 +11,7 @@ use crate::{ use itertools::Itertools; use sway_error::handler::Handler; use sway_parse::Parse; -use sway_types::{integer_bits::IntegerBits, BaseIdent, Named, Span}; +use sway_types::{integer_bits::IntegerBits, BaseIdent, ModuleId, Named, Spanned}; /// Contains all information needed to implement AbiEncode pub struct AutoImplAbiEncodeContext<'a, 'b> @@ -29,14 +29,21 @@ where Some(Self { ctx }) } - pub fn parse(input: &str) -> T + pub fn parse(engines: &Engines, module_id: ModuleId, input: &str) -> T where T: Parse, { // println!("[{}]", input); let handler = <_>::default(); - let ts = - sway_parse::lex(&handler, &std::sync::Arc::from(input), 0, input.len(), None).unwrap(); + let source_id = engines.se().get_autogenerated_source_id(module_id); + let ts = sway_parse::lex( + &handler, + &std::sync::Arc::from(input), + 0, + input.len(), + Some(source_id), + ) + .unwrap(); let mut p = sway_parse::Parser::new(&handler, &ts); p.check_double_underscore = false; @@ -247,6 +254,7 @@ where pub fn parse_item_fn_to_typed_ast_node( &mut self, engines: &Engines, + module_id: ModuleId, kind: FunctionDeclarationKind, code: &str, ) -> Option { @@ -257,7 +265,7 @@ where let handler = Handler::default(); - let item = Self::parse(code); + let item = Self::parse(engines, module_id, code); let nodes = crate::transform::to_parsed_lang::item_to_ast_nodes( &mut ctx, &handler, @@ -289,14 +297,15 @@ where assert!(!handler.has_warnings(), "{:?}", handler); Some(TyAstNode { + span: decl.span(), content: ty::TyAstNodeContent::Declaration(decl), - span: Span::dummy(), }) } fn parse_item_impl_to_typed_ast_node( &mut self, engines: &Engines, + module_id: ModuleId, code: &str, ) -> Option { let mut ctx = crate::transform::to_parsed_lang::Context::new( @@ -306,7 +315,7 @@ where let handler = Handler::default(); - let item = Self::parse(code); + let item = Self::parse(engines, module_id, code); let nodes = crate::transform::to_parsed_lang::item_to_ast_nodes( &mut ctx, &handler, engines, item, false, None, None, ) @@ -326,8 +335,8 @@ where None } else { Some(TyAstNode { + span: decl.span(), content: ty::TyAstNodeContent::Declaration(decl), - span: Span::dummy(), }) } } @@ -346,13 +355,20 @@ where let implementing_for_decl_ref = decl.get_struct_decl_ref().unwrap(); let struct_decl = self.ctx.engines().de().get(implementing_for_decl_ref.id()); + let module_id = struct_decl + .span() + .source_id() + .map(|sid| sid.module_id()) + .expect("expected a valid module id"); + let abi_encode_body = self.generate_abi_encode_struct_body(engines, &struct_decl); let abi_encode_code = self.generate_abi_encode_code( struct_decl.name(), &struct_decl.type_parameters, abi_encode_body, ); - let abi_encode_node = self.parse_item_impl_to_typed_ast_node(engines, &abi_encode_code); + let abi_encode_node = + self.parse_item_impl_to_typed_ast_node(engines, module_id, &abi_encode_code); let abi_decode_body = self.generate_abi_decode_struct_body(engines, &struct_decl); let abi_decode_code = self.generate_abi_decode_code( @@ -360,7 +376,8 @@ where &struct_decl.type_parameters, abi_decode_body, ); - let abi_decode_node = self.parse_item_impl_to_typed_ast_node(engines, &abi_decode_code); + let abi_decode_node = + self.parse_item_impl_to_typed_ast_node(engines, module_id, &abi_decode_code); (abi_encode_node, abi_decode_node) } @@ -378,13 +395,20 @@ where let enum_decl_ref = decl.get_enum_decl_ref().unwrap(); let enum_decl = self.ctx.engines().de().get(enum_decl_ref.id()); + let module_id = enum_decl + .span() + .source_id() + .map(|sid| sid.module_id()) + .expect("expected a valid module id"); + let abi_decode_body = self.generate_abi_encode_enum_body(engines, &enum_decl); let abi_decode_code = self.generate_abi_encode_code( enum_decl.name(), &enum_decl.type_parameters, abi_decode_body, ); - let abi_encode_node = self.parse_item_impl_to_typed_ast_node(engines, &abi_decode_code); + let abi_encode_node = + self.parse_item_impl_to_typed_ast_node(engines, module_id, &abi_decode_code); let abi_decode_body = self.generate_abi_decode_enum_body(engines, &enum_decl); let abi_decode_code = self.generate_abi_decode_code( @@ -392,7 +416,8 @@ where &enum_decl.type_parameters, abi_decode_body, ); - let abi_decode_node = self.parse_item_impl_to_typed_ast_node(engines, &abi_decode_code); + let abi_decode_node = + self.parse_item_impl_to_typed_ast_node(engines, module_id, &abi_decode_code); (abi_encode_node, abi_decode_node) } @@ -492,6 +517,14 @@ where engines: &Engines, contract_fns: &[DeclRef>], ) -> Option { + let module_id = contract_fns + .first() + .expect("expected a valid contract function") + .decl_span() + .source_id() + .map(|sid| sid.module_id()) + .expect("expected a valid module id"); + let mut code = String::new(); let mut reads = false; @@ -568,7 +601,12 @@ where }}" ); - self.parse_item_fn_to_typed_ast_node(engines, FunctionDeclarationKind::Entry, &code) + self.parse_item_fn_to_typed_ast_node( + engines, + module_id, + FunctionDeclarationKind::Entry, + &code, + ) } pub(crate) fn generate_predicate_entry( @@ -576,6 +614,12 @@ where engines: &Engines, decl: &TyFunctionDecl, ) -> Option { + let module_id = decl + .span + .source_id() + .map(|sid| sid.module_id()) + .expect("expected a valid module id"); + let args_types = itertools::intersperse( decl.parameters .iter() @@ -605,7 +649,13 @@ where main({expanded_args}) }}" ); - self.parse_item_fn_to_typed_ast_node(engines, FunctionDeclarationKind::Entry, &code) + + self.parse_item_fn_to_typed_ast_node( + engines, + module_id, + FunctionDeclarationKind::Entry, + &code, + ) } pub(crate) fn generate_script_entry( @@ -613,6 +663,12 @@ where engines: &Engines, decl: &TyFunctionDecl, ) -> Option { + let module_id = decl + .span + .source_id() + .map(|sid| sid.module_id()) + .expect("expected a valid module id"); + let args_types = itertools::intersperse( decl.parameters .iter() @@ -655,6 +711,11 @@ where ) }; - self.parse_item_fn_to_typed_ast_node(engines, FunctionDeclarationKind::Entry, &code) + self.parse_item_fn_to_typed_ast_node( + engines, + module_id, + FunctionDeclarationKind::Entry, + &code, + ) } } diff --git a/sway-types/src/source_engine.rs b/sway-types/src/source_engine.rs index dd46df80119..0a3707b1cdc 100644 --- a/sway-types/src/source_engine.rs +++ b/sway-types/src/source_engine.rs @@ -6,7 +6,7 @@ use std::{ }; /// The Source Engine manages a relationship between file paths and their corresponding -/// integer-based source IDs. Additionally, it maintains a reserve - a map that traces +/// integer-based source IDs. Additionally, it maintains the reverse - a map that traces /// back from a source ID to its original file path. The primary objective of this /// system is to enable clients that need to reference a file path to do so using an /// integer-based ID. This numeric representation can be stored more efficiently as @@ -38,6 +38,8 @@ impl Clone for SourceEngine { } impl SourceEngine { + const AUTOGENERATED_PATH: &'static str = ""; + /// This function retrieves an integer-based source ID for a provided path buffer. /// If an ID already exists for the given path, the function will return that /// existing ID. If not, a new ID will be created. @@ -48,7 +50,6 @@ impl SourceEngine { return source_map.get(path).cloned().unwrap(); } } - let manifest_path = sway_utils::find_parent_manifest_dir(path).unwrap_or(path.clone()); let module_id = { let mut module_map = self.path_to_module_map.write().unwrap(); @@ -59,6 +60,17 @@ impl SourceEngine { }) }; + self.get_source_id_with_module_id(path, module_id) + } + + pub fn get_source_id_with_module_id(&self, path: &PathBuf, module_id: ModuleId) -> SourceId { + { + let source_map = self.path_to_source_map.read().unwrap(); + if source_map.contains_key(path) { + return source_map.get(path).cloned().unwrap(); + } + } + let source_id = SourceId::new(module_id.id, *self.next_source_id.read().unwrap()); { let mut next_id = self.next_source_id.write().unwrap(); @@ -77,6 +89,10 @@ impl SourceEngine { source_id } + pub fn get_autogenerated_source_id(&self, module_id: ModuleId) -> SourceId { + self.get_source_id_with_module_id(&Self::AUTOGENERATED_PATH.into(), module_id) + } + /// This function provides the file path corresponding to a specified source ID. pub fn get_path(&self, source_id: &SourceId) -> PathBuf { self.source_to_path_map