diff --git a/sway-core/src/declaration_engine/declaration_engine.rs b/sway-core/src/declaration_engine/declaration_engine.rs index 08c44d36587..d2769c2847b 100644 --- a/sway-core/src/declaration_engine/declaration_engine.rs +++ b/sway-core/src/declaration_engine/declaration_engine.rs @@ -4,11 +4,15 @@ use sway_types::{Span, Spanned}; use crate::{ concurrent_slab::ConcurrentSlab, + error::{err, ok}, + namespace::{Path, Root}, semantic_analysis::{ TypedImplTrait, TypedStorageDeclaration, TypedStructDeclaration, TypedTraitDeclaration, TypedTraitFn, }, - CompileError, TypedFunctionDeclaration, + type_system::TypeArgument, + type_system::{type_engine::monomorphize, EnforceTypeArguments}, + CompileError, CompileResult, TypedFunctionDeclaration, }; use super::{declaration_id::DeclarationId, declaration_wrapper::DeclarationWrapper}; @@ -24,6 +28,7 @@ pub(crate) struct DeclarationEngine { // *declaration_id -> vec of monomorphized copies // where the declaration_id is the original declaration monomorphized_copies: RwLock>>, + is_monomorph_cache_enabled: bool, } impl DeclarationEngine { @@ -39,14 +44,10 @@ impl DeclarationEngine { fn de_add_monomorphized_copy(&self, original_id: DeclarationId, new_id: DeclarationId) { let mut monomorphized_copies = self.monomorphized_copies.write().unwrap(); - match monomorphized_copies.get_mut(&*original_id) { - Some(prev) => { - prev.push(new_id); - } - None => { - monomorphized_copies.insert(*original_id, vec![new_id]); - } - } + monomorphized_copies + .entry(*original_id) + .and_modify(|f| f.push(new_id.clone())) + .or_insert_with(|| vec![new_id.clone()]); } fn de_get_monomorphized_copies(&self, original_id: DeclarationId) -> Vec { @@ -76,17 +77,83 @@ impl DeclarationEngine { self.slab.get(*index).expect_function(span) } - fn de_add_monomorphized_function_copy( + pub(crate) fn de_get_monomorphized_function( &self, original_id: DeclarationId, - new_copy: TypedFunctionDeclaration, - ) { - let span = new_copy.span(); - let new_id = DeclarationId::new( - self.slab.insert(DeclarationWrapper::Function(new_copy)), - span, + type_arguments: &Vec, + access_span: &Span, + ) -> Result { + for copy in self + .de_get_monomorphized_copies(original_id) + .iter() + .cloned() + { + let monomorphized_fn_decl = copy.expect_function(access_span)?; + if &monomorphized_fn_decl.type_parameters == type_arguments { + return Ok(monomorphized_fn_decl); + } + } + Err(CompileError::Internal( + "could not find monomorphized function", + access_span.clone(), + )) + } + + pub(crate) fn de_get_or_create_monomorphized_function( + &mut self, + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, + ) -> CompileResult { + let mut warnings = Vec::new(); + let mut errors = Vec::new(); + + if self.is_monomorph_cache_enabled { + let cached_fn_decl = check!( + CompileResult::from(self.de_get_monomorphized_function( + decl_id, + type_arguments, + call_site_span + )), + return err(warnings, errors), + warnings, + errors + ); + return ok(cached_fn_decl, warnings, errors); + } + + // monomorphize the function declaration into a new copy + let mut typed_function_declaration = check!( + CompileResult::from(self.de_get_function(decl_id.clone(), call_site_span)), + return err(warnings, errors), + warnings, + errors + ); + + check!( + monomorphize( + &mut typed_function_declaration, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ), + return err(warnings, errors), + warnings, + errors ); - self.de_add_monomorphized_copy(original_id, new_id) + + // add the new copy to the declaration engine + let new_id = self.slab.insert(DeclarationWrapper::Function( + typed_function_declaration.clone(), + )); + self.de_add_monomorphized_copy(decl_id, DeclarationId::new(new_id, call_site_span.clone())); + + ok(typed_function_declaration, warnings, errors) } fn de_get_monomorphized_function_copies( @@ -129,7 +196,7 @@ impl DeclarationEngine { self.slab.get(*index).expect_trait_fn(span) } - fn insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { + fn de_insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { let span = trait_impl.span.clone(); DeclarationId::new( self.slab.insert(DeclarationWrapper::TraitImpl(trait_impl)), @@ -158,26 +225,83 @@ impl DeclarationEngine { self.slab.get(*index).expect_struct(span) } - fn de_add_monomorphized_struct_copy( + pub(crate) fn de_get_monomorphized_struct( &self, original_id: DeclarationId, - new_copy: TypedStructDeclaration, - ) { - let span = new_copy.span(); - let new_id = - DeclarationId::new(self.slab.insert(DeclarationWrapper::Struct(new_copy)), span); - self.de_add_monomorphized_copy(original_id, new_id) + type_arguments: &Vec, + span: &Span, + ) -> Result { + for copy in self + .de_get_monomorphized_copies(original_id) + .iter() + .cloned() + { + let monomorphized_struct_decl = copy.expect_struct(span)?; + if &monomorphized_struct_decl.type_parameters == type_arguments { + return Ok(monomorphized_struct_decl); + } + } + Err(CompileError::Internal( + "could not find monomorphized struct", + span.clone(), + )) } - fn de_get_monomorphized_struct_copies( + pub(crate) fn de_get_or_create_monomorphized_struct( &self, - original_id: DeclarationId, - span: &Span, - ) -> Result, CompileError> { - self.de_get_monomorphized_copies(original_id) - .into_iter() - .map(|x| x.expect_struct(span)) - .collect::>() + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, + ) -> CompileResult { + let mut warnings = Vec::new(); + let mut errors = Vec::new(); + + if self.is_monomorph_cache_enabled { + let cached_struct_decl = check!( + CompileResult::from(self.de_get_monomorphized_struct( + decl_id, + type_arguments, + call_site_span + )), + return err(warnings, errors), + warnings, + errors + ); + return ok(cached_struct_decl, warnings, errors); + } + + // monomorphize the struct declaration into a new copy + let mut typed_struct_declaration = check!( + CompileResult::from(self.de_get_struct(decl_id.clone(), call_site_span)), + return err(warnings, errors), + warnings, + errors + ); + + check!( + monomorphize( + &mut typed_struct_declaration, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ), + return err(warnings, errors), + warnings, + errors + ); + + // add the new copy to the declaration engine + let new_id = self + .slab + .insert(DeclarationWrapper::Struct(typed_struct_declaration.clone())); + self.de_add_monomorphized_copy(decl_id, DeclarationId::new(new_id, call_site_span.clone())); + + ok(typed_struct_declaration, warnings, errors) } fn de_insert_storage(&self, storage: TypedStorageDeclaration) -> DeclarationId { @@ -213,20 +337,6 @@ pub(crate) fn de_get_function( DECLARATION_ENGINE.de_get_function(index, span) } -pub(crate) fn de_add_monomorphized_function_copy( - original_id: DeclarationId, - new_copy: TypedFunctionDeclaration, -) { - DECLARATION_ENGINE.de_add_monomorphized_function_copy(original_id, new_copy); -} - -pub(crate) fn de_get_monomorphized_function_copies( - original_id: DeclarationId, - span: &Span, -) -> Result, CompileError> { - DECLARATION_ENGINE.de_get_monomorphized_function_copies(original_id, span) -} - pub(crate) fn de_insert_trait(r#trait: TypedTraitDeclaration) -> DeclarationId { DECLARATION_ENGINE.de_insert_trait(r#trait) } @@ -249,8 +359,8 @@ pub(crate) fn de_get_trait_fn( DECLARATION_ENGINE.de_get_trait_fn(index, span) } -pub(crate) fn insert_trait_impl(trait_impl: TypedImplTrait) -> DeclarationId { - DECLARATION_ENGINE.insert_trait_impl(trait_impl) +pub(crate) fn de_insert_trait_impl(trait_impl: TypedImplTrait) -> DeclarationId { + DECLARATION_ENGINE.de_insert_trait_impl(trait_impl) } pub(crate) fn de_get_trait_impl( @@ -264,25 +374,29 @@ pub(crate) fn de_insert_struct(r#struct: TypedStructDeclaration) -> DeclarationI DECLARATION_ENGINE.de_insert_struct(r#struct) } -pub(crate) fn de_get_struct( +pub fn de_get_struct( index: DeclarationId, span: &Span, ) -> Result { DECLARATION_ENGINE.de_get_struct(index, span) } -pub(crate) fn de_add_monomorphized_struct_copy( - original_id: DeclarationId, - new_copy: TypedStructDeclaration, -) { - DECLARATION_ENGINE.de_add_monomorphized_struct_copy(original_id, new_copy); -} - -pub(crate) fn de_get_monomorphized_struct_copies( - original_id: DeclarationId, - span: &Span, -) -> Result, CompileError> { - DECLARATION_ENGINE.de_get_monomorphized_struct_copies(original_id, span) +pub(crate) fn de_get_or_create_monomorphized_struct( + decl_id: DeclarationId, + type_arguments: &mut Vec, + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + namespace: &Root, + module_path: &Path, +) -> CompileResult { + DECLARATION_ENGINE.de_get_or_create_monomorphized_struct( + decl_id, + type_arguments, + enforce_type_arguments, + call_site_span, + namespace, + module_path, + ) } pub(crate) fn de_insert_storage(storage: TypedStorageDeclaration) -> DeclarationId { diff --git a/sway-core/src/type_system/mod.rs b/sway-core/src/type_system/mod.rs index bd80f613081..cccf02e9d7c 100644 --- a/sway-core/src/type_system/mod.rs +++ b/sway-core/src/type_system/mod.rs @@ -7,7 +7,7 @@ mod resolved_type; mod trait_constraint; mod type_argument; mod type_binding; -mod type_engine; +pub(crate) mod type_engine; mod type_id; mod type_info; mod type_mapping; diff --git a/sway-core/src/type_system/type_argument.rs b/sway-core/src/type_system/type_argument.rs index 03657319e6e..ad7aedbfc9a 100644 --- a/sway-core/src/type_system/type_argument.rs +++ b/sway-core/src/type_system/type_argument.rs @@ -30,6 +30,12 @@ impl PartialEq for TypeArgument { } } +impl PartialEq for TypeArgument { + fn eq(&self, other: &TypeParameter) -> bool { + self.type_id == other.type_id + } +} + impl Default for TypeArgument { fn default() -> Self { let initial_type_id = insert_type(TypeInfo::Unknown); diff --git a/sway-core/src/type_system/type_parameter.rs b/sway-core/src/type_system/type_parameter.rs index cbbcc93ac82..7bec38a4a50 100644 --- a/sway-core/src/type_system/type_parameter.rs +++ b/sway-core/src/type_system/type_parameter.rs @@ -37,6 +37,12 @@ impl PartialEq for TypeParameter { } } +impl PartialEq for TypeParameter { + fn eq(&self, other: &TypeArgument) -> bool { + self.type_id == other.type_id + } +} + impl CopyTypes for TypeParameter { fn copy_types(&mut self, type_mapping: &TypeMapping) { self.type_id = match look_up_type_id(self.type_id).matches_type_parameter(type_mapping) {