diff --git a/sway-core/src/semantic_analysis/ast_node/code_block.rs b/sway-core/src/semantic_analysis/ast_node/code_block.rs index 91bdc79e5d0..951181b7274 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -10,26 +10,22 @@ use crate::{ impl ty::TyCodeBlock { pub(crate) fn type_check( handler: &Handler, - mut ctx: TypeCheckContext, + ctx: TypeCheckContext, code_block: &CodeBlock, ) -> Result { - // Create a temp namespace for checking within the code block scope. - let mut code_block_namespace = ctx.namespace().clone(); - let evaluated_contents = code_block - .contents - .iter() - .filter_map(|node| { - ctx.by_ref() - .scoped(&mut code_block_namespace, |ctx| { - ty::TyAstNode::type_check(handler, ctx, node.clone()) - }) - .ok() - }) - .collect::>(); + ctx.scoped(|mut ctx| { + let evaluated_contents = code_block + .contents + .iter() + .filter_map(|node| { + ty::TyAstNode::type_check(handler, ctx.by_ref(), node.clone()).ok() + }) + .collect::>(); - Ok(ty::TyCodeBlock { - contents: evaluated_contents, - whole_block_span: code_block.whole_block_span.clone(), + Ok(ty::TyCodeBlock { + contents: evaluated_contents, + whole_block_span: code_block.whole_block_span.clone(), + }) }) } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs index 9c75657209f..f5486fd1d64 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -53,10 +53,9 @@ impl ty::TyAbiDecl { let self_type_id = self_type_param.type_id; // A temporary namespace for checking within this scope. - let mut abi_namespace = ctx.namespace().clone(); ctx.with_abi_mode(AbiMode::ImplAbiFn(name.clone(), None)) .with_self_type(Some(self_type_id)) - .scoped(&mut abi_namespace, |mut ctx| { + .scoped(|mut ctx| { // Insert the "self" type param into the namespace. self_type_param.insert_self_type_into_namespace(handler, ctx.by_ref()); 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 1de3df81611..b693c96513c 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs @@ -22,8 +22,7 @@ impl ty::TyEnumDecl { } = decl; // create a namespace for the decl, used to create a scope for generics - let mut decl_namespace = ctx.namespace().clone(); - ctx.scoped(&mut decl_namespace, |mut ctx| { + ctx.scoped(|mut ctx| { // Type check the type parameters. let new_type_parameters = TypeParameter::type_check_type_params( handler, 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 1b1f6978ecc..f15dbeabc67 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs @@ -80,12 +80,11 @@ impl ty::TyFunctionDecl { } // create a namespace for the function - let mut fn_namespace = ctx.namespace().clone(); ctx.by_ref() .with_purity(*purity) .with_const_shadowing_mode(ConstShadowingMode::Sequential) .disallow_functions() - .scoped(&mut fn_namespace, |mut ctx| { + .scoped(|mut ctx| { // Type check the type parameters. let new_type_parameters = TypeParameter::type_check_type_params( handler, @@ -171,12 +170,11 @@ impl ty::TyFunctionDecl { ty_fn_decl: &mut Self, ) -> Result { // create a namespace for the function - let mut fn_namespace = ctx.namespace().clone(); ctx.by_ref() .with_purity(ty_fn_decl.purity) .with_const_shadowing_mode(ConstShadowingMode::Sequential) .disallow_functions() - .scoped(&mut fn_namespace, |mut ctx| { + .scoped(|mut ctx| { let FunctionDeclaration { body, .. } = fn_decl; let ty::TyFunctionDecl { 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 829d0484fb5..174abc6254d 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 @@ -50,12 +50,11 @@ impl TyImplTrait { let self_type_id = self_type_param.type_id; // create a namespace for the impl - let mut impl_namespace = ctx.namespace().clone(); ctx.by_ref() .with_const_shadowing_mode(ConstShadowingMode::ItemStyle) .with_self_type(Some(self_type_id)) .allow_functions() - .scoped(&mut impl_namespace, |mut ctx| { + .scoped(|mut ctx| { // Type check the type parameters let new_impl_type_parameters = TypeParameter::type_check_type_params( handler, @@ -292,10 +291,9 @@ impl TyImplTrait { let engines = ctx.engines(); // create the namespace for the impl - let mut impl_namespace = ctx.namespace().clone(); ctx.with_const_shadowing_mode(ConstShadowingMode::ItemStyle) .allow_functions() - .scoped(&mut impl_namespace, |mut ctx| { + .scoped(|mut ctx| { // Create a new type parameter for the "self type". let self_type_param = TypeParameter::new_self_type(engines, implementing_for.span()); 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 c931e59ef63..66203ec7079 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs @@ -22,8 +22,7 @@ impl ty::TyStructDecl { } = decl; // create a namespace for the decl, used to create a scope for generics - let mut decl_namespace = ctx.namespace().clone(); - ctx.scoped(&mut decl_namespace, |mut ctx| { + ctx.scoped(|mut ctx| { // Type check the type parameters. let new_type_parameters = TypeParameter::type_check_type_params( handler, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs index 1df04a387d0..c0adf6b5c40 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -55,181 +55,176 @@ impl TyTraitDecl { let self_type = self_type_param.type_id; // A temporary namespace for checking within the trait's scope. - let mut trait_namespace = ctx.namespace().clone(); - ctx.with_self_type(Some(self_type)) - .scoped(&mut trait_namespace, |mut ctx| { - // Type check the type parameters. - let new_type_parameters = TypeParameter::type_check_type_params( - handler, - ctx.by_ref(), - type_parameters, - Some(self_type_param.clone()), - )?; + ctx.with_self_type(Some(self_type)).scoped(|mut ctx| { + // Type check the type parameters. + let new_type_parameters = TypeParameter::type_check_type_params( + handler, + ctx.by_ref(), + type_parameters, + Some(self_type_param.clone()), + )?; + + // Recursively make the interface surfaces and methods of the + // supertraits available to this trait. + insert_supertraits_into_namespace( + handler, + ctx.by_ref(), + self_type, + &supertraits, + &SupertraitOf::Trait, + )?; + + // type check the interface surface + let mut new_interface_surface = vec![]; + let mut dummy_interface_surface = vec![]; + + let mut ids: HashSet = HashSet::default(); + + for item in interface_surface.clone().into_iter() { + let decl_name = match item { + TraitItem::TraitFn(_) => None, + TraitItem::Constant(_) => None, + TraitItem::Type(decl_id) => { + let type_decl = engines.pe().get_trait_type(&decl_id).as_ref().clone(); + let type_decl = + ty::TyTraitType::type_check(handler, ctx.by_ref(), type_decl.clone())?; + let decl_ref = decl_engine.insert(type_decl.clone()); + dummy_interface_surface.push(ty::TyImplItem::Type(decl_ref.clone())); + new_interface_surface + .push(ty::TyTraitInterfaceItem::Type(decl_ref.clone())); + + Some(type_decl.name) + } + TraitItem::Error(_, _) => None, + }; - // Recursively make the interface surfaces and methods of the - // supertraits available to this trait. - insert_supertraits_into_namespace( - handler, - ctx.by_ref(), - self_type, - &supertraits, - &SupertraitOf::Trait, - )?; - - // type check the interface surface - let mut new_interface_surface = vec![]; - let mut dummy_interface_surface = vec![]; - - let mut ids: HashSet = HashSet::default(); - - for item in interface_surface.clone().into_iter() { - let decl_name = match item { - TraitItem::TraitFn(_) => None, - TraitItem::Constant(_) => None, - TraitItem::Type(decl_id) => { - let type_decl = engines.pe().get_trait_type(&decl_id).as_ref().clone(); - let type_decl = ty::TyTraitType::type_check( - handler, - ctx.by_ref(), - type_decl.clone(), - )?; - let decl_ref = decl_engine.insert(type_decl.clone()); - dummy_interface_surface.push(ty::TyImplItem::Type(decl_ref.clone())); - new_interface_surface - .push(ty::TyTraitInterfaceItem::Type(decl_ref.clone())); - - Some(type_decl.name) - } - TraitItem::Error(_, _) => None, - }; - - if let Some(decl_name) = decl_name { - if !ids.insert(decl_name.clone()) { - handler.emit_err(CompileError::MultipleDefinitionsOfName { - name: decl_name.clone(), - span: decl_name.span(), - }); - } + if let Some(decl_name) = decl_name { + if !ids.insert(decl_name.clone()) { + handler.emit_err(CompileError::MultipleDefinitionsOfName { + name: decl_name.clone(), + span: decl_name.span(), + }); } } + } - // insert placeholder functions representing the interface surface - // to allow methods to use those functions - ctx.insert_trait_implementation( - handler, - CallPath { - prefixes: vec![], - suffix: name.clone(), - is_absolute: false, - }, - new_type_parameters.iter().map(|x| x.into()).collect(), - self_type, - &dummy_interface_surface, - &span, - None, - IsImplSelf::No, - IsExtendingExistingImpl::No, - )?; - let mut dummy_interface_surface = vec![]; - - for item in interface_surface.into_iter() { - let decl_name = match item { - TraitItem::TraitFn(method) => { - let method = ty::TyTraitFn::type_check(handler, ctx.by_ref(), method)?; - let decl_ref = decl_engine.insert(method.clone()); - dummy_interface_surface.push(ty::TyImplItem::Fn( - decl_engine - .insert(method.to_dummy_func(AbiMode::NonAbi, Some(self_type))) - .with_parent(decl_engine, (*decl_ref.id()).into()), - )); - new_interface_surface.push(ty::TyTraitInterfaceItem::TraitFn(decl_ref)); - Some(method.name.clone()) - } - TraitItem::Constant(decl_id) => { - let const_decl = engines.pe().get_constant(&decl_id).as_ref().clone(); - let const_decl = - ty::TyConstantDecl::type_check(handler, ctx.by_ref(), const_decl)?; - let decl_ref = ctx.engines.de().insert(const_decl.clone()); - new_interface_surface - .push(ty::TyTraitInterfaceItem::Constant(decl_ref.clone())); - - let const_name = const_decl.call_path.suffix.clone(); - ctx.insert_symbol( - handler, - const_name.clone(), - ty::TyDecl::ConstantDecl(ty::ConstantDecl { - name: const_name.clone(), - decl_id: *decl_ref.id(), - decl_span: const_decl.span.clone(), - }), - )?; - - Some(const_name) - } - TraitItem::Type(_) => None, - TraitItem::Error(_, _) => { - continue; - } - }; - - if let Some(decl_name) = decl_name { - if !ids.insert(decl_name.clone()) { - handler.emit_err(CompileError::MultipleDefinitionsOfName { - name: decl_name.clone(), - span: decl_name.span(), - }); - } + // insert placeholder functions representing the interface surface + // to allow methods to use those functions + ctx.insert_trait_implementation( + handler, + CallPath { + prefixes: vec![], + suffix: name.clone(), + is_absolute: false, + }, + new_type_parameters.iter().map(|x| x.into()).collect(), + self_type, + &dummy_interface_surface, + &span, + None, + IsImplSelf::No, + IsExtendingExistingImpl::No, + )?; + let mut dummy_interface_surface = vec![]; + + for item in interface_surface.into_iter() { + let decl_name = match item { + TraitItem::TraitFn(method) => { + let method = ty::TyTraitFn::type_check(handler, ctx.by_ref(), method)?; + let decl_ref = decl_engine.insert(method.clone()); + dummy_interface_surface.push(ty::TyImplItem::Fn( + decl_engine + .insert(method.to_dummy_func(AbiMode::NonAbi, Some(self_type))) + .with_parent(decl_engine, (*decl_ref.id()).into()), + )); + new_interface_surface.push(ty::TyTraitInterfaceItem::TraitFn(decl_ref)); + Some(method.name.clone()) + } + TraitItem::Constant(decl_id) => { + let const_decl = engines.pe().get_constant(&decl_id).as_ref().clone(); + let const_decl = + ty::TyConstantDecl::type_check(handler, ctx.by_ref(), const_decl)?; + let decl_ref = ctx.engines.de().insert(const_decl.clone()); + new_interface_surface + .push(ty::TyTraitInterfaceItem::Constant(decl_ref.clone())); + + let const_name = const_decl.call_path.suffix.clone(); + ctx.insert_symbol( + handler, + const_name.clone(), + ty::TyDecl::ConstantDecl(ty::ConstantDecl { + name: const_name.clone(), + decl_id: *decl_ref.id(), + decl_span: const_decl.span.clone(), + }), + )?; + + Some(const_name) + } + TraitItem::Type(_) => None, + TraitItem::Error(_, _) => { + continue; + } + }; + + if let Some(decl_name) = decl_name { + if !ids.insert(decl_name.clone()) { + handler.emit_err(CompileError::MultipleDefinitionsOfName { + name: decl_name.clone(), + span: decl_name.span(), + }); } } + } - // insert placeholder functions representing the interface surface - // to allow methods to use those functions - ctx.insert_trait_implementation( + // insert placeholder functions representing the interface surface + // to allow methods to use those functions + ctx.insert_trait_implementation( + handler, + CallPath { + prefixes: vec![], + suffix: name.clone(), + is_absolute: false, + }, + new_type_parameters.iter().map(|x| x.into()).collect(), + self_type, + &dummy_interface_surface, + &span, + None, + IsImplSelf::No, + IsExtendingExistingImpl::Yes, + )?; + + // Type check the items. + let mut new_items = vec![]; + for method_decl_id in methods.into_iter() { + let method = engines.pe().get_function(&method_decl_id); + let method = ty::TyFunctionDecl::type_check( handler, - CallPath { - prefixes: vec![], - suffix: name.clone(), - is_absolute: false, - }, - new_type_parameters.iter().map(|x| x.into()).collect(), - self_type, - &dummy_interface_surface, - &span, - None, - IsImplSelf::No, - IsExtendingExistingImpl::Yes, - )?; - - // Type check the items. - let mut new_items = vec![]; - for method_decl_id in methods.into_iter() { - let method = engines.pe().get_function(&method_decl_id); - let method = ty::TyFunctionDecl::type_check( - handler, - ctx.by_ref(), - &method, - true, - false, - Some(self_type_param.type_id), - ) - .unwrap_or_else(|_| ty::TyFunctionDecl::error(&method)); - new_items.push(ty::TyTraitItem::Fn(decl_engine.insert(method))); - } + ctx.by_ref(), + &method, + true, + false, + Some(self_type_param.type_id), + ) + .unwrap_or_else(|_| ty::TyFunctionDecl::error(&method)); + new_items.push(ty::TyTraitItem::Fn(decl_engine.insert(method))); + } - let typed_trait_decl = ty::TyTraitDecl { - name: name.clone(), - type_parameters: new_type_parameters, - self_type: self_type_param, - interface_surface: new_interface_surface, - items: new_items, - supertraits, - visibility, - attributes, - call_path: CallPath::from(name).to_fullpath(ctx.namespace()), - span, - }; - Ok(typed_trait_decl) - }) + let typed_trait_decl = ty::TyTraitDecl { + name: name.clone(), + type_parameters: new_type_parameters, + self_type: self_type_param, + interface_surface: new_interface_surface, + items: new_items, + supertraits, + visibility, + attributes, + call_path: CallPath::from(name).to_fullpath(ctx.namespace()), + span, + }; + Ok(typed_trait_decl) + }) } /// Retrieves the interface surface and implemented items for this trait. 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 56a53c78b7f..82b68a70577 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 @@ -31,51 +31,48 @@ impl ty::TyTraitFn { let engines = ctx.engines(); // Create a namespace for the trait function. - let mut fn_namespace = ctx.namespace().clone(); - ctx.by_ref() - .with_purity(purity) - .scoped(&mut fn_namespace, |mut ctx| { - // TODO: when we add type parameters to trait fns, type check them here + ctx.by_ref().with_purity(purity).scoped(|mut ctx| { + // TODO: when we add type parameters to trait fns, type check them here - // Type check the parameters. - let mut typed_parameters = vec![]; - for param in parameters.into_iter() { - typed_parameters.push( - match ty::TyFunctionParameter::type_check_interface_parameter( - handler, - ctx.by_ref(), - param, - ) { - Ok(res) => res, - Err(_) => continue, - }, - ); - } - - // Type check the return type. - return_type.type_id = ctx - .resolve_type( + // Type check the parameters. + let mut typed_parameters = vec![]; + for param in parameters.into_iter() { + typed_parameters.push( + match ty::TyFunctionParameter::type_check_interface_parameter( handler, - return_type.type_id, - &return_type.span, - EnforceTypeArguments::Yes, - None, - ) - .unwrap_or_else(|err| { - type_engine.insert(engines, TypeInfo::ErrorRecovery(err), None) - }); + ctx.by_ref(), + param, + ) { + Ok(res) => res, + Err(_) => continue, + }, + ); + } + + // Type check the return type. + return_type.type_id = ctx + .resolve_type( + handler, + return_type.type_id, + &return_type.span, + EnforceTypeArguments::Yes, + None, + ) + .unwrap_or_else(|err| { + type_engine.insert(engines, TypeInfo::ErrorRecovery(err), None) + }); - let trait_fn = ty::TyTraitFn { - name, - span, - parameters: typed_parameters, - return_type, - purity, - attributes, - }; + let trait_fn = ty::TyTraitFn { + name, + span, + parameters: typed_parameters, + return_type, + purity, + attributes, + }; - Ok(trait_fn) - }) + Ok(trait_fn) + }) } /// This function is used in trait declarations to insert "placeholder" diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs index bcaa5eb52b4..c4e3db9b386 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs @@ -87,8 +87,7 @@ impl ty::TyMatchBranch { )?; // create a new namespace for this branch result - let mut namespace = ctx.namespace().clone(); - ctx.scoped(&mut namespace, |mut branch_ctx| { + ctx.scoped(|mut branch_ctx| { // for every variable that comes into result block, create a variable declaration, // insert it into the branch namespace, and add it to the block of code statements let mut code_block_contents: Vec = vec![]; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs index ed34b3d89fb..9f415035b65 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs @@ -146,8 +146,7 @@ impl ty::TyMatchExpression { }; } let ctx = ctx.by_ref().with_type_annotation(self.return_type_id); - let mut namespace = ctx.namespace().clone(); - ctx.scoped(&mut namespace, |mut branch_ctx| { + ctx.scoped(|mut branch_ctx| { let result_span = result.span.clone(); let condition = condition .clone() 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 30af893e323..0e5353c0241 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 @@ -215,9 +215,8 @@ pub(crate) fn struct_instantiation( } } - let mut struct_namespace = ctx.namespace().clone(); ctx.with_generic_shadowing_mode(GenericShadowingMode::Allow) - .scoped(&mut struct_namespace, |mut struct_ctx| { + .scoped(|mut struct_ctx| { // Insert struct type parameter into namespace. // This is required so check_type_parameter_bounds can resolve generic trait type parameters. for type_parameter in struct_decl.type_parameters { diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 89142a57b29..e99acc22e87 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -178,11 +178,11 @@ impl<'a> TypeCheckContext<'a> { /// Scope the `TypeCheckContext` with the given `Namespace`. pub fn scoped( self, - namespace: &'a mut Namespace, with_scoped_ctx: impl FnOnce(TypeCheckContext) -> Result, ) -> Result { + let mut namespace = self.namespace.clone(); let ctx = TypeCheckContext { - namespace, + namespace: &mut namespace, type_annotation: self.type_annotation, function_type_annotation: self.function_type_annotation, unify_generic: self.unify_generic,