Skip to content

Commit

Permalink
Use an explicit module id when generating auto impl declarations (Fue…
Browse files Browse the repository at this point in the history
…lLabs#5712)

## Description

This PR makes sure we assign specific module ids to the generated auto
impl decls.

Helps with FuelLabs#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 <[email protected]>
  • Loading branch information
tritao and IGI-111 authored Mar 11, 2024
1 parent f8e40eb commit 0583480
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 17 deletions.
91 changes: 76 additions & 15 deletions sway-core/src/semantic_analysis/ast_node/declaration/auto_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -29,14 +29,21 @@ where
Some(Self { ctx })
}

pub fn parse<T>(input: &str) -> T
pub fn parse<T>(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;

Expand Down Expand Up @@ -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<TyAstNode> {
Expand All @@ -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,
Expand Down Expand Up @@ -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<TyAstNode> {
let mut ctx = crate::transform::to_parsed_lang::Context::new(
Expand All @@ -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,
)
Expand All @@ -326,8 +335,8 @@ where
None
} else {
Some(TyAstNode {
span: decl.span(),
content: ty::TyAstNodeContent::Declaration(decl),
span: Span::dummy(),
})
}
}
Expand All @@ -346,21 +355,29 @@ 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(
struct_decl.name(),
&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)
}
Expand All @@ -378,21 +395,29 @@ 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(
enum_decl.name(),
&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)
}
Expand Down Expand Up @@ -492,6 +517,14 @@ where
engines: &Engines,
contract_fns: &[DeclRef<DeclId<TyFunctionDecl>>],
) -> Option<TyAstNode> {
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;
Expand Down Expand Up @@ -568,14 +601,25 @@ 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(
&mut self,
engines: &Engines,
decl: &TyFunctionDecl,
) -> Option<TyAstNode> {
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()
Expand Down Expand Up @@ -605,14 +649,26 @@ 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(
&mut self,
engines: &Engines,
decl: &TyFunctionDecl,
) -> Option<TyAstNode> {
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()
Expand Down Expand Up @@ -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,
)
}
}
20 changes: 18 additions & 2 deletions sway-types/src/source_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -38,6 +38,8 @@ impl Clone for SourceEngine {
}

impl SourceEngine {
const AUTOGENERATED_PATH: &'static str = "<autogenerated>";

/// 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.
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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
Expand Down

0 comments on commit 0583480

Please sign in to comment.