From 5221ba349869a534d5def976ce27a7b3531a44e4 Mon Sep 17 00:00:00 2001 From: Anton Trunov Date: Tue, 5 Sep 2023 11:41:24 +0400 Subject: [PATCH 1/2] Partially resolves issue #5050 All the `impl TypeEngine` methods from the file `type_system/engine.rs` that also take `Engines` and `Namespace` as parameters have been moved into `impl TypeCheckContext`. All the `impl Root` methods from the file `namespace/root.rs` that also take `Engines` as parameters have been moved into `impl TypeCheckContext`. I'm splitting the refactoring into several PRs to solicit early feedback, make review process a bit easier and potentially create fewer merge conflicts. List of changes: - `type_engine.monomorphize` -> `ctx.monomorphize_with_modpath` - `type_engine.resolve` -> `ctx.resolve` - `type_engine.resolve_with_self` -> `ctx.resolve_with_self` - `type_engine.MonomorphizeHelper` -> `ctx.MonomorphizeHelper` - `type_engine.EnforceTypeArguments` -> `ctx.EnforceTypeArguments` - `namespace.root.resolve_call_path_with_visibility_check` -> `ctx.resolve_call_path_with_visibility_check_and_modpath` --- sway-core/src/language/ty/declaration/enum.rs | 1 + .../src/language/ty/declaration/function.rs | 2 + .../src/language/ty/declaration/struct.rs | 1 + .../src/language/ty/declaration/trait.rs | 1 + .../src/language/ty/declaration/trait_fn.rs | 1 + sway-core/src/semantic_analysis.rs | 2 +- .../ast_node/declaration/constant.rs | 4 +- .../ast_node/declaration/declaration.rs | 2 +- .../ast_node/declaration/enum.rs | 2 +- .../ast_node/declaration/function.rs | 2 +- .../function/function_parameter.rs | 2 +- .../ast_node/declaration/impl_trait.rs | 4 +- .../ast_node/declaration/struct.rs | 2 +- .../ast_node/declaration/supertrait.rs | 3 +- .../ast_node/declaration/trait_fn.rs | 1 + .../ast_node/expression/intrinsic_function.rs | 2 +- .../match_expression/typed/typed_scrutinee.rs | 2 +- .../ast_node/expression/typed_expression.rs | 2 +- .../typed_expression/method_application.rs | 2 +- .../typed_expression/struct_instantiation.rs | 2 +- .../src/semantic_analysis/namespace/root.rs | 55 +-- .../semantic_analysis/type_check_context.rs | 437 +++++++++++++++++- .../src/type_system/ast_elements/binding.rs | 2 +- .../ast_elements/trait_constraint.rs | 1 + sway-core/src/type_system/engine.rs | 363 +-------------- sway-core/src/type_system/priv_prelude.rs | 1 - 26 files changed, 450 insertions(+), 449 deletions(-) diff --git a/sway-core/src/language/ty/declaration/enum.rs b/sway-core/src/language/ty/declaration/enum.rs index 2b40f9bcdf3..741bf79d615 100644 --- a/sway-core/src/language/ty/declaration/enum.rs +++ b/sway-core/src/language/ty/declaration/enum.rs @@ -12,6 +12,7 @@ use sway_types::{Ident, Named, Span, Spanned}; use crate::{ engine_threading::*, language::{CallPath, Visibility}, + semantic_analysis::type_check_context::MonomorphizeHelper, transform, type_system::*, }; diff --git a/sway-core/src/language/ty/declaration/function.rs b/sway-core/src/language/ty/declaration/function.rs index 6ab800f9d57..24886ffff5e 100644 --- a/sway-core/src/language/ty/declaration/function.rs +++ b/sway-core/src/language/ty/declaration/function.rs @@ -6,6 +6,8 @@ use std::{ use sha2::{Digest, Sha256}; use sway_error::handler::{ErrorEmitted, Handler}; +use crate::semantic_analysis::type_check_context::MonomorphizeHelper; + use crate::{ decl_engine::*, engine_threading::*, diff --git a/sway-core/src/language/ty/declaration/struct.rs b/sway-core/src/language/ty/declaration/struct.rs index ea089a75e54..9d70f1b76d3 100644 --- a/sway-core/src/language/ty/declaration/struct.rs +++ b/sway-core/src/language/ty/declaration/struct.rs @@ -12,6 +12,7 @@ use sway_types::{Ident, Named, Span, Spanned}; use crate::{ engine_threading::*, language::{CallPath, Visibility}, + semantic_analysis::type_check_context::MonomorphizeHelper, transform, type_system::*, }; diff --git a/sway-core/src/language/ty/declaration/trait.rs b/sway-core/src/language/ty/declaration/trait.rs index 31b8d079332..3af47faa255 100644 --- a/sway-core/src/language/ty/declaration/trait.rs +++ b/sway-core/src/language/ty/declaration/trait.rs @@ -8,6 +8,7 @@ use crate::{ }, engine_threading::*, language::{parsed, Visibility}, + semantic_analysis::type_check_context::MonomorphizeHelper, transform, type_system::*, }; diff --git a/sway-core/src/language/ty/declaration/trait_fn.rs b/sway-core/src/language/ty/declaration/trait_fn.rs index f09b71f0ec1..3cbd5817de3 100644 --- a/sway-core/src/language/ty/declaration/trait_fn.rs +++ b/sway-core/src/language/ty/declaration/trait_fn.rs @@ -5,6 +5,7 @@ use sway_types::{Ident, Named, Span, Spanned}; use crate::{ engine_threading::*, language::{ty::*, Purity}, + semantic_analysis::type_check_context::MonomorphizeHelper, transform, type_system::*, }; diff --git a/sway-core/src/semantic_analysis.rs b/sway-core/src/semantic_analysis.rs index e27574e7393..db5f7834165 100644 --- a/sway-core/src/semantic_analysis.rs +++ b/sway-core/src/semantic_analysis.rs @@ -6,7 +6,7 @@ mod module; pub mod namespace; mod node_dependencies; mod program; -mod type_check_context; +pub(crate) mod type_check_context; pub use ast_node::*; pub use namespace::Namespace; pub(crate) use type_check_context::TypeCheckContext; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs b/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs index 88f9d1b1c1f..a46788a67d4 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs @@ -10,8 +10,8 @@ use crate::{ ty::{self, TyConstantDecl}, CallPath, }, - semantic_analysis::*, - EnforceTypeArguments, Engines, TypeInfo, + semantic_analysis::{type_check_context::EnforceTypeArguments, *}, + Engines, TypeInfo, }; impl ty::TyConstantDecl { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index 45aacc63000..5a605d70d80 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -4,7 +4,7 @@ use sway_types::{Named, Spanned}; use crate::{ decl_engine::{DeclEngineInsert, DeclRef, ReplaceFunctionImplementingType}, language::{parsed, ty}, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs index 1f086c0873e..892740516e8 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs @@ -2,7 +2,7 @@ use sway_error::handler::{ErrorEmitted, Handler}; use crate::{ language::{parsed::*, ty, CallPath}, - semantic_analysis::*, + semantic_analysis::{type_check_context::EnforceTypeArguments, *}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs index 0aa9c6e71e3..98bc86233e9 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs @@ -13,7 +13,7 @@ use crate::{ ty::{self, TyCodeBlock}, Visibility, }, - semantic_analysis::*, + semantic_analysis::{type_check_context::EnforceTypeArguments, *}, type_system::*, }; use sway_types::{style::is_snake_case, Spanned}; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs index 9c26fd9ea60..cf54789c046 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs @@ -1,6 +1,6 @@ use crate::{ language::{parsed::FunctionParameter, ty}, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs index efca97f8e7b..52cc1b0de80 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs @@ -15,7 +15,9 @@ use crate::{ *, }, namespace::TryInsertingTraitImplOnFailure, - semantic_analysis::{AbiMode, ConstShadowingMode, TypeCheckContext}, + semantic_analysis::{ + type_check_context::EnforceTypeArguments, AbiMode, ConstShadowingMode, TypeCheckContext, + }, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs index c2e3355ebf3..95f1de866d8 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs @@ -2,7 +2,7 @@ use sway_error::handler::{ErrorEmitted, Handler}; use crate::{ language::{parsed::*, ty, CallPath}, - semantic_analysis::*, + semantic_analysis::{type_check_context::EnforceTypeArguments, *}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/supertrait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/supertrait.rs index 241117abcf2..dfe481596cb 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/supertrait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/supertrait.rs @@ -2,10 +2,11 @@ use sway_error::error::CompileError; use sway_error::handler::{ErrorEmitted, Handler}; use sway_types::{Span, Spanned}; +use crate::semantic_analysis::type_check_context::EnforceTypeArguments; use crate::{ language::{parsed, ty}, semantic_analysis::TypeCheckContext, - EnforceTypeArguments, TypeId, + TypeId, }; #[derive(Clone, PartialEq, Eq)] diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait_fn.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait_fn.rs index 40064d7870b..bda3e15f9ad 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait_fn.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait_fn.rs @@ -3,6 +3,7 @@ use sway_types::{Span, Spanned}; use crate::{ decl_engine::DeclId, language::{parsed, ty, Visibility}, + semantic_analysis::type_check_context::EnforceTypeArguments, }; use sway_error::handler::{ErrorEmitted, Handler}; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs index a9b630ef387..a0fb0dfd124 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs @@ -9,7 +9,7 @@ use sway_types::Span; use crate::{ engine_threading::*, language::{parsed::Expression, ty}, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs index 284bb11efca..d957b02e7ff 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs @@ -11,7 +11,7 @@ use crate::{ ty::{self, TyDecl}, CallPath, }, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 29cc202a9e9..a03a2bc31bf 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -25,7 +25,7 @@ use crate::{ ty::{self, TyImplItem}, *, }, - semantic_analysis::{expression::ReachableReport, *}, + semantic_analysis::{expression::ReachableReport, type_check_context::EnforceTypeArguments, *}, transform::to_parsed_lang::type_name_to_type_info_opt, type_system::*, Engines, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 39bc5f26fd9..1c92a5b98d0 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -2,7 +2,7 @@ use crate::{ decl_engine::{DeclEngineInsert, DeclRefFunction, ReplaceDecls, UpdateConstantExpression}, language::{parsed::*, ty, *}, namespace::TryInsertingTraitImplOnFailure, - semantic_analysis::*, + semantic_analysis::{type_check_context::EnforceTypeArguments, *}, type_system::*, }; use ast_node::typed_expression::check_function_arguments_arity; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs index 064fba0cb9f..f1e543c9e24 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/struct_instantiation.rs @@ -7,7 +7,7 @@ use sway_types::{Ident, Span, Spanned}; use crate::{ decl_engine::DeclRefStruct, language::{parsed::*, ty, CallPath}, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::*, }; diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index 7c012dbe953..f3cf9fef6bf 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -1,13 +1,8 @@ -use sway_error::{ - error::CompileError, - handler::{ErrorEmitted, Handler}, -}; -use sway_types::Spanned; -use sway_utils::iter_prefixes; +use sway_error::handler::{ErrorEmitted, Handler}; use crate::{ language::{ty, CallPath}, - Engines, Ident, + Ident, }; use super::{module::Module, namespace::Namespace, Path}; @@ -44,52 +39,6 @@ impl Root { self.resolve_symbol(handler, &symbol_path, &call_path.suffix) } - /// Resolve a symbol that is potentially prefixed with some path, e.g. `foo::bar::symbol`. - /// - /// This will concatenate the `mod_path` with the `call_path`'s prefixes and - /// then calling `resolve_symbol` with the resulting path and call_path's suffix. - /// - /// The `mod_path` is significant here as we assume the resolution is done within the - /// context of the module pointed to by `mod_path` and will only check the call path prefixes - /// and the symbol's own visibility - pub(crate) fn resolve_call_path_with_visibility_check( - &self, - handler: &Handler, - engines: &Engines, - mod_path: &Path, - call_path: &CallPath, - ) -> Result<&ty::TyDecl, ErrorEmitted> { - let decl = self.resolve_call_path(handler, mod_path, call_path)?; - - // In case there are no prefixes we don't need to check visibility - if call_path.prefixes.is_empty() { - return Ok(decl); - } - - // check the visibility of the call path elements - // we don't check the first prefix because direct children are always accessible - for prefix in iter_prefixes(&call_path.prefixes).skip(1) { - let module = self.check_submodule(handler, prefix)?; - if module.visibility.is_private() { - let prefix_last = prefix[prefix.len() - 1].clone(); - handler.emit_err(CompileError::ImportPrivateModule { - span: prefix_last.span(), - name: prefix_last, - }); - } - } - - // check the visibility of the symbol itself - if !decl.visibility(engines.de()).is_public() { - handler.emit_err(CompileError::ImportPrivateSymbol { - name: call_path.suffix.clone(), - span: call_path.suffix.span(), - }); - } - - Ok(decl) - } - /// Given a path to a module and the identifier of a symbol within that module, resolve its /// declaration. /// diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 35f8a7f20a6..f5d97e3f7f2 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, VecDeque}; use crate::{ - decl_engine::{DeclRefConstant, DeclRefFunction}, + decl_engine::{DeclEngineInsert, DeclRefConstant, DeclRefFunction}, engine_threading::*, language::{ parsed::TreeType, @@ -13,16 +13,15 @@ use crate::{ ast_node::{AbiMode, ConstShadowingMode}, Namespace, }, - type_system::{ - EnforceTypeArguments, MonomorphizeHelper, SubstTypes, TypeArgument, TypeId, TypeInfo, - }, - ReplaceSelfType, UnifyCheck, + type_system::{SubstTypes, TypeArgument, TypeId, TypeInfo}, + CreateTypeId, ReplaceSelfType, TypeParameter, TypeSubstMap, UnifyCheck, }; use sway_error::{ error::CompileError, handler::{ErrorEmitted, Handler}, }; use sway_types::{span::Span, Ident, Spanned}; +use sway_utils::iter_prefixes; /// Contextual state tracked and accumulated throughout type-checking. pub struct TypeCheckContext<'a> { @@ -277,14 +276,12 @@ impl<'a> TypeCheckContext<'a> { T: MonomorphizeHelper + SubstTypes, { let mod_path = self.namespace.mod_path.clone(); - self.engines.te().monomorphize( + self.monomorphize_with_modpath( handler, - self.engines(), value, type_arguments, enforce_type_arguments, call_site_span, - self.namespace, &mod_path, ) } @@ -321,6 +318,208 @@ impl<'a> TypeCheckContext<'a> { self.engines } + /// Resolve the type of the given [TypeId], replacing any instances of + /// [TypeInfo::Custom] with either a monomorphized struct, monomorphized + /// enum, or a reference to a type parameter. + #[allow(clippy::too_many_arguments)] + pub(crate) fn resolve( + &mut self, + handler: &Handler, + type_id: TypeId, + span: &Span, + enforce_type_arguments: EnforceTypeArguments, + type_info_prefix: Option<&Path>, + mod_path: &Path, + ) -> Result { + let decl_engine = self.engines.de(); + let type_engine = self.engines.te(); + let module_path = type_info_prefix.unwrap_or(mod_path); + let type_id = match type_engine.get(type_id) { + TypeInfo::Custom { + call_path, + type_arguments, + } => { + match self + .resolve_call_path_with_visibility_check_and_modpath( + handler, + module_path, + &call_path, + ) + .ok() + .cloned() + { + Some(ty::TyDecl::StructDecl(ty::StructDecl { + decl_id: original_id, + .. + })) => { + // get the copy from the declaration engine + let mut new_copy = decl_engine.get_struct(&original_id); + + // monomorphize the copy, in place + self.monomorphize_with_modpath( + handler, + &mut new_copy, + &mut type_arguments.unwrap_or_default(), + enforce_type_arguments, + span, + mod_path, + )?; + + // insert the new copy in the decl engine + let new_decl_ref = decl_engine.insert(new_copy); + + // create the type id from the copy + let type_id = + type_engine.insert(self.engines, TypeInfo::Struct(new_decl_ref)); + + // take any trait methods that apply to this type and copy them to the new type + self.namespace + .insert_trait_implementation_for_type(self.engines, type_id); + + // return the id + type_id + } + Some(ty::TyDecl::EnumDecl(ty::EnumDecl { + decl_id: original_id, + .. + })) => { + // get the copy from the declaration engine + let mut new_copy = decl_engine.get_enum(&original_id); + + // monomorphize the copy, in place + self.monomorphize_with_modpath( + handler, + &mut new_copy, + &mut type_arguments.unwrap_or_default(), + enforce_type_arguments, + span, + mod_path, + )?; + + // insert the new copy in the decl engine + let new_decl_ref = decl_engine.insert(new_copy); + + // create the type id from the copy + let type_id = + type_engine.insert(self.engines, TypeInfo::Enum(new_decl_ref)); + + // take any trait methods that apply to this type and copy them to the new type + self.namespace + .insert_trait_implementation_for_type(self.engines, type_id); + + // return the id + type_id + } + Some(ty::TyDecl::TypeAliasDecl(ty::TypeAliasDecl { + decl_id: original_id, + .. + })) => { + let new_copy = decl_engine.get_type_alias(&original_id); + + // TODO: monomorphize the copy, in place, when generic type aliases are + // supported + + let type_id = new_copy.create_type_id(self.engines); + self.namespace + .insert_trait_implementation_for_type(self.engines, type_id); + + type_id + } + Some(ty::TyDecl::GenericTypeForFunctionScope( + ty::GenericTypeForFunctionScope { type_id, .. }, + )) => type_id, + _ => { + let err = handler.emit_err(CompileError::UnknownTypeName { + name: call_path.to_string(), + span: call_path.span(), + }); + type_engine.insert(self.engines, TypeInfo::ErrorRecovery(err)) + } + } + } + TypeInfo::Array(mut elem_ty, n) => { + elem_ty.type_id = self + .resolve( + handler, + elem_ty.type_id, + span, + enforce_type_arguments, + None, + mod_path, + ) + .unwrap_or_else(|err| { + self.engines + .te() + .insert(self.engines, TypeInfo::ErrorRecovery(err)) + }); + + let type_id = self + .engines + .te() + .insert(self.engines, TypeInfo::Array(elem_ty, n)); + + // take any trait methods that apply to this type and copy them to the new type + self.namespace + .insert_trait_implementation_for_type(self.engines, type_id); + + type_id + } + TypeInfo::Tuple(mut type_arguments) => { + for type_argument in type_arguments.iter_mut() { + type_argument.type_id = self + .resolve( + handler, + type_argument.type_id, + span, + enforce_type_arguments, + None, + mod_path, + ) + .unwrap_or_else(|err| { + self.engines + .te() + .insert(self.engines, TypeInfo::ErrorRecovery(err)) + }); + } + + let type_id = self + .engines + .te() + .insert(self.engines, TypeInfo::Tuple(type_arguments)); + + // take any trait methods that apply to this type and copy them to the new type + self.namespace + .insert_trait_implementation_for_type(self.engines, type_id); + + type_id + } + _ => type_id, + }; + Ok(type_id) + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn resolve_with_self( + &mut self, + handler: &Handler, + mut type_id: TypeId, + self_type: TypeId, + span: &Span, + enforce_type_arguments: EnforceTypeArguments, + type_info_prefix: Option<&Path>, + mod_path: &Path, + ) -> Result { + type_id.replace_self_type(self.engines, self_type); + self.resolve( + handler, + type_id, + span, + enforce_type_arguments, + type_info_prefix, + mod_path, + ) + } + /// Short-hand for calling [Root::resolve_type_with_self] on `root` with the `mod_path`. #[allow(clippy::too_many_arguments)] // TODO: remove lint bypass once private modules are no longer experimental pub(crate) fn resolve_type_with_self( @@ -333,15 +532,13 @@ impl<'a> TypeCheckContext<'a> { type_info_prefix: Option<&Path>, ) -> Result { let mod_path = self.namespace.mod_path.clone(); - self.engines.te().resolve_with_self( + self.resolve_with_self( handler, - self.engines, type_id, self_type, span, enforce_type_arguments, type_info_prefix, - self.namespace, &mod_path, ) } @@ -355,14 +552,12 @@ impl<'a> TypeCheckContext<'a> { type_info_prefix: Option<&Path>, ) -> Result { let mod_path = self.namespace.mod_path.clone(); - self.engines.te().resolve( + self.resolve( handler, - self.engines, type_id, span, EnforceTypeArguments::Yes, type_info_prefix, - self.namespace, &mod_path, ) } @@ -373,14 +568,61 @@ impl<'a> TypeCheckContext<'a> { handler: &Handler, call_path: &CallPath, ) -> Result<&ty::TyDecl, ErrorEmitted> { - self.namespace.root.resolve_call_path_with_visibility_check( + self.resolve_call_path_with_visibility_check_and_modpath( handler, - self.engines, &self.namespace.mod_path, call_path, ) } + /// Resolve a symbol that is potentially prefixed with some path, e.g. `foo::bar::symbol`. + /// + /// This will concatenate the `mod_path` with the `call_path`'s prefixes and + /// then calling `resolve_symbol` with the resulting path and call_path's suffix. + /// + /// The `mod_path` is significant here as we assume the resolution is done within the + /// context of the module pointed to by `mod_path` and will only check the call path prefixes + /// and the symbol's own visibility + pub(crate) fn resolve_call_path_with_visibility_check_and_modpath( + &self, + handler: &Handler, + mod_path: &Path, + call_path: &CallPath, + ) -> Result<&ty::TyDecl, ErrorEmitted> { + let decl = self + .namespace + .root + .resolve_call_path(handler, mod_path, call_path)?; + + // In case there are no prefixes we don't need to check visibility + if call_path.prefixes.is_empty() { + return Ok(decl); + } + + // check the visibility of the call path elements + // we don't check the first prefix because direct children are always accessible + for prefix in iter_prefixes(&call_path.prefixes).skip(1) { + let module = self.namespace.root.check_submodule(handler, prefix)?; + if module.visibility.is_private() { + let prefix_last = prefix[prefix.len() - 1].clone(); + handler.emit_err(CompileError::ImportPrivateModule { + span: prefix_last.span(), + name: prefix_last, + }); + } + } + + // check the visibility of the symbol itself + if !decl.visibility(self.engines.de()).is_public() { + handler.emit_err(CompileError::ImportPrivateSymbol { + name: call_path.suffix.clone(), + span: call_path.suffix.span(), + }); + } + + Ok(decl) + } + /// Given a name and a type (plus a `self_type` to potentially /// resolve it), find items matching in the namespace. pub(crate) fn find_items_for_type( @@ -413,15 +655,13 @@ impl<'a> TypeCheckContext<'a> { type_id.replace_self_type(self.engines, self_type); // resolve the type - let type_id = type_engine + let type_id = self .resolve( handler, - self.engines, type_id, &item_name.span(), EnforceTypeArguments::No, None, - self.namespace, item_prefix, ) .unwrap_or_else(|err| type_engine.insert(self.engines, TypeInfo::ErrorRecovery(err))); @@ -863,4 +1103,163 @@ impl<'a> TypeCheckContext<'a> { .implemented_traits .get_items_for_type_and_trait_name(self.engines, type_id, &trait_name) } + + /// Given a `value` of type `T` that is able to be monomorphized and a set + /// of `type_arguments`, monomorphize `value` with the `type_arguments`. + /// + /// When this function is called, it is passed a `T` that is a copy of some + /// original declaration for `T` (let's denote the original with `[T]`). + /// Because monomorphization happens at application time (e.g. function + /// application), we want to be able to modify `value` such that type + /// checking the application of `value` affects only `T` and not `[T]`. + /// + /// So, at a high level, this function does two things. It 1) performs the + /// necessary work to refresh the relevant generic types in `T` so that they + /// are distinct from the generics of the same name in `[T]`. And it 2) + /// applies `type_arguments` (if any are provided) to the type parameters + /// of `value`, unifying the types. + /// + /// There are 4 cases that are handled in this function: + /// + /// 1. `value` does not have type parameters + `type_arguments` is empty: + /// 1a. return ok + /// 2. `value` has type parameters + `type_arguments` is empty: + /// 2a. if the [EnforceTypeArguments::Yes] variant is provided, then + /// error + /// 2b. refresh the generic types with a [TypeSubstMapping] + /// 3. `value` does have type parameters + `type_arguments` is nonempty: + /// 3a. error + /// 4. `value` has type parameters + `type_arguments` is nonempty: + /// 4a. check to see that the type parameters and `type_arguments` have + /// the same length + /// 4b. for each type argument in `type_arguments`, resolve the type + /// 4c. refresh the generic types with a [TypeSubstMapping] + #[allow(clippy::too_many_arguments)] + pub(crate) fn monomorphize_with_modpath( + &mut self, + handler: &Handler, + value: &mut T, + type_arguments: &mut [TypeArgument], + enforce_type_arguments: EnforceTypeArguments, + call_site_span: &Span, + mod_path: &Path, + ) -> Result<(), ErrorEmitted> + where + T: MonomorphizeHelper + SubstTypes, + { + match ( + value.type_parameters().is_empty(), + type_arguments.is_empty(), + ) { + (true, true) => Ok(()), + (false, true) => { + if let EnforceTypeArguments::Yes = enforce_type_arguments { + return Err(handler.emit_err(CompileError::NeedsTypeArguments { + name: value.name().clone(), + span: call_site_span.clone(), + })); + } + let type_mapping = + TypeSubstMap::from_type_parameters(self.engines, value.type_parameters()); + value.subst(&type_mapping, self.engines); + Ok(()) + } + (true, false) => { + let type_arguments_span = type_arguments + .iter() + .map(|x| x.span.clone()) + .reduce(Span::join) + .unwrap_or_else(|| value.name().span()); + Err(handler.emit_err(CompileError::DoesNotTakeTypeArguments { + name: value.name().clone(), + span: type_arguments_span, + })) + } + (false, false) => { + let type_arguments_span = type_arguments + .iter() + .map(|x| x.span.clone()) + .reduce(Span::join) + .unwrap_or_else(|| value.name().span()); + if value.type_parameters().len() != type_arguments.len() { + return Err( + handler.emit_err(CompileError::IncorrectNumberOfTypeArguments { + given: type_arguments.len(), + expected: value.type_parameters().len(), + span: type_arguments_span, + }), + ); + } + for type_argument in type_arguments.iter_mut() { + type_argument.type_id = self + .resolve( + handler, + type_argument.type_id, + &type_argument.span, + enforce_type_arguments, + None, + mod_path, + ) + .unwrap_or_else(|err| { + self.engines + .te() + .insert(self.engines, TypeInfo::ErrorRecovery(err)) + }); + } + let type_mapping = TypeSubstMap::from_type_parameters_and_type_arguments( + value + .type_parameters() + .iter() + .map(|type_param| type_param.type_id) + .collect(), + type_arguments + .iter() + .map(|type_arg| type_arg.type_id) + .collect(), + ); + value.subst(&type_mapping, self.engines); + Ok(()) + } + } + } +} + +pub(crate) trait MonomorphizeHelper { + fn name(&self) -> &Ident; + fn type_parameters(&self) -> &[TypeParameter]; +} + +/// This type is used to denote if, during monomorphization, the compiler +/// should enforce that type arguments be provided. An example of that +/// might be this: +/// +/// ```ignore +/// struct Point { +/// x: u64, +/// y: u64 +/// } +/// +/// fn add(p1: Point, p2: Point) -> Point { +/// Point { +/// x: p1.x + p2.x, +/// y: p1.y + p2.y +/// } +/// } +/// ``` +/// +/// `EnforeTypeArguments` would require that the type annotations +/// for `p1` and `p2` contain `<...>`. This is to avoid ambiguous definitions: +/// +/// ```ignore +/// fn add(p1: Point, p2: Point) -> Point { +/// Point { +/// x: p1.x + p2.x, +/// y: p1.y + p2.y +/// } +/// } +/// ``` +#[derive(Clone, Copy)] +pub(crate) enum EnforceTypeArguments { + Yes, + No, } diff --git a/sway-core/src/type_system/ast_elements/binding.rs b/sway-core/src/type_system/ast_elements/binding.rs index ffe92ee5560..fed0dd913dc 100644 --- a/sway-core/src/type_system/ast_elements/binding.rs +++ b/sway-core/src/type_system/ast_elements/binding.rs @@ -5,7 +5,7 @@ use crate::{ decl_engine::*, engine_threading::*, language::{ty, CallPath}, - semantic_analysis::TypeCheckContext, + semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::priv_prelude::*, Ident, }; diff --git a/sway-core/src/type_system/ast_elements/trait_constraint.rs b/sway-core/src/type_system/ast_elements/trait_constraint.rs index 22b519ca48c..c94c1e45aa2 100644 --- a/sway-core/src/type_system/ast_elements/trait_constraint.rs +++ b/sway-core/src/type_system/ast_elements/trait_constraint.rs @@ -14,6 +14,7 @@ use crate::{ language::{parsed::Supertrait, ty, CallPath}, semantic_analysis::{ declaration::{insert_supertraits_into_namespace, SupertraitOf}, + type_check_context::EnforceTypeArguments, TypeCheckContext, }, type_system::priv_prelude::*, diff --git a/sway-core/src/type_system/engine.rs b/sway-core/src/type_system/engine.rs index 3be8eefb432..2f6405c4285 100644 --- a/sway-core/src/type_system/engine.rs +++ b/sway-core/src/type_system/engine.rs @@ -7,12 +7,12 @@ use sway_types::integer_bits::IntegerBits; use crate::concurrent_slab::ListDisplay; use crate::{ - concurrent_slab::ConcurrentSlab, decl_engine::*, engine_threading::*, language::ty, - namespace::Path, type_system::priv_prelude::*, Namespace, + concurrent_slab::ConcurrentSlab, decl_engine::*, engine_threading::*, + type_system::priv_prelude::*, }; use sway_error::{error::CompileError, type_error::TypeError}; -use sway_types::{span::Span, Ident, Spanned}; +use sway_types::span::Span; #[derive(Debug, Default)] pub struct TypeEngine { @@ -61,125 +61,6 @@ impl TypeEngine { } } - /// Given a `value` of type `T` that is able to be monomorphized and a set - /// of `type_arguments`, monomorphize `value` with the `type_arguments`. - /// - /// When this function is called, it is passed a `T` that is a copy of some - /// original declaration for `T` (let's denote the original with `[T]`). - /// Because monomorphization happens at application time (e.g. function - /// application), we want to be able to modify `value` such that type - /// checking the application of `value` affects only `T` and not `[T]`. - /// - /// So, at a high level, this function does two things. It 1) performs the - /// necessary work to refresh the relevant generic types in `T` so that they - /// are distinct from the generics of the same name in `[T]`. And it 2) - /// applies `type_arguments` (if any are provided) to the type parameters - /// of `value`, unifying the types. - /// - /// There are 4 cases that are handled in this function: - /// - /// 1. `value` does not have type parameters + `type_arguments` is empty: - /// 1a. return ok - /// 2. `value` has type parameters + `type_arguments` is empty: - /// 2a. if the [EnforceTypeArguments::Yes] variant is provided, then - /// error - /// 2b. refresh the generic types with a [TypeSubstMapping] - /// 3. `value` does have type parameters + `type_arguments` is nonempty: - /// 3a. error - /// 4. `value` has type parameters + `type_arguments` is nonempty: - /// 4a. check to see that the type parameters and `type_arguments` have - /// the same length - /// 4b. for each type argument in `type_arguments`, resolve the type - /// 4c. refresh the generic types with a [TypeSubstMapping] - #[allow(clippy::too_many_arguments)] - pub(crate) fn monomorphize( - &self, - handler: &Handler, - engines: &Engines, - value: &mut T, - type_arguments: &mut [TypeArgument], - enforce_type_arguments: EnforceTypeArguments, - call_site_span: &Span, - namespace: &mut Namespace, - mod_path: &Path, - ) -> Result<(), ErrorEmitted> - where - T: MonomorphizeHelper + SubstTypes, - { - match ( - value.type_parameters().is_empty(), - type_arguments.is_empty(), - ) { - (true, true) => Ok(()), - (false, true) => { - if let EnforceTypeArguments::Yes = enforce_type_arguments { - return Err(handler.emit_err(CompileError::NeedsTypeArguments { - name: value.name().clone(), - span: call_site_span.clone(), - })); - } - let type_mapping = - TypeSubstMap::from_type_parameters(engines, value.type_parameters()); - value.subst(&type_mapping, engines); - Ok(()) - } - (true, false) => { - let type_arguments_span = type_arguments - .iter() - .map(|x| x.span.clone()) - .reduce(Span::join) - .unwrap_or_else(|| value.name().span()); - Err(handler.emit_err(CompileError::DoesNotTakeTypeArguments { - name: value.name().clone(), - span: type_arguments_span, - })) - } - (false, false) => { - let type_arguments_span = type_arguments - .iter() - .map(|x| x.span.clone()) - .reduce(Span::join) - .unwrap_or_else(|| value.name().span()); - if value.type_parameters().len() != type_arguments.len() { - return Err( - handler.emit_err(CompileError::IncorrectNumberOfTypeArguments { - given: type_arguments.len(), - expected: value.type_parameters().len(), - span: type_arguments_span, - }), - ); - } - for type_argument in type_arguments.iter_mut() { - type_argument.type_id = self - .resolve( - handler, - engines, - type_argument.type_id, - &type_argument.span, - enforce_type_arguments, - None, - namespace, - mod_path, - ) - .unwrap_or_else(|err| self.insert(engines, TypeInfo::ErrorRecovery(err))); - } - let type_mapping = TypeSubstMap::from_type_parameters_and_type_arguments( - value - .type_parameters() - .iter() - .map(|type_param| type_param.type_id) - .collect(), - type_arguments - .iter() - .map(|type_arg| type_arg.type_id) - .collect(), - ); - value.subst(&type_mapping, engines); - Ok(()) - } - } - } - /// Replace any instances of the [TypeInfo::SelfType] variant with /// `self_type` in both `received` and `expected`, then unify `received` and /// `expected`. @@ -375,204 +256,6 @@ impl TypeEngine { Ok(()) } - /// Resolve the type of the given [TypeId], replacing any instances of - /// [TypeInfo::Custom] with either a monomorphized struct, monomorphized - /// enum, or a reference to a type parameter. - #[allow(clippy::too_many_arguments)] - pub(crate) fn resolve( - &self, - handler: &Handler, - engines: &Engines, - type_id: TypeId, - span: &Span, - enforce_type_arguments: EnforceTypeArguments, - type_info_prefix: Option<&Path>, - namespace: &mut Namespace, - mod_path: &Path, - ) -> Result { - let decl_engine = engines.de(); - let module_path = type_info_prefix.unwrap_or(mod_path); - let type_id = match self.get(type_id) { - TypeInfo::Custom { - call_path, - type_arguments, - } => { - match namespace - .root() - .resolve_call_path_with_visibility_check( - handler, - engines, - module_path, - &call_path, - ) - .ok() - .cloned() - { - Some(ty::TyDecl::StructDecl(ty::StructDecl { - decl_id: original_id, - .. - })) => { - // get the copy from the declaration engine - let mut new_copy = decl_engine.get_struct(&original_id); - - // monomorphize the copy, in place - self.monomorphize( - handler, - engines, - &mut new_copy, - &mut type_arguments.unwrap_or_default(), - enforce_type_arguments, - span, - namespace, - mod_path, - )?; - - // insert the new copy in the decl engine - let new_decl_ref = decl_engine.insert(new_copy); - - // create the type id from the copy - let type_id = engines.te().insert(engines, TypeInfo::Struct(new_decl_ref)); - - // take any trait methods that apply to this type and copy them to the new type - namespace.insert_trait_implementation_for_type(engines, type_id); - - // return the id - type_id - } - Some(ty::TyDecl::EnumDecl(ty::EnumDecl { - decl_id: original_id, - .. - })) => { - // get the copy from the declaration engine - let mut new_copy = decl_engine.get_enum(&original_id); - - // monomorphize the copy, in place - self.monomorphize( - handler, - engines, - &mut new_copy, - &mut type_arguments.unwrap_or_default(), - enforce_type_arguments, - span, - namespace, - mod_path, - )?; - - // insert the new copy in the decl engine - let new_decl_ref = decl_engine.insert(new_copy); - - // create the type id from the copy - let type_id = engines.te().insert(engines, TypeInfo::Enum(new_decl_ref)); - - // take any trait methods that apply to this type and copy them to the new type - namespace.insert_trait_implementation_for_type(engines, type_id); - - // return the id - type_id - } - Some(ty::TyDecl::TypeAliasDecl(ty::TypeAliasDecl { - decl_id: original_id, - .. - })) => { - let new_copy = decl_engine.get_type_alias(&original_id); - - // TODO: monomorphize the copy, in place, when generic type aliases are - // supported - - let type_id = new_copy.create_type_id(engines); - namespace.insert_trait_implementation_for_type(engines, type_id); - - type_id - } - Some(ty::TyDecl::GenericTypeForFunctionScope( - ty::GenericTypeForFunctionScope { type_id, .. }, - )) => type_id, - _ => { - let err = handler.emit_err(CompileError::UnknownTypeName { - name: call_path.to_string(), - span: call_path.span(), - }); - self.insert(engines, TypeInfo::ErrorRecovery(err)) - } - } - } - TypeInfo::Array(mut elem_ty, n) => { - elem_ty.type_id = self - .resolve( - handler, - engines, - elem_ty.type_id, - span, - enforce_type_arguments, - None, - namespace, - mod_path, - ) - .unwrap_or_else(|err| self.insert(engines, TypeInfo::ErrorRecovery(err))); - - let type_id = self.insert(engines, TypeInfo::Array(elem_ty, n)); - - // take any trait methods that apply to this type and copy them to the new type - namespace.insert_trait_implementation_for_type(engines, type_id); - - type_id - } - TypeInfo::Tuple(mut type_arguments) => { - for type_argument in type_arguments.iter_mut() { - type_argument.type_id = self - .resolve( - handler, - engines, - type_argument.type_id, - span, - enforce_type_arguments, - None, - namespace, - mod_path, - ) - .unwrap_or_else(|err| self.insert(engines, TypeInfo::ErrorRecovery(err))); - } - - let type_id = self.insert(engines, TypeInfo::Tuple(type_arguments)); - - // take any trait methods that apply to this type and copy them to the new type - namespace.insert_trait_implementation_for_type(engines, type_id); - - type_id - } - _ => type_id, - }; - Ok(type_id) - } - - /// Replace any instances of the [TypeInfo::SelfType] variant with - /// `self_type` in `type_id`, then resolve `type_id`. - #[allow(clippy::too_many_arguments)] - pub(crate) fn resolve_with_self( - &self, - handler: &Handler, - engines: &Engines, - mut type_id: TypeId, - self_type: TypeId, - span: &Span, - enforce_type_arguments: EnforceTypeArguments, - type_info_prefix: Option<&Path>, - namespace: &mut Namespace, - mod_path: &Path, - ) -> Result { - type_id.replace_self_type(engines, self_type); - self.resolve( - handler, - engines, - type_id, - span, - enforce_type_arguments, - type_info_prefix, - namespace, - mod_path, - ) - } - /// Pretty print method for printing the [TypeEngine]. This method is /// manually implemented to avoid implementation overhead regarding using /// [DisplayWithEngines]. @@ -588,43 +271,3 @@ impl TypeEngine { builder } } - -pub(crate) trait MonomorphizeHelper { - fn name(&self) -> &Ident; - fn type_parameters(&self) -> &[TypeParameter]; -} - -/// This type is used to denote if, during monomorphization, the compiler -/// should enforce that type arguments be provided. An example of that -/// might be this: -/// -/// ```ignore -/// struct Point { -/// x: u64, -/// y: u64 -/// } -/// -/// fn add(p1: Point, p2: Point) -> Point { -/// Point { -/// x: p1.x + p2.x, -/// y: p1.y + p2.y -/// } -/// } -/// ``` -/// -/// `EnforeTypeArguments` would require that the type annotations -/// for `p1` and `p2` contain `<...>`. This is to avoid ambiguous definitions: -/// -/// ```ignore -/// fn add(p1: Point, p2: Point) -> Point { -/// Point { -/// x: p1.x + p2.x, -/// y: p1.y + p2.y -/// } -/// } -/// ``` -#[derive(Clone, Copy)] -pub(crate) enum EnforceTypeArguments { - Yes, - No, -} diff --git a/sway-core/src/type_system/priv_prelude.rs b/sway-core/src/type_system/priv_prelude.rs index e081db43eff..ed1d340582a 100644 --- a/sway-core/src/type_system/priv_prelude.rs +++ b/sway-core/src/type_system/priv_prelude.rs @@ -6,7 +6,6 @@ pub(crate) use super::{ create_type_id::CreateTypeId, replace_self_type::ReplaceSelfType, }, - engine::{EnforceTypeArguments, MonomorphizeHelper}, info::VecSet, substitute::{subst_list::SubstList, subst_map::TypeSubstMap, subst_types::SubstTypes}, unify::unify_check::UnifyCheck, From 6db645bed2657c90f3cdd5199c077e9b650a8347 Mon Sep 17 00:00:00 2001 From: Anton Trunov Date: Tue, 5 Sep 2023 12:52:55 +0400 Subject: [PATCH 2/2] `ctx.namespace.insert_trait_implementation_for_type` -> `ctx.insert_trait_implementation_for_type` --- .../ty/expression/expression_variant.rs | 3 +-- .../ast_node/expression/typed_expression.rs | 3 +-- .../typed_expression/function_application.rs | 4 +--- .../typed_expression/method_application.rs | 3 +-- .../src/semantic_analysis/namespace/items.rs | 8 ------- .../semantic_analysis/type_check_context.rs | 24 +++++++++---------- 6 files changed, 16 insertions(+), 29 deletions(-) diff --git a/sway-core/src/language/ty/expression/expression_variant.rs b/sway-core/src/language/ty/expression/expression_variant.rs index 7535add8316..06f93790f3c 100644 --- a/sway-core/src/language/ty/expression/expression_variant.rs +++ b/sway-core/src/language/ty/expression/expression_variant.rs @@ -940,8 +940,7 @@ impl ReplaceDecls for TyExpressionVariant { for type_param in method.type_parameters.iter() { let TypeParameter { type_id, .. } = type_param; - ctx.namespace - .insert_trait_implementation_for_type(engines, *type_id); + ctx.insert_trait_implementation_for_type(*type_id); } // Handle the trait constraints. This includes checking to see if the trait diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index a03a2bc31bf..311673757f0 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -991,8 +991,7 @@ impl ty::TyExpression { // take any trait items that apply to `StorageKey` and copy them to the // monomorphized type - ctx.namespace - .insert_trait_implementation_for_type(engines, access_type); + ctx.insert_trait_implementation_for_type(access_type); Ok(ty::TyExpression { expression: ty::TyExpressionVariant::StorageAccess(storage_access), diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs index 22bba240677..3bd7ffa7270 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs @@ -17,7 +17,6 @@ pub(crate) fn instantiate_function_application( span: Span, ) -> Result { let decl_engine = ctx.engines.de(); - let engines = ctx.engines(); let mut function_decl = decl_engine.get_function(&function_decl_ref); @@ -59,8 +58,7 @@ pub(crate) fn instantiate_function_application( // Retrieve the implemented traits for the type of the return type and // insert them in the broader namespace. - ctx.namespace - .insert_trait_implementation_for_type(engines, function_decl.return_type.type_id); + ctx.insert_trait_implementation_for_type(function_decl.return_type.type_id); // Handle the trait constraints. This includes checking to see if the trait // constraints are satisfied and replacing old decl ids based on the diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 1c92a5b98d0..7e9aa0bfec4 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -325,8 +325,7 @@ pub(crate) fn type_check_method_application( // Retrieve the implemented traits for the type of the return type and // insert them in the broader namespace. - ctx.namespace - .insert_trait_implementation_for_type(engines, method.return_type.type_id); + ctx.insert_trait_implementation_for_type(method.return_type.type_id); // Handle the trait constraints. This includes checking to see if the trait // constraints are satisfied and replacing old decl ids based on the diff --git a/sway-core/src/semantic_analysis/namespace/items.rs b/sway-core/src/semantic_analysis/namespace/items.rs index 5c4773b0970..31a04a5fef4 100644 --- a/sway-core/src/semantic_analysis/namespace/items.rs +++ b/sway-core/src/semantic_analysis/namespace/items.rs @@ -252,14 +252,6 @@ impl Items { }) } - pub(crate) fn insert_trait_implementation_for_type( - &mut self, - engines: &Engines, - type_id: TypeId, - ) { - self.implemented_traits.insert_for_type(engines, type_id); - } - pub fn get_items_for_type(&self, engines: &Engines, type_id: TypeId) -> Vec { self.implemented_traits.get_items_for_type(engines, type_id) } diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index f5d97e3f7f2..2ba28bcb033 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -373,8 +373,7 @@ impl<'a> TypeCheckContext<'a> { type_engine.insert(self.engines, TypeInfo::Struct(new_decl_ref)); // take any trait methods that apply to this type and copy them to the new type - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); // return the id type_id @@ -404,8 +403,7 @@ impl<'a> TypeCheckContext<'a> { type_engine.insert(self.engines, TypeInfo::Enum(new_decl_ref)); // take any trait methods that apply to this type and copy them to the new type - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); // return the id type_id @@ -420,8 +418,7 @@ impl<'a> TypeCheckContext<'a> { // supported let type_id = new_copy.create_type_id(self.engines); - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); type_id } @@ -459,8 +456,7 @@ impl<'a> TypeCheckContext<'a> { .insert(self.engines, TypeInfo::Array(elem_ty, n)); // take any trait methods that apply to this type and copy them to the new type - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); type_id } @@ -488,8 +484,7 @@ impl<'a> TypeCheckContext<'a> { .insert(self.engines, TypeInfo::Tuple(type_arguments)); // take any trait methods that apply to this type and copy them to the new type - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); type_id } @@ -910,8 +905,7 @@ impl<'a> TypeCheckContext<'a> { // insert_trait_implementation_for_type is already called when we do type check of structs, enums, arrays and tuples. // In cases such as blanket trait implementation and usage of builtin types a method may not be found because // insert_trait_implementation_for_type has yet to be called for that type. - self.namespace - .insert_trait_implementation_for_type(self.engines, type_id); + self.insert_trait_implementation_for_type(type_id); return self.find_method_for_type( handler, @@ -1222,6 +1216,12 @@ impl<'a> TypeCheckContext<'a> { } } } + + pub(crate) fn insert_trait_implementation_for_type(&mut self, type_id: TypeId) { + self.namespace + .implemented_traits + .insert_for_type(self.engines, type_id); + } } pub(crate) trait MonomorphizeHelper {