diff --git a/forc-plugins/forc-doc/src/render/item/type_anchor.rs b/forc-plugins/forc-doc/src/render/item/type_anchor.rs index 03fd446ef8f..1ef537fde72 100644 --- a/forc-plugins/forc-doc/src/render/item/type_anchor.rs +++ b/forc-plugins/forc-doc/src/render/item/type_anchor.rs @@ -119,9 +119,6 @@ pub(crate) fn render_type_anchor( TypeInfo::Custom { call_path, .. } => Ok(box_html! { : call_path.suffix.as_str(); }), - TypeInfo::SelfType => Ok(box_html! { - : "Self"; - }), TypeInfo::B256 => Ok(box_html! { : "b256"; }), diff --git a/sway-core/src/abi_generation/evm_abi.rs b/sway-core/src/abi_generation/evm_abi.rs index 8698a3b67f9..3db31e7a4da 100644 --- a/sway-core/src/abi_generation/evm_abi.rs +++ b/sway-core/src/abi_generation/evm_abi.rs @@ -102,7 +102,6 @@ pub fn abi_str(type_info: &TypeInfo, type_engine: &TypeEngine, decl_engine: &Dec .collect::>(); format!("({})", field_strs.join(", ")) } - SelfType => "Self".into(), B256 => "uint256".into(), Numeric => "u64".into(), // u64 is the default Contract => "contract".into(), diff --git a/sway-core/src/abi_generation/fuel_abi.rs b/sway-core/src/abi_generation/fuel_abi.rs index 11f3780b535..344fb0f69c1 100644 --- a/sway-core/src/abi_generation/fuel_abi.rs +++ b/sway-core/src/abi_generation/fuel_abi.rs @@ -807,7 +807,6 @@ impl TypeInfo { .collect::>(); format!("({})", field_strs.join(", ")) } - SelfType => "Self".into(), B256 => "b256".into(), Numeric => "u64".into(), // u64 is the default Contract => "contract".into(), diff --git a/sway-core/src/control_flow_analysis/dead_code_analysis.rs b/sway-core/src/control_flow_analysis/dead_code_analysis.rs index 2e72b290ea6..e907eceab3e 100644 --- a/sway-core/src/control_flow_analysis/dead_code_analysis.rs +++ b/sway-core/src/control_flow_analysis/dead_code_analysis.rs @@ -922,10 +922,10 @@ fn connect_typed_fn_decl<'eng: 'cfg, 'cfg>( for fn_param in fn_decl.parameters.iter() { let fn_param_node = graph.add_node(ControlFlowGraphNode::FunctionParameter { param_name: fn_param.name.clone(), - is_self: matches!( - type_engine.get(fn_param.type_argument.initial_type_id), - TypeInfo::SelfType - ), + is_self: engines + .te() + .get(fn_param.type_argument.initial_type_id) + .is_self_type(), }); graph.add_edge(entry_node, fn_param_node, "".into()); diff --git a/sway-core/src/decl_engine/id.rs b/sway-core/src/decl_engine/id.rs index b7976ae85cc..d676c7ad51d 100644 --- a/sway-core/src/decl_engine/id.rs +++ b/sway-core/src/decl_engine/id.rs @@ -134,6 +134,7 @@ impl SubstTypes for DeclId { decl_engine.replace(*self, decl); } } + impl SubstTypes for DeclId { fn subst_inner(&mut self, type_mapping: &TypeSubstMap, engines: &Engines) { let decl_engine = engines.de(); @@ -142,68 +143,3 @@ impl SubstTypes for DeclId { decl_engine.replace(*self, decl); } } - -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} -impl ReplaceSelfType for DeclId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(self); - decl.replace_self_type(engines, self_type); - decl_engine.replace(*self, decl); - } -} diff --git a/sway-core/src/decl_engine/mapping.rs b/sway-core/src/decl_engine/mapping.rs index c2d6a3c5f17..9105c5710e9 100644 --- a/sway-core/src/decl_engine/mapping.rs +++ b/sway-core/src/decl_engine/mapping.rs @@ -56,6 +56,16 @@ impl fmt::Debug for DeclMapping { } impl DeclMapping { + pub(crate) fn new() -> Self { + Self { + mapping: Vec::new(), + } + } + + pub(crate) fn insert(&mut self, k: SourceDecl, v: DestinationDecl) { + self.mapping.push((k, v)) + } + pub(crate) fn is_empty(&self) -> bool { self.mapping.is_empty() } diff --git a/sway-core/src/decl_engine/ref.rs b/sway-core/src/decl_engine/ref.rs index b299ea5b649..13371cf3bd0 100644 --- a/sway-core/src/decl_engine/ref.rs +++ b/sway-core/src/decl_engine/ref.rs @@ -119,22 +119,6 @@ where decl_engine.insert(decl) } } -impl DeclRef> -where - DeclEngine: DeclEngineIndex, - T: Named + Spanned + ReplaceSelfType, -{ - pub(crate) fn replace_self_type_and_insert_new( - &self, - engines: &Engines, - self_type: TypeId, - ) -> Self { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(&self.id); - decl.replace_self_type(engines, self_type); - decl_engine.insert(decl) - } -} impl DeclRef> where @@ -170,30 +154,12 @@ where .with_parent(decl_engine, self.id.into()) } } + impl DeclRef> where AssociatedItemDeclId: From>, DeclEngine: DeclEngineIndex, - T: Named + Spanned + ReplaceSelfType, -{ - pub(crate) fn replace_self_type_and_insert_new_with_parent( - &self, - engines: &Engines, - self_type: TypeId, - ) -> Self { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(&self.id); - decl.replace_self_type(engines, self_type); - decl_engine - .insert(decl) - .with_parent(decl_engine, self.id.into()) - } -} -impl DeclRef> -where - AssociatedItemDeclId: From>, - DeclEngine: DeclEngineIndex, - T: Named + Spanned + ReplaceDecls, + T: Named + Spanned + ReplaceDecls + std::fmt::Debug, { pub(crate) fn replace_decls_and_insert_new_with_parent( &self, @@ -324,19 +290,6 @@ where } } -impl ReplaceSelfType for DeclRef> -where - DeclEngine: DeclEngineIndex, - T: Named + Spanned + ReplaceSelfType, -{ - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - let decl_engine = engines.de(); - let mut decl = decl_engine.get(&self.id); - decl.replace_self_type(engines, self_type); - decl_engine.replace(self.id, decl); - } -} - impl ReplaceDecls for DeclRefFunction { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/ir_generation/convert.rs b/sway-core/src/ir_generation/convert.rs index dbfd2ae5885..6474bf049f6 100644 --- a/sway-core/src/ir_generation/convert.rs +++ b/sway-core/src/ir_generation/convert.rs @@ -158,7 +158,6 @@ fn convert_resolved_type( // Unsupported types which shouldn't exist in the AST after type checking and // monomorphisation. TypeInfo::Custom { .. } => reject_type!("Custom"), - TypeInfo::SelfType { .. } => reject_type!("Self"), TypeInfo::Contract => reject_type!("Contract"), TypeInfo::ContractCaller { .. } => reject_type!("ContractCaller"), TypeInfo::Unknown => reject_type!("Unknown"), diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index 8dc3b755704..e7affe6409d 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -72,24 +72,6 @@ impl SubstTypes for TyAstNode { } } -impl ReplaceSelfType for TyAstNode { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - match self.content { - TyAstNodeContent::ImplicitReturnExpression(ref mut exp) => { - exp.replace_self_type(engines, self_type) - } - TyAstNodeContent::Declaration(ref mut decl) => { - decl.replace_self_type(engines, self_type) - } - TyAstNodeContent::Expression(ref mut expr) => { - expr.replace_self_type(engines, self_type) - } - TyAstNodeContent::SideEffect(_) => (), - TyAstNodeContent::Error(_, _) => (), - } - } -} - impl ReplaceDecls for TyAstNode { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/language/ty/code_block.rs b/sway-core/src/language/ty/code_block.rs index 4a62ab2907d..a0989e86222 100644 --- a/sway-core/src/language/ty/code_block.rs +++ b/sway-core/src/language/ty/code_block.rs @@ -34,14 +34,6 @@ impl SubstTypes for TyCodeBlock { } } -impl ReplaceSelfType for TyCodeBlock { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.contents - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} - impl ReplaceDecls for TyCodeBlock { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/language/ty/declaration/constant.rs b/sway-core/src/language/ty/declaration/constant.rs index 41f494dc5bc..ef0aec84868 100644 --- a/sway-core/src/language/ty/declaration/constant.rs +++ b/sway-core/src/language/ty/declaration/constant.rs @@ -94,16 +94,6 @@ impl SubstTypes for TyConstantDecl { } } -impl ReplaceSelfType for TyConstantDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.return_type.replace_self_type(engines, self_type); - self.type_ascription.replace_self_type(engines, self_type); - if let Some(expr) = &mut self.value { - expr.replace_self_type(engines, self_type); - } - } -} - impl ReplaceDecls for TyConstantDecl { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/language/ty/declaration/declaration.rs b/sway-core/src/language/ty/declaration/declaration.rs index af9a1857ef3..8c59763e86d 100644 --- a/sway-core/src/language/ty/declaration/declaration.rs +++ b/sway-core/src/language/ty/declaration/declaration.rs @@ -349,46 +349,6 @@ impl SubstTypes for TyDecl { } } -impl ReplaceSelfType for TyDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - match self { - TyDecl::VariableDecl(ref mut var_decl) => { - var_decl.replace_self_type(engines, self_type) - } - TyDecl::FunctionDecl(FunctionDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::TraitDecl(TraitDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::StructDecl(StructDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::EnumDecl(EnumDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::EnumVariantDecl(EnumVariantDecl { - ref mut enum_ref, .. - }) => enum_ref.replace_self_type(engines, self_type), - TyDecl::ImplTrait(ImplTrait { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::TypeAliasDecl(TypeAliasDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - TyDecl::TraitTypeDecl(TraitTypeDecl { - ref mut decl_id, .. - }) => decl_id.replace_self_type(engines, self_type), - // generics in an ABI is unsupported by design - TyDecl::AbiDecl(_) - | TyDecl::ConstantDecl(_) - | TyDecl::StorageDecl(_) - | TyDecl::GenericTypeForFunctionScope(_) - | TyDecl::ErrorRecovery(..) => (), - } - } -} - impl TyDecl { pub fn get_fun_decl_ref(&self) -> Option { if let TyDecl::FunctionDecl(FunctionDecl { @@ -613,6 +573,16 @@ impl TyDecl { .get(ty.type_id) .expect_enum(handler, engines, "", &span) } + // `Self` type parameter might resolve to an Enum + TyDecl::GenericTypeForFunctionScope(GenericTypeForFunctionScope { + type_id, .. + }) => match engines.te().get(*type_id) { + TypeInfo::Enum(r) => Ok(r), + _ => Err(handler.emit_err(CompileError::DeclIsNotAnEnum { + actually: self.friendly_type_name().to_string(), + span: self.span(), + })), + }, TyDecl::ErrorRecovery(_, err) => Err(*err), decl => Err(handler.emit_err(CompileError::DeclIsNotAnEnum { actually: decl.friendly_type_name().to_string(), diff --git a/sway-core/src/language/ty/declaration/enum.rs b/sway-core/src/language/ty/declaration/enum.rs index 741bf79d615..b5ceaea1c78 100644 --- a/sway-core/src/language/ty/declaration/enum.rs +++ b/sway-core/src/language/ty/declaration/enum.rs @@ -73,17 +73,6 @@ impl SubstTypes for TyEnumDecl { } } -impl ReplaceSelfType for TyEnumDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.variants - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.type_parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} - impl Spanned for TyEnumDecl { fn span(&self) -> Span { self.span.clone() @@ -98,6 +87,10 @@ impl MonomorphizeHelper for TyEnumDecl { fn name(&self) -> &Ident { &self.call_path.suffix } + + fn has_self_type_param(&self) -> bool { + false + } } impl TyEnumDecl { @@ -184,9 +177,3 @@ impl SubstTypes for TyEnumVariant { self.type_argument.subst_inner(type_mapping, engines); } } - -impl ReplaceSelfType for TyEnumVariant { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_argument.replace_self_type(engines, self_type); - } -} diff --git a/sway-core/src/language/ty/declaration/function.rs b/sway-core/src/language/ty/declaration/function.rs index 983c1b16a72..5c86ac5c1fe 100644 --- a/sway-core/src/language/ty/declaration/function.rs +++ b/sway-core/src/language/ty/declaration/function.rs @@ -121,19 +121,6 @@ impl SubstTypes for TyFunctionDecl { } } -impl ReplaceSelfType for TyFunctionDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.return_type.replace_self_type(engines, self_type); - self.body.replace_self_type(engines, self_type); - } -} - impl ReplaceDecls for TyFunctionDecl { fn replace_decls_inner( &mut self, @@ -159,6 +146,10 @@ impl MonomorphizeHelper for TyFunctionDecl { fn name(&self) -> &Ident { &self.name } + + fn has_self_type_param(&self) -> bool { + false + } } impl UnconstrainedTypeParameters for TyFunctionDecl { @@ -404,14 +395,6 @@ impl SubstTypes for TyFunctionParameter { } } -impl ReplaceSelfType for TyFunctionParameter { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_argument - .type_id - .replace_self_type(engines, self_type); - } -} - impl TyFunctionParameter { pub fn is_self(&self) -> bool { self.name.as_str() == "self" diff --git a/sway-core/src/language/ty/declaration/impl_trait.rs b/sway-core/src/language/ty/declaration/impl_trait.rs index 423a262400e..f8cddea7f05 100644 --- a/sway-core/src/language/ty/declaration/impl_trait.rs +++ b/sway-core/src/language/ty/declaration/impl_trait.rs @@ -82,15 +82,3 @@ impl SubstTypes for TyImplTrait { .for_each(|x| x.subst(type_mapping, engines)); } } - -impl ReplaceSelfType for TyImplTrait { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.impl_type_parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.implementing_for.replace_self_type(engines, self_type); - self.items - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} diff --git a/sway-core/src/language/ty/declaration/struct.rs b/sway-core/src/language/ty/declaration/struct.rs index 9d70f1b76d3..24145f24e0d 100644 --- a/sway-core/src/language/ty/declaration/struct.rs +++ b/sway-core/src/language/ty/declaration/struct.rs @@ -73,17 +73,6 @@ impl SubstTypes for TyStructDecl { } } -impl ReplaceSelfType for TyStructDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.fields - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.type_parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} - impl Spanned for TyStructDecl { fn span(&self) -> Span { self.span.clone() @@ -98,6 +87,10 @@ impl MonomorphizeHelper for TyStructDecl { fn name(&self) -> &Ident { &self.call_path.suffix } + + fn has_self_type_param(&self) -> bool { + false + } } impl TyStructDecl { @@ -192,9 +185,3 @@ impl SubstTypes for TyStructField { self.type_argument.subst_inner(type_mapping, engines); } } - -impl ReplaceSelfType for TyStructField { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_argument.replace_self_type(engines, self_type); - } -} diff --git a/sway-core/src/language/ty/declaration/trait.rs b/sway-core/src/language/ty/declaration/trait.rs index 974ce59262e..5e36366c315 100644 --- a/sway-core/src/language/ty/declaration/trait.rs +++ b/sway-core/src/language/ty/declaration/trait.rs @@ -5,8 +5,8 @@ use sway_types::{Ident, Named, Span, Spanned}; use crate::{ decl_engine::{ - DeclEngineReplace, DeclRefConstant, DeclRefFunction, DeclRefTraitFn, DeclRefTraitType, - ReplaceFunctionImplementingType, + mapping::DeclMapping, DeclEngineReplace, DeclRefConstant, DeclRefFunction, DeclRefTraitFn, + DeclRefTraitType, ReplaceFunctionImplementingType, }, engine_threading::*, language::{parsed, Visibility}, @@ -22,6 +22,7 @@ use super::TyDecl; pub struct TyTraitDecl { pub name: Ident, pub type_parameters: Vec, + pub self_type: TypeParameter, pub interface_surface: Vec, pub items: Vec, pub supertraits: Vec, @@ -73,6 +74,7 @@ impl HashWithEngines for TyTraitDecl { let TyTraitDecl { name, type_parameters, + self_type, interface_surface, items, supertraits, @@ -84,6 +86,7 @@ impl HashWithEngines for TyTraitDecl { } = self; name.hash(state); type_parameters.hash(state, engines); + self_type.hash(state, engines); interface_surface.hash(state, engines); items.hash(state, engines); supertraits.hash(state, engines); @@ -167,6 +170,7 @@ impl TypeCheckFinalization for TyTraitItem { impl SubstTypes for TyTraitDecl { fn subst_inner(&mut self, type_mapping: &TypeSubstMap, engines: &Engines) { + let mut decl_mapping = DeclMapping::new(); self.type_parameters .iter_mut() .for_each(|x| x.subst(type_mapping, engines)); @@ -177,12 +181,14 @@ impl SubstTypes for TyTraitDecl { let new_item_ref = item_ref .clone() .subst_types_and_insert_new_with_parent(type_mapping, engines); + decl_mapping.insert(item_ref.id().into(), new_item_ref.id().into()); item_ref.replace_id(*new_item_ref.id()); } TyTraitInterfaceItem::Constant(decl_ref) => { let new_decl_ref = decl_ref .clone() .subst_types_and_insert_new(type_mapping, engines); + decl_mapping.insert(decl_ref.id().into(), new_decl_ref.id().into()); decl_ref.replace_id(*new_decl_ref.id()); } TyTraitInterfaceItem::Type(decl_ref) => { @@ -225,80 +231,6 @@ impl SubstTypes for TyTraitItem { } } -impl ReplaceSelfType for TyTraitDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.interface_surface - .iter_mut() - .for_each(|item| match item { - TyTraitInterfaceItem::TraitFn(item_ref) => { - let new_item_ref = item_ref - .clone() - .replace_self_type_and_insert_new_with_parent(engines, self_type); - item_ref.replace_id(*new_item_ref.id()); - } - TyTraitInterfaceItem::Constant(decl_ref) => { - let new_decl_ref = decl_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - decl_ref.replace_id(*new_decl_ref.id()); - } - TyTraitInterfaceItem::Type(decl_ref) => { - let new_decl_ref = decl_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - decl_ref.replace_id(*new_decl_ref.id()); - } - }); - self.items.iter_mut().for_each(|item| match item { - TyTraitItem::Fn(item_ref) => { - let new_item_ref = item_ref - .clone() - .replace_self_type_and_insert_new_with_parent(engines, self_type); - item_ref.replace_id(*new_item_ref.id()); - } - TyTraitItem::Constant(item_ref) => { - let new_decl_ref = item_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - item_ref.replace_id(*new_decl_ref.id()); - } - TyTraitItem::Type(item_ref) => { - let new_decl_ref = item_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - item_ref.replace_id(*new_decl_ref.id()); - } - }); - } -} - -impl ReplaceSelfType for TyTraitInterfaceItem { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - match self { - TyTraitInterfaceItem::TraitFn(fn_decl) => fn_decl.replace_self_type(engines, self_type), - TyTraitInterfaceItem::Constant(const_decl) => { - const_decl.replace_self_type(engines, self_type) - } - TyTraitInterfaceItem::Type(type_decl) => { - type_decl.replace_self_type(engines, self_type) - } - } - } -} - -impl ReplaceSelfType for TyTraitItem { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - match self { - TyTraitItem::Fn(fn_decl) => fn_decl.replace_self_type(engines, self_type), - TyTraitItem::Constant(const_decl) => const_decl.replace_self_type(engines, self_type), - TyTraitItem::Type(type_decl) => type_decl.replace_self_type(engines, self_type), - } - } -} - impl ReplaceFunctionImplementingType for TyTraitItem { fn replace_implementing_type(&mut self, engines: &Engines, implementing_type: TyDecl) { match self { @@ -323,4 +255,8 @@ impl MonomorphizeHelper for TyTraitDecl { fn type_parameters(&self) -> &[TypeParameter] { &self.type_parameters } + + fn has_self_type_param(&self) -> bool { + true + } } diff --git a/sway-core/src/language/ty/declaration/trait_fn.rs b/sway-core/src/language/ty/declaration/trait_fn.rs index 3cbd5817de3..d4a53972bcb 100644 --- a/sway-core/src/language/ty/declaration/trait_fn.rs +++ b/sway-core/src/language/ty/declaration/trait_fn.rs @@ -85,15 +85,6 @@ impl SubstTypes for TyTraitFn { } } -impl ReplaceSelfType for TyTraitFn { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.parameters - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - self.return_type.replace_self_type(engines, self_type); - } -} - impl MonomorphizeHelper for TyTraitFn { fn name(&self) -> &Ident { &self.name @@ -102,4 +93,8 @@ impl MonomorphizeHelper for TyTraitFn { fn type_parameters(&self) -> &[TypeParameter] { &[] } + + fn has_self_type_param(&self) -> bool { + false + } } diff --git a/sway-core/src/language/ty/declaration/trait_type.rs b/sway-core/src/language/ty/declaration/trait_type.rs index 1b763387a41..143ed28de04 100644 --- a/sway-core/src/language/ty/declaration/trait_type.rs +++ b/sway-core/src/language/ty/declaration/trait_type.rs @@ -48,14 +48,6 @@ impl SubstTypes for TyTraitType { } } -impl ReplaceSelfType for TyTraitType { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - if let Some(ref mut ty) = self.ty { - ty.replace_self_type(engines, self_type); - } - } -} - impl Spanned for TyTraitType { fn span(&self) -> Span { self.span.clone() diff --git a/sway-core/src/language/ty/declaration/type_alias.rs b/sway-core/src/language/ty/declaration/type_alias.rs index 2c1829fcfc8..e94df224be5 100644 --- a/sway-core/src/language/ty/declaration/type_alias.rs +++ b/sway-core/src/language/ty/declaration/type_alias.rs @@ -51,12 +51,6 @@ impl SubstTypes for TyTypeAliasDecl { } } -impl ReplaceSelfType for TyTypeAliasDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.ty.replace_self_type(engines, self_type); - } -} - impl CreateTypeId for TyTypeAliasDecl { fn create_type_id(&self, engines: &Engines) -> TypeId { let type_engine = engines.te(); diff --git a/sway-core/src/language/ty/declaration/variable.rs b/sway-core/src/language/ty/declaration/variable.rs index 5c6250f06c8..3b885582326 100644 --- a/sway-core/src/language/ty/declaration/variable.rs +++ b/sway-core/src/language/ty/declaration/variable.rs @@ -59,14 +59,6 @@ impl SubstTypes for TyVariableDecl { } } -impl ReplaceSelfType for TyVariableDecl { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.return_type.replace_self_type(engines, self_type); - self.type_ascription.replace_self_type(engines, self_type); - self.body.replace_self_type(engines, self_type) - } -} - impl TypeCheckFinalization for TyVariableDecl { fn type_check_finalize( &mut self, diff --git a/sway-core/src/language/ty/expression/asm.rs b/sway-core/src/language/ty/expression/asm.rs index e7d6a5eafb2..b1e95610306 100644 --- a/sway-core/src/language/ty/expression/asm.rs +++ b/sway-core/src/language/ty/expression/asm.rs @@ -38,11 +38,3 @@ impl SubstTypes for TyAsmRegisterDeclaration { } } } - -impl ReplaceSelfType for TyAsmRegisterDeclaration { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - if let Some(ref mut initializer) = self.initializer { - initializer.replace_self_type(engines, self_type) - } - } -} diff --git a/sway-core/src/language/ty/expression/expression.rs b/sway-core/src/language/ty/expression/expression.rs index f639bdb7afd..da9704bc0ef 100644 --- a/sway-core/src/language/ty/expression/expression.rs +++ b/sway-core/src/language/ty/expression/expression.rs @@ -56,13 +56,6 @@ impl SubstTypes for TyExpression { } } -impl ReplaceSelfType for TyExpression { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.return_type.replace_self_type(engines, self_type); - self.expression.replace_self_type(engines, self_type); - } -} - impl ReplaceDecls for TyExpression { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/language/ty/expression/expression_variant.rs b/sway-core/src/language/ty/expression/expression_variant.rs index 401f58d9905..d629e96b156 100644 --- a/sway-core/src/language/ty/expression/expression_variant.rs +++ b/sway-core/src/language/ty/expression/expression_variant.rs @@ -749,144 +749,6 @@ impl SubstTypes for TyExpressionVariant { } } -impl ReplaceSelfType for TyExpressionVariant { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - use TyExpressionVariant::*; - match self { - Literal(..) => (), - FunctionApplication { - arguments, - ref mut fn_ref, - .. - } => { - arguments - .iter_mut() - .for_each(|(_ident, expr)| expr.replace_self_type(engines, self_type)); - let new_decl_ref = fn_ref - .clone() - .replace_self_type_and_insert_new_with_parent(engines, self_type); - fn_ref.replace_id(*new_decl_ref.id()); - } - LazyOperator { lhs, rhs, .. } => { - (*lhs).replace_self_type(engines, self_type); - (*rhs).replace_self_type(engines, self_type); - } - ConstantExpression { const_decl, .. } => { - const_decl.replace_self_type(engines, self_type) - } - VariableExpression { .. } => (), - Tuple { fields } => fields - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)), - Array { - ref mut elem_type, - contents, - } => { - elem_type.replace_self_type(engines, self_type); - contents - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)) - } - ArrayIndex { prefix, index } => { - (*prefix).replace_self_type(engines, self_type); - (*index).replace_self_type(engines, self_type); - } - StructExpression { - struct_ref, - fields, - instantiation_span: _, - call_path_binding: _, - } => { - let new_struct_ref = struct_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - struct_ref.replace_id(*new_struct_ref.id()); - fields - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } - CodeBlock(block) => { - block.replace_self_type(engines, self_type); - } - FunctionParameter => (), - MatchExp { desugared, .. } => desugared.replace_self_type(engines, self_type), - IfExp { - condition, - then, - r#else, - } => { - condition.replace_self_type(engines, self_type); - then.replace_self_type(engines, self_type); - if let Some(ref mut r#else) = r#else { - r#else.replace_self_type(engines, self_type); - } - } - AsmExpression { registers, .. } => { - registers - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } - StructFieldAccess { - prefix, - field_to_access, - ref mut resolved_type_of_parent, - .. - } => { - resolved_type_of_parent.replace_self_type(engines, self_type); - field_to_access.replace_self_type(engines, self_type); - prefix.replace_self_type(engines, self_type); - } - TupleElemAccess { - prefix, - ref mut resolved_type_of_parent, - .. - } => { - resolved_type_of_parent.replace_self_type(engines, self_type); - prefix.replace_self_type(engines, self_type); - } - EnumInstantiation { - enum_ref, contents, .. - } => { - let new_enum_ref = enum_ref - .clone() - .replace_self_type_and_insert_new(engines, self_type); - enum_ref.replace_id(*new_enum_ref.id()); - if let Some(ref mut contents) = contents { - contents.replace_self_type(engines, self_type) - }; - } - AbiCast { address, .. } => address.replace_self_type(engines, self_type), - StorageAccess { .. } => (), - IntrinsicFunction(kind) => { - kind.replace_self_type(engines, self_type); - } - EnumTag { exp } => { - exp.replace_self_type(engines, self_type); - } - UnsafeDowncast { - exp, - variant, - call_path_decl: _, - } => { - exp.replace_self_type(engines, self_type); - variant.replace_self_type(engines, self_type); - } - AbiName(_) => (), - WhileLoop { - ref mut condition, - ref mut body, - } => { - condition.replace_self_type(engines, self_type); - body.replace_self_type(engines, self_type); - } - Break => (), - Continue => (), - Reassignment(reassignment) => reassignment.replace_self_type(engines, self_type), - Return(stmt) => stmt.replace_self_type(engines, self_type), - } - } -} - impl ReplaceDecls for TyExpressionVariant { fn replace_decls_inner( &mut self, @@ -903,17 +765,7 @@ impl ReplaceDecls for TyExpressionVariant { ref mut arguments, .. } => { - let mut filter_type_opt = None; - if let Some(arg) = arguments.get(0) { - match ctx.engines.te().get(arg.1.return_type) { - TypeInfo::SelfType => { - filter_type_opt = Some(ctx.self_type()); - } - _ => { - filter_type_opt = Some(arg.1.return_type); - } - } - } + let filter_type_opt = arguments.get(0).map(|(_, arg)| arg.return_type); if let Some(filter_type) = filter_type_opt { let filtered_decl_mapping = diff --git a/sway-core/src/language/ty/expression/intrinsic_function.rs b/sway-core/src/language/ty/expression/intrinsic_function.rs index 4b25f4205fe..d0c16ec7463 100644 --- a/sway-core/src/language/ty/expression/intrinsic_function.rs +++ b/sway-core/src/language/ty/expression/intrinsic_function.rs @@ -55,17 +55,6 @@ impl SubstTypes for TyIntrinsicFunctionKind { } } -impl ReplaceSelfType for TyIntrinsicFunctionKind { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - for arg in &mut self.arguments { - arg.replace_self_type(engines, self_type); - } - for targ in &mut self.type_arguments { - targ.type_id.replace_self_type(engines, self_type); - } - } -} - impl DebugWithEngines for TyIntrinsicFunctionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { let targs = self diff --git a/sway-core/src/language/ty/expression/reassignment.rs b/sway-core/src/language/ty/expression/reassignment.rs index a55dd71c84c..3561bd69374 100644 --- a/sway-core/src/language/ty/expression/reassignment.rs +++ b/sway-core/src/language/ty/expression/reassignment.rs @@ -60,13 +60,6 @@ impl SubstTypes for TyReassignment { } } -impl ReplaceSelfType for TyReassignment { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.rhs.replace_self_type(engines, self_type); - self.lhs_type.replace_self_type(engines, self_type); - } -} - impl ReplaceDecls for TyReassignment { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/language/ty/expression/struct_exp_field.rs b/sway-core/src/language/ty/expression/struct_exp_field.rs index a4e5bc1f733..aca406f4ccb 100644 --- a/sway-core/src/language/ty/expression/struct_exp_field.rs +++ b/sway-core/src/language/ty/expression/struct_exp_field.rs @@ -38,12 +38,6 @@ impl SubstTypes for TyStructExpressionField { } } -impl ReplaceSelfType for TyStructExpressionField { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.value.replace_self_type(engines, self_type); - } -} - impl ReplaceDecls for TyStructExpressionField { fn replace_decls_inner( &mut self, diff --git a/sway-core/src/monomorphize/solve/solver.rs b/sway-core/src/monomorphize/solve/solver.rs index 910150d349e..9468e5d7ae1 100644 --- a/sway-core/src/monomorphize/solve/solver.rs +++ b/sway-core/src/monomorphize/solve/solver.rs @@ -132,7 +132,6 @@ impl<'a> Solver<'a> { } TypeInfo::ContractCaller { .. } => todo!(), TypeInfo::Custom { .. } => todo!(), - TypeInfo::SelfType => todo!(), TypeInfo::Numeric => todo!(), TypeInfo::ErrorRecovery(_) => todo!(), TypeInfo::Array(_, _) => todo!(), 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 645855e3a22..9167f7f641b 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -91,7 +91,7 @@ impl ty::TyCodeBlock { } }); - ctx.unify_with_self(handler, block_type, &span); + ctx.unify_with_type_annotation(handler, block_type, &span); let typed_code_block = ty::TyCodeBlock { contents: evaluated_contents, 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 e285d5598cc..90fe5c93a27 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -8,6 +8,7 @@ use crate::{ language::ty::TyAbiDecl, namespace::{IsExtendingExistingImpl, IsImplSelf, TryInsertingTraitImplOnFailure}, semantic_analysis::{TypeCheckFinalization, TypeCheckFinalizationContext}, + TypeParameter, }; use sway_error::handler::{ErrorEmitted, Handler}; @@ -21,7 +22,7 @@ use crate::{ semantic_analysis::{ declaration::insert_supertraits_into_namespace, AbiMode, TypeCheckContext, }, - ReplaceSelfType, TypeId, TypeInfo, + TypeId, }; impl ty::TyAbiDecl { @@ -45,20 +46,22 @@ impl ty::TyAbiDecl { // from itself. This is by design. // A temporary namespace for checking within this scope. - let type_engine = ctx.engines.te(); let mut abi_namespace = ctx.namespace.clone(); - let self_type = type_engine.insert(ctx.engines(), TypeInfo::SelfType); let mut ctx = ctx .scoped(&mut abi_namespace) - .with_abi_mode(AbiMode::ImplAbiFn(name.clone(), None)) - .with_self_type(self_type); + .with_abi_mode(AbiMode::ImplAbiFn(name.clone(), None)); + + // Insert the "self" type param into the namespace. + let self_type_param = TypeParameter::new_self_type(ctx.engines, name.span()); + let self_type_id = self_type_param.type_id; + self_type_param.insert_self_type_into_namespace(handler, ctx.by_ref()); // Recursively make the interface surfaces and methods of the // supertraits available to this abi. insert_supertraits_into_namespace( handler, ctx.by_ref(), - self_type, + self_type_id, &supertraits, &SupertraitOf::Abi(span.clone()), )?; @@ -72,10 +75,9 @@ impl ty::TyAbiDecl { |method_name: &Ident, ctx: &mut TypeCheckContext| { if let Ok(superabi_impl_method_ref) = ctx.find_method_for_type( &Handler::default(), - ctx.self_type(), + self_type_id, &[], &method_name.clone(), - ctx.self_type(), ctx.type_annotation(), &Default::default(), None, @@ -205,7 +207,6 @@ impl ty::TyAbiDecl { subabi_span: Option, ) -> Result<(), ErrorEmitted> { let decl_engine = ctx.engines.de(); - let engines = ctx.engines(); let ty::TyAbiDecl { interface_surface, @@ -225,15 +226,14 @@ impl ty::TyAbiDecl { for item in interface_surface.iter() { match item { ty::TyTraitInterfaceItem::TraitFn(decl_ref) => { - let mut method = decl_engine.get_trait_fn(decl_ref); + let method = decl_engine.get_trait_fn(decl_ref); if look_for_conflicting_abi_methods { // looking for conflicting ABI methods for triangle-like ABI hierarchies if let Ok(superabi_method_ref) = ctx.find_method_for_type( &Handler::default(), - ctx.self_type(), + type_id, &[], &method.name.clone(), - ctx.self_type(), ctx.type_annotation(), &Default::default(), None, @@ -268,7 +268,6 @@ impl ty::TyAbiDecl { } } } - method.replace_self_type(engines, type_id); all_items.push(TyImplItem::Fn( ctx.engines .de() @@ -316,16 +315,15 @@ impl ty::TyAbiDecl { for item in items.iter() { match item { ty::TyTraitItem::Fn(decl_ref) => { - let mut method = decl_engine.get_function(decl_ref); + let method = decl_engine.get_function(decl_ref); // check if we inherit the same impl method from different branches // XXX this piece of code can be abstracted out into a closure // and reused for interface methods if the issue of mutable ctx is solved if let Ok(superabi_impl_method_ref) = ctx.find_method_for_type( &Handler::default(), - ctx.self_type(), + type_id, &[], &method.name.clone(), - ctx.self_type(), ctx.type_annotation(), &Default::default(), None, @@ -347,7 +345,6 @@ impl ty::TyAbiDecl { } } } - method.replace_self_type(engines, type_id); all_items.push(TyImplItem::Fn( ctx.engines .de() @@ -356,13 +353,11 @@ impl ty::TyAbiDecl { )); } ty::TyTraitItem::Constant(decl_ref) => { - let mut const_decl = decl_engine.get_constant(decl_ref); - const_decl.replace_self_type(engines, type_id); + let const_decl = decl_engine.get_constant(decl_ref); all_items.push(TyImplItem::Constant(ctx.engines.de().insert(const_decl))); } ty::TyTraitItem::Type(decl_ref) => { - let mut type_decl = decl_engine.get_type(decl_ref); - type_decl.replace_self_type(engines, type_id); + let type_decl = decl_engine.get_type(decl_ref); all_items.push(TyImplItem::Type(ctx.engines.de().insert(type_decl))); } } 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 f7a476d8859..1196d9ea101 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs @@ -34,10 +34,9 @@ impl ty::TyConstantDecl { } = decl; type_ascription.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_ascription.type_id, - ctx.self_type(), &type_ascription.span, EnforceTypeArguments::No, None, 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 159c8520561..0e68de4eea9 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -33,10 +33,9 @@ impl TyDecl { is_mutable, }) => { type_ascription.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_ascription.type_id, - ctx.self_type(), &type_ascription.span, EnforceTypeArguments::Yes, None, @@ -302,10 +301,11 @@ impl TyDecl { .. } in fields { - type_argument.type_id = ctx.resolve_type_without_self( + type_argument.type_id = ctx.resolve_type( handler, type_argument.type_id, &name.span(), + EnforceTypeArguments::Yes, None, )?; @@ -343,14 +343,7 @@ impl TyDecl { // Resolve the type that the type alias replaces let new_ty = ctx - .resolve_type_with_self( - handler, - ty.type_id, - ctx.self_type(), - &span, - EnforceTypeArguments::Yes, - None, - ) + .resolve_type(handler, ty.type_id, &span, EnforceTypeArguments::Yes, None) .unwrap_or_else(|err| { type_engine.insert(engines, TypeInfo::ErrorRecovery(err)) }); 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 f319f0c3461..865e8e8d835 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs @@ -28,7 +28,7 @@ impl ty::TyEnumDecl { // Type check the type parameters. let new_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters)?; + TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters, None)?; // Insert them into the current namespace. for p in &new_type_parameters { @@ -72,10 +72,9 @@ impl ty::TyEnumVariant { let engines = ctx.engines(); let mut type_argument = variant.type_argument; type_argument.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_argument.type_id, - ctx.self_type(), &type_argument.span, EnforceTypeArguments::Yes, None, 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 96d3847a7ae..e1fbbf84de4 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs @@ -86,7 +86,7 @@ impl ty::TyFunctionDecl { // Type check the type parameters. let new_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters)?; + TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters, None)?; // Insert them into the current namespace. for p in &new_type_parameters { @@ -113,10 +113,9 @@ impl ty::TyFunctionDecl { // type check the return type return_type.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, return_type.type_id, - ctx.self_type(), &return_type.span, EnforceTypeArguments::Yes, None, @@ -260,12 +259,11 @@ fn unify_return_statements( handler.scope(|handler| { for stmt in return_statements.iter() { - type_engine.unify_with_self( + type_engine.unify( handler, ctx.engines(), stmt.return_type, return_type, - ctx.self_type(), &stmt.span, "Return statement must return the declared function return type.", None, 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 cf54789c046..833d067a755 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 @@ -28,10 +28,9 @@ impl ty::TyFunctionParameter { } = parameter; type_argument.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_argument.type_id, - ctx.self_type(), &type_argument.span, EnforceTypeArguments::Yes, None, @@ -83,10 +82,9 @@ impl ty::TyFunctionParameter { } = parameter; type_argument.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_argument.type_id, - ctx.self_type(), &type_argument.span, EnforceTypeArguments::Yes, None, 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 8af06692717..be70aaa484b 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 @@ -49,9 +49,17 @@ impl TyImplTrait { .with_const_shadowing_mode(ConstShadowingMode::ItemStyle) .allow_functions(); - // Type check the type parameters. - let new_impl_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), impl_type_parameters)?; + // Create a new type parameter for the Self type + let self_type_param = TypeParameter::new_self_type(engines, implementing_for.span()); + let self_type_id = self_type_param.type_id; + + // Type check the type parameters + let new_impl_type_parameters = TypeParameter::type_check_type_params( + handler, + ctx.by_ref(), + impl_type_parameters, + Some(self_type_param), + )?; // Insert them into the current namespace. for p in &new_impl_type_parameters { @@ -60,16 +68,22 @@ impl TyImplTrait { // resolve the types of the trait type arguments for type_arg in trait_type_arguments.iter_mut() { - type_arg.type_id = - ctx.resolve_type_without_self(handler, type_arg.type_id, &type_arg.span, None)?; + type_arg.type_id = ctx.resolve_type( + handler, + type_arg.type_id, + &type_arg.span, + EnforceTypeArguments::Yes, + None, + )?; } // type check the type that we are implementing for - implementing_for.type_id = ctx.resolve_type_without_self( + implementing_for.type_id = ctx.resolve_type( handler, implementing_for.type_id, &implementing_for.span, + EnforceTypeArguments::Yes, None, )?; @@ -87,9 +101,22 @@ impl TyImplTrait { implementing_for.type_id, )?; - // Update the context with the new `self` type. + // Unify the "self" type param and the type that we are implementing for + handler.scope(|h| { + type_engine.unify( + h, + engines, + implementing_for.type_id, + self_type_id, + &implementing_for.span, + "", + None, + ); + Ok(()) + })?; + + // Update the context let mut ctx = ctx - .with_self_type(implementing_for.type_id) .with_help_text("") .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown)); @@ -101,6 +128,13 @@ impl TyImplTrait { Some(ty::TyDecl::TraitDecl(ty::TraitDecl { decl_id, .. })) => { let mut trait_decl = decl_engine.get_trait(&decl_id); + // the following essentially is needed to map `Self` to `implementing_for` + // during trait decl monomorphization + trait_decl + .type_parameters + .push(trait_decl.self_type.clone()); + trait_type_arguments.push(implementing_for.clone()); + // monomorphize the trait declaration ctx.monomorphize( handler, @@ -110,6 +144,10 @@ impl TyImplTrait { &trait_name.span(), )?; + // restore type parameters and type arguments + trait_decl.type_parameters.pop(); + trait_type_arguments.pop(); + // Insert the interface surface and methods from this trait into // the namespace. trait_decl.insert_interface_surface_and_items_into_namespace( @@ -123,6 +161,7 @@ impl TyImplTrait { let new_items = type_check_trait_implementation( handler, ctx.by_ref(), + implementing_for.type_id, &new_impl_type_parameters, &trait_decl.type_parameters, &trait_type_arguments, @@ -167,6 +206,22 @@ impl TyImplTrait { }); } + let self_type_param = TypeParameter::new_self_type(engines, abi.span.clone()); + // Unify the "self" type param from the abi declaration with + // the type that we are implementing for. + handler.scope(|h| { + type_engine.unify( + h, + engines, + implementing_for.type_id, + self_type_param.type_id, + &implementing_for.span, + "", + None, + ); + Ok(()) + })?; + let mut ctx = ctx.with_abi_mode(AbiMode::ImplAbiFn(abi.name.clone(), None)); // Insert the interface surface and methods from this trait into @@ -182,6 +237,7 @@ impl TyImplTrait { let new_items = type_check_trait_implementation( handler, ctx.by_ref(), + implementing_for.type_id, &[], // this is empty because abi definitions don't support generics, &[], // this is empty because abi definitions don't support generics, &[], // this is empty because abi definitions don't support generics, @@ -238,6 +294,10 @@ impl TyImplTrait { .allow_functions() .with_defer_monomorphization(); + // Create a new type parameter for the "self type". + let self_type_param = TypeParameter::new_self_type(engines, implementing_for.span()); + let self_type_id = self_type_param.type_id; + // create the trait name let trait_name = CallPath { prefixes: vec![], @@ -249,8 +309,12 @@ impl TyImplTrait { }; // Type check the type parameters. - let new_impl_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), impl_type_parameters)?; + let new_impl_type_parameters = TypeParameter::type_check_type_params( + handler, + ctx.by_ref(), + impl_type_parameters, + Some(self_type_param), + )?; // Insert them into the current namespace. for p in &new_impl_type_parameters { @@ -258,10 +322,11 @@ impl TyImplTrait { } // type check the type that we are implementing for - implementing_for.type_id = ctx.resolve_type_without_self( + implementing_for.type_id = ctx.resolve_type( handler, implementing_for.type_id, &implementing_for.span, + EnforceTypeArguments::Yes, None, )?; @@ -286,21 +351,24 @@ impl TyImplTrait { vec![], )?; + // Unify the "self" type param and the type that we are implementing for + handler.scope(|h| { + type_engine.unify( + h, + engines, + implementing_for.type_id, + self_type_id, + &implementing_for.span, + "", + None, + ); + Ok(()) + })?; + let mut ctx = ctx - .with_self_type(implementing_for.type_id) .with_help_text("") .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown)); - // Insert implementing type decl as `Self` symbol. - let self_decl: Option = match type_engine.get(implementing_for.type_id) { - TypeInfo::Enum(r) => Some(r.into()), - TypeInfo::Struct(r) => Some(r.into()), - _ => None, - }; - if let Some(self_decl) = self_decl { - let _ = ctx.insert_symbol(handler, Ident::new_no_span("Self".to_string()), self_decl); - } - // type check the items inside of the impl block let mut new_items = vec![]; @@ -419,6 +487,7 @@ impl TyImplTrait { fn type_check_trait_implementation( handler: &Handler, mut ctx: TypeCheckContext, + implementing_for: TypeId, impl_type_parameters: &[TypeParameter], trait_type_parameters: &[TypeParameter], trait_type_arguments: &[TypeArgument], @@ -434,7 +503,6 @@ fn type_check_trait_implementation( let type_engine = ctx.engines.te(); let decl_engine = ctx.engines.de(); let engines = ctx.engines(); - let self_type = ctx.self_type(); // Check to see if the type that we are implementing for implements the // supertraits of this trait. @@ -442,7 +510,7 @@ fn type_check_trait_implementation( .implemented_traits .check_if_trait_constraints_are_satisfied_for_type( handler, - self_type, + implementing_for, &trait_supertraits .iter() .map(|x| x.into()) @@ -495,13 +563,13 @@ fn type_check_trait_implementation( if !trait_supertraits.is_empty() { // Gather the supertrait "stub_method_refs" and "impld_method_refs". let (this_supertrait_stub_method_refs, this_supertrait_impld_method_refs) = - handle_supertraits(handler, ctx.by_ref(), trait_supertraits)?; + handle_supertraits(handler, ctx.by_ref(), implementing_for, trait_supertraits)?; let _ = ctx.insert_trait_implementation( &Handler::default(), trait_name.clone(), trait_type_arguments.to_vec(), - self_type, + implementing_for, &this_supertrait_impld_method_refs .values() .cloned() @@ -534,12 +602,12 @@ fn type_check_trait_implementation( // declaration. let interface_item_parents = decl_engine.find_all_parents(engines, decl_ref.id()); match interface_item_parents.len() { - 0 => { interface_item_refs.insert((name, self_type), item.clone()); }, + 0 => { interface_item_refs.insert((name, implementing_for), item.clone()); }, 1 => match interface_item_parents[0] { AssociatedItemDeclId::TraitFn(parent_decl_id) => { let parent_interface_item = TyTraitInterfaceItem::TraitFn(DeclRef::new(name.clone(), parent_decl_id, decl_ref.span())); - interface_item_refs.insert((name, self_type), parent_interface_item); + interface_item_refs.insert((name, implementing_for), parent_interface_item); } _ => return Err(handler.emit_err(CompileError::Internal( "A trait interface method's parent is expected to be another trait interface method", @@ -554,13 +622,13 @@ fn type_check_trait_implementation( let constant = decl_engine.get_constant(decl_ref); let name = constant.call_path.suffix.clone(); constant_checklist.insert(name.clone(), constant); - interface_item_refs.insert((name, self_type), item.clone()); + interface_item_refs.insert((name, implementing_for), item.clone()); } TyTraitInterfaceItem::Type(decl_ref) => { let ty = decl_engine.get_type(decl_ref); let name = ty.name.clone(); type_checklist.insert(name.clone(), ty); - interface_item_refs.insert((name, self_type), item.clone()); + interface_item_refs.insert((name, implementing_for), item.clone()); } } } @@ -578,6 +646,7 @@ fn type_check_trait_implementation( ctx.by_ref(), type_decl, trait_name, + implementing_for, is_contract, &impld_item_refs, &type_checklist, @@ -592,11 +661,11 @@ fn type_check_trait_implementation( // Add this type to the "impld decls". let decl_ref = decl_engine.insert(type_decl.clone()); - impld_item_refs.insert((name, self_type), TyTraitItem::Type(decl_ref)); + impld_item_refs.insert((name, implementing_for), TyTraitItem::Type(decl_ref)); let old_type_decl_info = TypeInfo::TraitType { name: type_decl.name.clone(), - trait_type_id: self_type, + trait_type_id: implementing_for, }; trait_type_mapping.extend(TypeSubstMap::from_type_parameters_and_type_arguments( vec![type_engine.insert(engines, old_type_decl_info)], @@ -612,6 +681,7 @@ fn type_check_trait_implementation( let mut impl_method = type_check_impl_method( handler, ctx.by_ref().with_type_subst(&trait_type_mapping), + implementing_for, impl_type_parameters, impl_method, trait_name, @@ -629,7 +699,7 @@ fn type_check_trait_implementation( // Add this method to the "impld items". let decl_ref = decl_engine.insert(impl_method); - impld_item_refs.insert((name, self_type), TyTraitItem::Fn(decl_ref)); + impld_item_refs.insert((name, implementing_for), TyTraitItem::Fn(decl_ref)); } ImplItem::Constant(const_decl) => { let mut const_decl = type_check_const_decl( @@ -651,7 +721,7 @@ fn type_check_trait_implementation( // Add this constant to the "impld decls". let decl_ref = decl_engine.insert(const_decl); - impld_item_refs.insert((name, self_type), TyTraitItem::Constant(decl_ref)); + impld_item_refs.insert((name, implementing_for), TyTraitItem::Constant(decl_ref)); } ImplItem::Type(_) => {} } @@ -689,7 +759,6 @@ fn type_check_trait_implementation( TyImplItem::Fn(decl_ref) => { let mut method = decl_engine.get_function(decl_ref); method.replace_decls(&decl_mapping, handler, &mut ctx)?; - method.replace_self_type(engines, ctx.self_type()); method.subst(&type_mapping, engines); all_items_refs.push(TyImplItem::Fn( decl_engine @@ -700,13 +769,11 @@ fn type_check_trait_implementation( TyImplItem::Constant(decl_ref) => { let mut const_decl = decl_engine.get_constant(decl_ref); const_decl.replace_decls(&decl_mapping, handler, &mut ctx)?; - const_decl.replace_self_type(engines, ctx.self_type()); const_decl.subst(&type_mapping, engines); all_items_refs.push(TyImplItem::Constant(decl_engine.insert(const_decl))); } TyImplItem::Type(decl_ref) => { let mut type_decl = decl_engine.get_type(decl_ref); - type_decl.replace_self_type(engines, ctx.self_type()); type_decl.subst(&type_mapping, engines); all_items_refs.push(TyImplItem::Type(decl_engine.insert(type_decl.clone()))); } @@ -744,6 +811,7 @@ fn type_check_trait_implementation( fn type_check_impl_method( handler: &Handler, mut ctx: TypeCheckContext, + implementing_for: TypeId, impl_type_parameters: &[TypeParameter], impl_method: &FunctionDeclaration, trait_name: &CallPath, @@ -753,7 +821,6 @@ fn type_check_impl_method( ) -> Result { let type_engine = ctx.engines.te(); let engines = ctx.engines(); - let self_type = ctx.self_type(); let mut ctx = ctx .by_ref() @@ -773,7 +840,7 @@ fn type_check_impl_method( ty::TyFunctionDecl::type_check(handler, ctx.by_ref(), impl_method.clone(), true, false)?; // Ensure that there aren't multiple definitions of this function impl'd - if impld_item_refs.contains_key(&(impl_method.name.clone(), self_type)) { + if impld_item_refs.contains_key(&(impl_method.name.clone(), implementing_for)) { return Err( handler.emit_err(CompileError::MultipleDefinitionsOfFunction { name: impl_method.name.clone(), @@ -796,11 +863,6 @@ fn type_check_impl_method( } }; - // replace instances of `TypeInfo::SelfType` with a fresh - // `TypeInfo::SelfType` to avoid replacing types in the stub trait - // declaration - impl_method_signature.replace_self_type(engines, self_type); - // ensure this fn decl's parameters and signature lines up with the one // in the trait if impl_method.parameters.len() != impl_method_signature.parameters.len() { @@ -816,8 +878,7 @@ fn type_check_impl_method( } handler.scope(|handler| { - // unify the types from the parameters of the function declaration - // with the parameters of the function signature + // Ensure that the method decl's parameters match the stub method's parameters for (impl_method_signature_param, impl_method_param) in impl_method_signature .parameters .iter_mut() @@ -979,7 +1040,10 @@ fn type_check_const_decl( ) -> Result { let type_engine = ctx.engines.te(); let engines = ctx.engines(); - let self_type = ctx.self_type(); + + // Create a new type parameter for the "self type". + let self_type_param = TypeParameter::new_self_type(engines, const_decl.span.clone()); + let self_type_id = self_type_param.type_id; let mut ctx = ctx .by_ref() @@ -1000,7 +1064,7 @@ fn type_check_const_decl( let const_name = const_decl.call_path.suffix.clone(); // Ensure that there aren't multiple definitions of this constant - if impld_constant_ids.contains_key(&(const_name.clone(), self_type)) { + if impld_constant_ids.contains_key(&(const_name.clone(), self_type_id)) { return Err( handler.emit_err(CompileError::MultipleDefinitionsOfConstant { name: const_name.clone(), @@ -1010,7 +1074,7 @@ fn type_check_const_decl( } // Ensure that the constant checklist contains this constant. - let mut const_decl_signature = match constant_checklist.get(&const_name) { + let const_decl_signature = match constant_checklist.get(&const_name) { Some(const_decl) => const_decl.clone(), None => { return Err( @@ -1023,11 +1087,6 @@ fn type_check_const_decl( } }; - // replace instances of `TypeInfo::SelfType` with a fresh - // `TypeInfo::SelfType` to avoid replacing types in the stub constant - // declaration - const_decl_signature.replace_self_type(engines, self_type); - // this subst is required to replace associated types, namely TypeInfo::TraitType. let mut const_decl_type_id = const_decl.type_ascription.type_id; const_decl_type_id.subst(&ctx.type_subst(), engines); @@ -1054,18 +1113,19 @@ fn type_check_const_decl( Ok(const_decl) } +#[allow(clippy::too_many_arguments)] fn type_check_type_decl( handler: &Handler, mut ctx: TypeCheckContext, type_decl: &TraitTypeDeclaration, trait_name: &CallPath, + self_type: TypeId, is_contract: bool, impld_type_ids: &ItemMap, type_checklist: &BTreeMap, ) -> Result { let engines = ctx.engines(); let type_engine = engines.te(); - let self_type = ctx.self_type(); let mut ctx = ctx .by_ref() @@ -1094,8 +1154,8 @@ fn type_check_type_decl( } // Ensure that the type checklist contains this type. - let mut type_decl_signature = match type_checklist.get(&type_name) { - Some(type_decl) => type_decl.clone(), + match type_checklist.get(&type_name) { + Some(_type_decl) => {} None => { return Err( handler.emit_err(CompileError::TypeNotAPartOfInterfaceSurface { @@ -1107,11 +1167,6 @@ fn type_check_type_decl( } }; - // replace instances of `TypeInfo::SelfType` with a fresh - // `TypeInfo::SelfType` to avoid replacing types in the stub constant - // declaration - type_decl_signature.replace_self_type(engines, self_type); - Ok(type_decl) } @@ -1156,7 +1211,8 @@ fn check_for_unconstrained_type_parameters( trait_type_arguments: &[TypeArgument], self_type: TypeId, ) -> Result<(), ErrorEmitted> { - // create a list of defined generics, with the generic and a span + // Create a list of defined generics, with the generic and a span. + // Purposefully exclude the "self" type parameters. let mut defined_generics: HashMap<_, _> = HashMap::from_iter( type_parameters .iter() @@ -1200,6 +1256,7 @@ fn check_for_unconstrained_type_parameters( fn handle_supertraits( handler: &Handler, mut ctx: TypeCheckContext, + self_type: TypeId, supertraits: &[Supertrait], ) -> Result<(InterfaceItemMap, ItemMap), ErrorEmitted> { let engines = ctx.engines; @@ -1207,7 +1264,6 @@ fn handle_supertraits( let mut interface_surface_item_ids: InterfaceItemMap = BTreeMap::new(); let mut impld_item_refs: ItemMap = BTreeMap::new(); - let self_type = ctx.self_type(); handler.scope(|handler| { for supertrait in supertraits.iter() { @@ -1255,7 +1311,12 @@ fn handle_supertraits( // Retrieve the interface surfaces and implemented methods for // the supertraits of this type. let (next_interface_supertrait_decl_refs, next_these_supertrait_decl_refs) = - match handle_supertraits(handler, ctx.by_ref(), &trait_decl.supertraits) { + match handle_supertraits( + handler, + ctx.by_ref(), + self_type, + &trait_decl.supertraits, + ) { Ok(res) => res, Err(_) => continue, }; 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 15fa4164026..971c1db6691 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs @@ -28,7 +28,7 @@ impl ty::TyStructDecl { // Type check the type parameters. let new_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters)?; + TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters, None)?; // Insert them into the current namespace. for p in &new_type_parameters { @@ -68,10 +68,9 @@ impl ty::TyStructField { let mut type_argument = field.type_argument; type_argument.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_argument.type_id, - ctx.self_type(), &type_argument.span, EnforceTypeArguments::Yes, None, 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 8dce60824da..4094df63733 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -46,18 +46,24 @@ impl TyTraitDecl { }); } - let type_engine = ctx.engines.te(); let decl_engine = ctx.engines.de(); let engines = ctx.engines(); // A temporary namespace for checking within the trait's scope. - let self_type = type_engine.insert(engines, TypeInfo::SelfType); let mut trait_namespace = ctx.namespace.clone(); - let mut ctx = ctx.scoped(&mut trait_namespace).with_self_type(self_type); + let mut ctx = ctx.scoped(&mut trait_namespace); + + // Create a new type parameter for the "self type". + let self_type_param = TypeParameter::new_self_type(engines, name.span()); + let self_type = self_type_param.type_id; // Type check the type parameters. - let new_type_parameters = - TypeParameter::type_check_type_params(handler, ctx.by_ref(), type_parameters)?; + let new_type_parameters = TypeParameter::type_check_type_params( + handler, + ctx.by_ref(), + type_parameters, + Some(self_type_param.clone()), + )?; // Insert them into the current namespace. for p in &new_type_parameters { @@ -204,6 +210,7 @@ impl TyTraitDecl { let typed_trait_decl = ty::TyTraitDecl { name, type_parameters: new_type_parameters, + self_type: self_type_param, interface_surface: new_interface_surface, items: new_items, supertraits, @@ -411,7 +418,6 @@ impl TyTraitDecl { match item { ty::TyTraitInterfaceItem::TraitFn(decl_ref) => { let mut method = decl_engine.get_trait_fn(decl_ref); - method.replace_self_type(engines, type_id); method.subst(&type_mapping, engines); all_items.push(TyImplItem::Fn( ctx.engines @@ -445,7 +451,6 @@ impl TyTraitDecl { match item { ty::TyTraitItem::Fn(decl_ref) => { let mut method = decl_engine.get_function(decl_ref); - method.replace_self_type(engines, type_id); method.subst(&type_mapping, engines); all_items.push(TyImplItem::Fn( ctx.engines @@ -456,13 +461,11 @@ impl TyTraitDecl { } ty::TyTraitItem::Constant(decl_ref) => { let mut const_decl = decl_engine.get_constant(decl_ref); - const_decl.replace_self_type(engines, type_id); const_decl.subst(&type_mapping, engines); all_items.push(TyImplItem::Constant(ctx.engines.de().insert(const_decl))); } ty::TyTraitItem::Type(decl_ref) => { let mut type_decl = decl_engine.get_type(decl_ref); - type_decl.replace_self_type(engines, type_id); type_decl.subst(&type_mapping, engines); all_items.push(TyImplItem::Type(ctx.engines.de().insert(type_decl))); } 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 bda3e15f9ad..a1ff1d36ffd 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 @@ -53,10 +53,9 @@ impl ty::TyTraitFn { // Type check the return type. return_type.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, return_type.type_id, - ctx.self_type(), &return_type.span, EnforceTypeArguments::Yes, None, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait_type.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait_type.rs index 6f07059d111..04e6283563c 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait_type.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait_type.rs @@ -28,10 +28,9 @@ impl ty::TyTraitType { let ty = if let Some(mut ty) = ty_opt { ty.type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, ty.type_id, - ctx.self_type(), &ty.span, EnforceTypeArguments::No, None, 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 d6289949e12..d7fbe90b8cc 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 @@ -209,10 +209,9 @@ fn type_check_size_of_type( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -262,10 +261,9 @@ fn type_check_is_reference_type( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -316,10 +314,9 @@ fn type_check_assert_is_str_array( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -509,10 +506,9 @@ fn type_check_gtf( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -741,10 +737,9 @@ fn type_check_state_store_word( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -833,10 +828,9 @@ fn type_check_state_quad( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, @@ -1188,10 +1182,9 @@ fn type_check_ptr_ops( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::No, None, @@ -1286,10 +1279,9 @@ fn type_check_smo( .unwrap_or_else(TypeInfo::ErrorRecovery); let initial_type_id = type_engine.insert(engines, initial_type_info); let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, initial_type_id, - ctx.self_type(), &targ.span, EnforceTypeArguments::Yes, None, 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 c70479bc48b..b02ba5ff38c 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 @@ -74,7 +74,7 @@ impl ty::TyMatchBranch { // unify the return type from the typed result with the type annotation if !typed_result.deterministically_aborts(decl_engine, true) { - ctx.unify_with_self(handler, typed_result.return_type, &typed_result.span); + ctx.unify_with_type_annotation(handler, typed_result.return_type, &typed_result.span); } // if the typed branch result is a code block, then add the contents 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 3f232b9aa6d..1d0f3b37896 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 @@ -380,14 +380,13 @@ impl ty::TyExpression { }; // if the return type cannot be cast into the annotation type then it is a type error - ctx.unify_with_self(handler, typed_expression.return_type, &expr_span); + ctx.unify_with_type_annotation(handler, typed_expression.return_type, &expr_span); // The annotation may result in a cast, which is handled in the type engine. typed_expression.return_type = ctx - .resolve_type_with_self( + .resolve_type( handler, typed_expression.return_type, - ctx.self_type(), &expr_span, EnforceTypeArguments::No, None, @@ -570,7 +569,7 @@ impl ty::TyExpression { ) }); - ctx.unify_with_self(handler, block_return_type, &span); + ctx.unify_with_type_annotation(handler, block_return_type, &span); let exp = ty::TyExpression { expression: ty::TyExpressionVariant::CodeBlock(ty::TyCodeBlock { @@ -836,10 +835,9 @@ impl ty::TyExpression { .map(|x| x.1) .unwrap_or_else(|| asm.whole_block_span.clone()); let return_type = ctx - .resolve_type_with_self( + .resolve_type( handler, type_engine.insert(engines, asm.return_type.clone()), - ctx.self_type(), &asm_span, EnforceTypeArguments::No, None, @@ -1402,8 +1400,10 @@ impl ty::TyExpression { }) }); - if let Some(TypeInfo::SelfType) = type_info_opt { - call_path_binding.strip_prefixes(); + if let Some(type_info) = type_info_opt { + if TypeInfo::is_self_type(&type_info) { + call_path_binding.strip_prefixes(); + } } let const_opt: Option<(DeclRefConstant, _)> = @@ -1433,15 +1433,12 @@ impl ty::TyExpression { Err(_) => return None, }; - let const_decl_ref = match ctx.find_constant_for_type( - const_probe_handler, - struct_type_id.unwrap(), - &suffix, - ctx.self_type(), - ) { - Ok(Some(val)) => val, - Ok(None) | Err(_) => return None, - }; + let const_decl_ref = + match ctx.find_constant_for_type(const_probe_handler, struct_type_id.unwrap(), &suffix) + { + Ok(Some(val)) => val, + Ok(None) | Err(_) => return None, + }; Some((const_decl_ref, call_path_binding.clone())) } @@ -1653,7 +1650,7 @@ impl ty::TyExpression { let h = Handler::default(); ctx.by_ref() .with_type_annotation(elem_type) - .unify_with_self(&h, typed_elem.return_type, &typed_elem.span); + .unify_with_type_annotation(&h, typed_elem.return_type, &typed_elem.span); let (new_errors, new_warnings) = h.consume(); let no_warnings = new_warnings.is_empty(); let no_errors = new_errors.is_empty(); diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs index 9864a4bf053..c7ba5429e3e 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs @@ -30,12 +30,11 @@ pub(crate) fn instantiate_if_expression( } else { type_engine.insert(engines, TypeInfo::Tuple(vec![])) }; - type_engine.unify_with_self( + type_engine.unify( handler, engines, then.return_type, ty_to_check, - ctx.self_type(), &then.span, "`then` branch must return expected type.", None, @@ -51,12 +50,11 @@ pub(crate) fn instantiate_if_expression( }; if !else_deterministically_aborts { // if this does not deterministically_abort, check the block return type - type_engine.unify_with_self( + type_engine.unify( handler, engines, r#else.return_type, ty_to_check, - ctx.self_type(), &r#else.span, "`else` branch must return expected type.", None, @@ -73,12 +71,11 @@ pub(crate) fn instantiate_if_expression( if !else_deterministically_aborts && !then_deterministically_aborts { // delay emitting the errors until we decide if this is a missing else branch or some other set of errors let h = Handler::default(); - type_engine.unify_with_self( + type_engine.unify( &h, engines, then.return_type, r#else_ret_ty, - ctx.self_type(), &span, "The two branches of an if expression must return the same type.", None, 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 58f320f5145..c2ca633bba7 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 @@ -377,12 +377,11 @@ fn unify_arguments_and_parameters( for ((_, arg), param) in arguments.iter().zip(parameters.iter()) { // unify the type of the argument with the type of the param let unify_res = handler.scope(|handler| { - type_engine.unify_with_self( + type_engine.unify( handler, engines, arg.return_type, param.type_argument.type_id, - ctx.self_type(), &arg.span, "This argument's type is not castable to the declared parameter type.", Some(CompileError::ArgumentParameterTypeMismatch { @@ -437,7 +436,6 @@ pub(crate) fn resolve_method_name( type_id, &type_info_prefix, method_name, - ctx.self_type(), ctx.type_annotation(), &arguments, None, @@ -475,7 +473,6 @@ pub(crate) fn resolve_method_name( type_id, &module_path, &call_path.suffix, - ctx.self_type(), ctx.type_annotation(), &arguments, None, @@ -500,7 +497,6 @@ pub(crate) fn resolve_method_name( type_id, &module_path, method_name, - ctx.self_type(), ctx.type_annotation(), &arguments, None, @@ -524,7 +520,6 @@ pub(crate) fn resolve_method_name( type_id, &type_info_prefix, method_name, - ctx.self_type(), ctx.type_annotation(), &arguments, Some(as_trait.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 850315c07b6..5796ba1f7c7 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 @@ -51,7 +51,7 @@ pub(crate) fn struct_instantiation( let type_arguments = type_arguments.to_vec(); let type_info = match (suffix.as_str(), type_arguments.is_empty()) { - ("Self", true) => TypeInfo::SelfType, + ("Self", true) => TypeInfo::new_self_type(suffix.span()), ("Self", false) => { return Err(handler.emit_err(CompileError::TypeArgumentsNotAllowed { span: suffix.span(), @@ -77,10 +77,9 @@ pub(crate) fn struct_instantiation( // resolve the type of the struct decl let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_engine.insert(engines, type_info), - ctx.self_type(), &inner_span, EnforceTypeArguments::No, Some(&type_info_prefix), diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index e5839249404..bbfd9ea8c5d 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -10,6 +10,7 @@ use sway_types::span::Span; /// Enum used to pass a value asking for insertion of type into trait map when an implementation /// of the trait cannot be found. +#[derive(Debug)] pub enum TryInsertingTraitImplOnFailure { Yes, No, diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index aa55052fa10..6bf0f7ef895 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -17,7 +17,7 @@ use crate::{ CallPath, }, type_system::{SubstTypes, TypeId}, - ReplaceSelfType, TraitConstraint, TypeArgument, TypeInfo, TypeSubstMap, UnifyCheck, + TraitConstraint, TypeArgument, TypeInfo, TypeSubstMap, UnifyCheck, }; use super::TryInsertingTraitImplOnFailure; @@ -706,8 +706,7 @@ impl TraitMap { *map_type_id, *type_id, ); - let new_self_type = type_engine.insert(engines, TypeInfo::SelfType); - type_id.replace_self_type(engines, new_self_type); + type_id.subst(&type_mapping, engines); let trait_items: TraitItems = map_trait_items .clone() .into_iter() @@ -715,7 +714,6 @@ impl TraitMap { ty::TyTraitItem::Fn(decl_ref) => { let mut decl = decl_engine.get(decl_ref.id()); decl.subst(&type_mapping, engines); - decl.replace_self_type(engines, new_self_type); let new_ref = decl_engine .insert(decl) .with_parent(decl_engine, decl_ref.id().into()); @@ -724,14 +722,12 @@ impl TraitMap { ty::TyTraitItem::Constant(decl_ref) => { let mut decl = decl_engine.get(decl_ref.id()); decl.subst(&type_mapping, engines); - decl.replace_self_type(engines, new_self_type); let new_ref = decl_engine.insert(decl); (name, TyImplItem::Constant(new_ref)) } ty::TyTraitItem::Type(decl_ref) => { let mut decl = decl_engine.get(decl_ref.id()); decl.subst(&type_mapping, engines); - decl.replace_self_type(engines, new_self_type); let new_ref = decl_engine.insert(decl); (name, TyImplItem::Type(new_ref)) } diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 8ddbfb24a10..7436edf3dab 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -885,7 +885,6 @@ fn type_info_name(type_info: &TypeInfo) -> String { } => name.suffix.as_str(), TypeInfo::Tuple(fields) if fields.is_empty() => "unit", TypeInfo::Tuple(..) => "tuple", - TypeInfo::SelfType => "self", TypeInfo::B256 => "b256", TypeInfo::Numeric => "numeric", TypeInfo::Contract => "contract", diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index c790f12433e..eac863171ac 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -14,7 +14,7 @@ use crate::{ Namespace, }, type_system::{SubstTypes, TypeArgument, TypeId, TypeInfo}, - CreateTypeId, ReplaceSelfType, TypeParameter, TypeSubstMap, UnifyCheck, + CreateTypeId, TypeParameter, TypeSubstMap, UnifyCheck, }; use sway_error::{ error::CompileError, @@ -41,10 +41,6 @@ pub struct TypeCheckContext<'a> { // into a new node during type checking, these fields should be updated using the `with_*` // methods which provides a new `TypeCheckContext`, ensuring we don't leak our changes into // the parent nodes. - /// While type-checking an `impl` (whether inherent or for a `trait`/`abi`) this represents the - /// type for which we are implementing. For example in `impl Foo {}` or `impl Trait for Foo - /// {}`, this represents the type ID of `Foo`. - self_type: TypeId, /// While type-checking an expression, this indicates the expected type. /// /// Assists type inference. @@ -104,8 +100,6 @@ impl<'a> TypeCheckContext<'a> { type_annotation: engines.te().insert(engines, TypeInfo::Unknown), type_subst: TypeSubstMap::new(), help_text: "", - // TODO: Contract? Should this be passed in based on program kind (aka TreeType)? - self_type: engines.te().insert(engines, TypeInfo::Contract), abi_mode: AbiMode::NonAbi, const_shadowing_mode: ConstShadowingMode::ItemStyle, purity: Purity::default(), @@ -128,7 +122,6 @@ impl<'a> TypeCheckContext<'a> { namespace: self.namespace, type_annotation: self.type_annotation, type_subst: self.type_subst.clone(), - self_type: self.self_type, abi_mode: self.abi_mode.clone(), const_shadowing_mode: self.const_shadowing_mode, help_text: self.help_text, @@ -146,7 +139,6 @@ impl<'a> TypeCheckContext<'a> { namespace, type_annotation: self.type_annotation, type_subst: self.type_subst, - self_type: self.self_type, abi_mode: self.abi_mode, const_shadowing_mode: self.const_shadowing_mode, help_text: self.help_text, @@ -225,11 +217,6 @@ impl<'a> TypeCheckContext<'a> { Self { kind, ..self } } - /// Map this `TypeCheckContext` instance to a new one with the given purity. - pub(crate) fn with_self_type(self, self_type: TypeId) -> Self { - Self { self_type, ..self } - } - /// Map this `TypeCheckContext` instance to a new one with /// `disallow_functions` set to `true`. pub(crate) fn disallow_functions(self) -> Self { @@ -289,10 +276,6 @@ impl<'a> TypeCheckContext<'a> { self.kind.clone() } - pub(crate) fn self_type(&self) -> TypeId { - self.self_type - } - pub(crate) fn functions_disallowed(&self) -> bool { self.disallow_functions } @@ -326,15 +309,14 @@ impl<'a> TypeCheckContext<'a> { ) } - /// Short-hand around `type_system::unify_with_self`, where the `TypeCheckContext` provides the - /// type annotation, self type and help text. - pub(crate) fn unify_with_self(&self, handler: &Handler, ty: TypeId, span: &Span) { - self.engines.te().unify_with_self( + /// Short-hand around `type_system::unify_`, where the `TypeCheckContext` + /// provides the type annotation and help text. + pub(crate) fn unify_with_type_annotation(&self, handler: &Handler, ty: TypeId, span: &Span) { + self.engines.te().unify( handler, self.engines(), ty, self.type_annotation(), - self.self_type(), span, self.help_text(), None, @@ -490,7 +472,7 @@ impl<'a> TypeCheckContext<'a> { self.engines, TypeInfo::TraitType { name, - trait_type_id: self.self_type(), + trait_type_id: type_id, }, ) } @@ -592,44 +574,20 @@ impl<'a> TypeCheckContext<'a> { 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( + pub(crate) fn resolve_type( &mut self, handler: &Handler, type_id: TypeId, - self_type: TypeId, span: &Span, enforce_type_arguments: EnforceTypeArguments, type_info_prefix: Option<&Path>, ) -> Result { let mod_path = self.namespace.mod_path.clone(); - self.resolve_with_self( + self.resolve( handler, type_id, - self_type, span, enforce_type_arguments, type_info_prefix, @@ -729,10 +687,9 @@ impl<'a> TypeCheckContext<'a> { pub(crate) fn find_items_for_type( &mut self, handler: &Handler, - mut type_id: TypeId, + type_id: TypeId, item_prefix: &Path, item_name: &Ident, - self_type: TypeId, ) -> Result, ErrorEmitted> { let type_engine = self.engines.te(); let _decl_engine = self.engines.de(); @@ -753,8 +710,6 @@ impl<'a> TypeCheckContext<'a> { // grab the local items from the local module let local_items = local_module.get_items_for_type(self.engines, type_id); - type_id.replace_self_type(self.engines, self_type); - // resolve the type let type_id = self .resolve( @@ -818,7 +773,6 @@ impl<'a> TypeCheckContext<'a> { type_id: TypeId, method_prefix: &Path, method_name: &Ident, - self_type: TypeId, annotation_type: TypeId, args_buf: &VecDeque, as_trait: Option, @@ -836,7 +790,7 @@ impl<'a> TypeCheckContext<'a> { } let matching_item_decl_refs = - self.find_items_for_type(handler, type_id, method_prefix, method_name, self_type)?; + self.find_items_for_type(handler, type_id, method_prefix, method_name)?; let matching_method_decl_refs = matching_item_decl_refs .into_iter() @@ -1025,7 +979,6 @@ impl<'a> TypeCheckContext<'a> { type_id, method_prefix, method_name, - self_type, annotation_type, args_buf, as_trait, @@ -1057,10 +1010,9 @@ impl<'a> TypeCheckContext<'a> { handler: &Handler, type_id: TypeId, item_name: &Ident, - self_type: TypeId, ) -> Result, ErrorEmitted> { let matching_item_decl_refs = - self.find_items_for_type(handler, type_id, &Vec::::new(), item_name, self_type)?; + self.find_items_for_type(handler, type_id, &Vec::::new(), item_name)?; let matching_constant_decl_refs = matching_item_decl_refs .into_iter() @@ -1285,47 +1237,73 @@ impl<'a> TypeCheckContext<'a> { where T: MonomorphizeHelper + SubstTypes, { - match ( - value.type_parameters().is_empty(), - type_arguments.is_empty(), - ) { - (true, true) => Ok(TypeSubstMap::default()), - (false, true) => { + fn make_type_arity_mismatch_error( + name: Ident, + span: Span, + given: usize, + expected: usize, + ) -> CompileError { + match (expected, given) { + (0, 0) => unreachable!(), + (_, 0) => CompileError::NeedsTypeArguments { name, span }, + (0, _) => CompileError::DoesNotTakeTypeArguments { name, span }, + (_, _) => CompileError::IncorrectNumberOfTypeArguments { + name, + given, + expected, + span, + }, + } + } + + match (value.type_parameters().len(), type_arguments.len()) { + (0, 0) => Ok(TypeSubstMap::default()), + (num_type_params, 0) => { if let EnforceTypeArguments::Yes = enforce_type_arguments { - return Err(handler.emit_err(CompileError::NeedsTypeArguments { - name: value.name().clone(), - span: call_site_span.clone(), - })); + return Err(handler.emit_err(make_type_arity_mismatch_error( + value.name().clone(), + call_site_span.clone(), + 0, + num_type_params, + ))); } let type_mapping = TypeSubstMap::from_type_parameters(self.engines, value.type_parameters()); Ok(type_mapping) } - (true, false) => { + (0, num_type_args) => { 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, - })) + Err(handler.emit_err(make_type_arity_mismatch_error( + value.name().clone(), + type_arguments_span.clone(), + num_type_args, + 0, + ))) } - (false, false) => { + (num_type_params, num_type_args) => { 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, - }), - ); + // a trait decl is passed the self type parameter and the corresponding argument + // but it would be confusing for the user if the error reporting mechanism + // reported the number of arguments including the implicit self, hence + // we adjust it below + let adjust_for_trait_decl = value.has_self_type_param() as usize; + let num_type_params = num_type_params - adjust_for_trait_decl; + let num_type_args = num_type_args - adjust_for_trait_decl; + if num_type_params != num_type_args { + return Err(handler.emit_err(make_type_arity_mismatch_error( + value.name().clone(), + type_arguments_span, + num_type_args, + num_type_params, + ))); } for type_argument in type_arguments.iter_mut() { type_argument.type_id = self @@ -1369,6 +1347,7 @@ impl<'a> TypeCheckContext<'a> { pub(crate) trait MonomorphizeHelper { fn name(&self) -> &Ident; fn type_parameters(&self) -> &[TypeParameter]; + fn has_self_type_param(&self) -> bool; } /// This type is used to denote if, during monomorphization, the compiler diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 85a2062631d..a49f0801725 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -1262,7 +1262,9 @@ fn fn_args_to_function_parameters( (Some(reference), None) => reference.span(), (Some(reference), Some(mutable)) => Span::join(reference.span(), mutable.span()), }; - let type_id = engines.te().insert(engines, TypeInfo::SelfType); + let type_id = engines + .te() + .insert(engines, TypeInfo::new_self_type(self_token.span())); let mut function_parameters = vec![FunctionParameter { name: Ident::new(self_token.span()), is_reference: ref_self.is_some(), @@ -1314,7 +1316,7 @@ pub(crate) fn type_name_to_type_info_opt(name: &Ident) -> Option { "str" => Some(TypeInfo::StringSlice), "raw_ptr" => Some(TypeInfo::RawUntypedPtr), "raw_slice" => Some(TypeInfo::RawUntypedSlice), - "Self" | "self" => Some(TypeInfo::SelfType), + "Self" | "self" => Some(TypeInfo::new_self_type(name.span())), "Contract" => Some(TypeInfo::Contract), _other => None, } @@ -3967,24 +3969,6 @@ fn path_type_to_type_info( } = path_type.clone(); let type_info = match type_name_to_type_info_opt(&name) { - Some(type_info @ TypeInfo::SelfType) => { - if root_opt.is_some() { - let error = ConvertParseTreeError::FullySpecifiedTypesNotSupported { span }; - return Err(handler.emit_err(error.into())); - } - if !suffix.is_empty() { - let (call_path, type_arguments) = path_type_to_call_path_and_type_arguments( - context, handler, engines, path_type, - )?; - TypeInfo::Custom { - call_path, - type_arguments: Some(type_arguments), - root_type_id: None, - } - } else { - type_info - } - } Some(type_info) => { if root_opt.is_some() || !suffix.is_empty() { let error = ConvertParseTreeError::FullySpecifiedTypesNotSupported { span }; @@ -4196,10 +4180,7 @@ fn error_if_self_param_is_not_allowed( fn_kind: &str, ) -> Result<(), ErrorEmitted> { for param in parameters { - if matches!( - engines.te().get(param.type_argument.type_id), - TypeInfo::SelfType - ) { + if engines.te().get(param.type_argument.type_id).is_self_type() { let error = ConvertParseTreeError::SelfParameterNotAllowedForFn { fn_kind: fn_kind.to_owned(), span: param.type_argument.span.clone(), diff --git a/sway-core/src/type_system/ast_elements/binding.rs b/sway-core/src/type_system/ast_elements/binding.rs index 33b36eb9b29..e61810a4021 100644 --- a/sway-core/src/type_system/ast_elements/binding.rs +++ b/sway-core/src/type_system/ast_elements/binding.rs @@ -184,10 +184,9 @@ impl TypeBinding> { // resolve the type of the type info object let type_id = ctx - .resolve_type_with_self( + .resolve_type( handler, type_engine.insert(engines, type_info), - ctx.self_type(), &type_info_span, EnforceTypeArguments::No, Some(&type_info_prefix), @@ -251,10 +250,9 @@ impl TypeCheckTypeBinding for TypeBinding { TypeArgs::Prefix(_) => { // Resolve the type arguments without monomorphizing. for type_argument in self.type_arguments.to_vec_mut().iter_mut() { - ctx.resolve_type_with_self( + ctx.resolve_type( handler, type_argument.type_id, - ctx.self_type(), &type_argument.span, EnforceTypeArguments::Yes, None, diff --git a/sway-core/src/type_system/ast_elements/mod.rs b/sway-core/src/type_system/ast_elements/mod.rs index 2ce66f07ac7..bebd719965e 100644 --- a/sway-core/src/type_system/ast_elements/mod.rs +++ b/sway-core/src/type_system/ast_elements/mod.rs @@ -1,7 +1,6 @@ pub(crate) mod binding; pub(crate) mod create_type_id; pub(crate) mod length; -pub(crate) mod replace_self_type; pub(crate) mod trait_constraint; pub(crate) mod type_argument; pub(crate) mod type_parameter; diff --git a/sway-core/src/type_system/ast_elements/replace_self_type.rs b/sway-core/src/type_system/ast_elements/replace_self_type.rs deleted file mode 100644 index 14ea289e094..00000000000 --- a/sway-core/src/type_system/ast_elements/replace_self_type.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::{engine_threading::Engines, type_system::priv_prelude::*}; - -/// Replace any instances of `TypeInfo::SelfType` with a provided [TypeId] -/// `self_type`. -pub trait ReplaceSelfType { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId); -} 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 58163ccd3a7..c9ac23ed5a7 100644 --- a/sway-core/src/type_system/ast_elements/trait_constraint.rs +++ b/sway-core/src/type_system/ast_elements/trait_constraint.rs @@ -70,14 +70,6 @@ impl SubstTypes for TraitConstraint { } } -impl ReplaceSelfType for TraitConstraint { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_arguments - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} - impl From<&Supertrait> for TraitConstraint { fn from(supertrait: &Supertrait) -> Self { TraitConstraint { @@ -151,10 +143,11 @@ impl TraitConstraint { // Type check the type arguments. for type_argument in self.type_arguments.iter_mut() { type_argument.type_id = ctx - .resolve_type_without_self( + .resolve_type( handler, type_argument.type_id, &type_argument.span, + EnforceTypeArguments::Yes, None, ) .unwrap_or_else(|err| { @@ -191,6 +184,13 @@ impl TraitConstraint { Some(ty::TyDecl::TraitDecl(ty::TraitDecl { decl_id, .. })) => { let mut trait_decl = decl_engine.get_trait(&decl_id); + // the following essentially is needed to map `Self` to the right type + // during trait decl monomorphization + trait_decl + .type_parameters + .push(trait_decl.self_type.clone()); + type_arguments.push(TypeArgument::from(type_id)); + // Monomorphize the trait declaration. ctx.monomorphize( handler, @@ -200,6 +200,10 @@ impl TraitConstraint { &trait_name.span(), )?; + // restore type parameters and type arguments + trait_decl.type_parameters.pop(); + type_arguments.pop(); + // Insert the interface surface and methods from this trait into // the namespace. trait_decl.insert_interface_surface_and_items_into_namespace( diff --git a/sway-core/src/type_system/ast_elements/type_argument.rs b/sway-core/src/type_system/ast_elements/type_argument.rs index 4f5b9fc5187..14267278467 100644 --- a/sway-core/src/type_system/ast_elements/type_argument.rs +++ b/sway-core/src/type_system/ast_elements/type_argument.rs @@ -97,12 +97,6 @@ impl From<&TypeParameter> for TypeArgument { } } -impl ReplaceSelfType for TypeArgument { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_id.replace_self_type(engines, self_type); - } -} - impl SubstTypes for TypeArgument { fn subst_inner(&mut self, type_mapping: &TypeSubstMap, engines: &Engines) { self.type_id.subst(type_mapping, engines); diff --git a/sway-core/src/type_system/ast_elements/type_parameter.rs b/sway-core/src/type_system/ast_elements/type_parameter.rs index d87c2283108..470093f437d 100644 --- a/sway-core/src/type_system/ast_elements/type_parameter.rs +++ b/sway-core/src/type_system/ast_elements/type_parameter.rs @@ -98,15 +98,6 @@ impl SubstTypes for TypeParameter { } } -impl ReplaceSelfType for TypeParameter { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - self.type_id.replace_self_type(engines, self_type); - self.trait_constraints - .iter_mut() - .for_each(|x| x.replace_self_type(engines, self_type)); - } -} - impl Spanned for TypeParameter { fn span(&self) -> Span { self.name_ident.span() @@ -131,6 +122,47 @@ impl fmt::Debug for TypeParameter { } impl TypeParameter { + pub(crate) fn new_self_type(engines: &Engines, span: Span) -> TypeParameter { + let type_engine = engines.te(); + + let name = Ident::new_with_override("Self".into(), span.clone()); + let type_id = type_engine.insert( + engines, + TypeInfo::UnknownGeneric { + name: name.clone(), + trait_constraints: VecSet(vec![]), + }, + ); + TypeParameter { + type_id, + initial_type_id: type_id, + name_ident: name, + trait_constraints: vec![], + trait_constraints_span: span, + is_from_parent: false, + } + } + + pub(crate) fn insert_self_type_into_namespace(&self, handler: &Handler, ctx: TypeCheckContext) { + let type_parameter_decl = + ty::TyDecl::GenericTypeForFunctionScope(ty::GenericTypeForFunctionScope { + name: self.name_ident.clone(), + type_id: self.type_id, + }); + let name_a = Ident::new_with_override("self".into(), self.name_ident.span()); + let name_b = Ident::new_with_override("Self".into(), self.name_ident.span()); + let const_shadowing_mode = ctx.const_shadowing_mode(); + let _ = ctx.namespace.insert_symbol( + handler, + name_a, + type_parameter_decl.clone(), + const_shadowing_mode, + ); + let _ = + ctx.namespace + .insert_symbol(handler, name_b, type_parameter_decl, const_shadowing_mode); + } + /// Type check a list of [TypeParameter] and return a new list of /// [TypeParameter]. This will also insert this new list into the current /// namespace. @@ -138,9 +170,14 @@ impl TypeParameter { handler: &Handler, mut ctx: TypeCheckContext, type_params: Vec, + self_type_param: Option, ) -> Result, ErrorEmitted> { let mut new_type_params: Vec = vec![]; + if let Some(self_type_param) = self_type_param.clone() { + self_type_param.insert_self_type_into_namespace(handler, ctx.by_ref()); + } + handler.scope(|handler| { for type_param in type_params.into_iter() { new_type_params.push( @@ -168,14 +205,56 @@ impl TypeParameter { let TypeParameter { initial_type_id, name_ident, - mut trait_constraints, + trait_constraints, trait_constraints_span, is_from_parent, .. } = type_parameter; + // Expands a trait constraint to include all its supertraits. + // Another way to incorporate this info would be at the level of unification, + // we would check that two generic type parameters should unify when + // the left one is a supertrait of the right one (at least in the NonDynamicEquality mode) + fn expand_trait_constraints( + handler: &Handler, + ctx: &TypeCheckContext, + tc: &TraitConstraint, + ) -> Vec { + match ctx + .namespace + .resolve_call_path(handler, ctx.engines, &tc.trait_name) + .ok() + { + Some(ty::TyDecl::TraitDecl(ty::TraitDecl { decl_id, .. })) => { + let trait_decl = ctx.engines.de().get_trait(&decl_id); + let mut result = trait_decl + .supertraits + .iter() + .flat_map(|supertrait| { + expand_trait_constraints( + handler, + ctx, + &TraitConstraint { + trait_name: supertrait.name.clone(), + type_arguments: tc.type_arguments.clone(), + }, + ) + }) + .collect::>(); + result.push(tc.clone()); + result + } + _ => vec![tc.clone()], + } + } + + let mut trait_constraints_with_supertraits: Vec = trait_constraints + .iter() + .flat_map(|tc| expand_trait_constraints(handler, &ctx, tc)) + .collect(); + // Type check the trait constraints. - for trait_constraint in trait_constraints.iter_mut() { + for trait_constraint in trait_constraints_with_supertraits.iter_mut() { trait_constraint.type_check(handler, ctx.by_ref())?; } @@ -185,7 +264,7 @@ impl TypeParameter { engines, TypeInfo::UnknownGeneric { name: name_ident.clone(), - trait_constraints: VecSet(trait_constraints.clone()), + trait_constraints: VecSet(trait_constraints_with_supertraits.clone()), }, ); diff --git a/sway-core/src/type_system/engine.rs b/sway-core/src/type_system/engine.rs index 5aae49b08b3..f922b3a0d87 100644 --- a/sway-core/src/type_system/engine.rs +++ b/sway-core/src/type_system/engine.rs @@ -61,34 +61,6 @@ impl TypeEngine { } } - /// Replace any instances of the [TypeInfo::SelfType] variant with - /// `self_type` in both `received` and `expected`, then unify `received` and - /// `expected`. - #[allow(clippy::too_many_arguments)] - pub(crate) fn unify_with_self( - &self, - handler: &Handler, - engines: &Engines, - mut received: TypeId, - mut expected: TypeId, - self_type: TypeId, - span: &Span, - help_text: &str, - err_override: Option, - ) { - received.replace_self_type(engines, self_type); - expected.replace_self_type(engines, self_type); - self.unify( - handler, - engines, - received, - expected, - span, - help_text, - err_override, - ) - } - /// Make the types of `received` and `expected` equivalent (or produce an /// error if there is a conflict between them). /// @@ -181,7 +153,6 @@ impl TypeEngine { | TypeInfo::Boolean | TypeInfo::ContractCaller { .. } | TypeInfo::Custom { .. } - | TypeInfo::SelfType | TypeInfo::B256 | TypeInfo::Contract | TypeInfo::ErrorRecovery(..) @@ -236,7 +207,6 @@ impl TypeEngine { | TypeInfo::Boolean | TypeInfo::ContractCaller { .. } | TypeInfo::Custom { .. } - | TypeInfo::SelfType | TypeInfo::B256 | TypeInfo::Contract | TypeInfo::ErrorRecovery(..) diff --git a/sway-core/src/type_system/id.rs b/sway-core/src/type_system/id.rs index 84c9f402e3b..59a3e48abf6 100644 --- a/sway-core/src/type_system/id.rs +++ b/sway-core/src/type_system/id.rs @@ -5,12 +5,8 @@ use sway_error::{ use sway_types::{BaseIdent, Span}; use crate::{ - decl_engine::{DeclEngine, DeclEngineInsert}, - engine_threading::*, - language::CallPath, - semantic_analysis::TypeCheckContext, - type_system::priv_prelude::*, - types::*, + decl_engine::DeclEngine, engine_threading::*, language::CallPath, + semantic_analysis::TypeCheckContext, type_system::priv_prelude::*, types::*, }; use std::{ @@ -74,202 +70,6 @@ impl CollectTypesMetadata for TypeId { } } -impl ReplaceSelfType for TypeId { - fn replace_self_type(&mut self, engines: &Engines, self_type: TypeId) { - fn helper(type_id: TypeId, engines: &Engines, self_type: TypeId) -> Option { - let type_engine = engines.te(); - let decl_engine = engines.de(); - match type_engine.get(type_id) { - TypeInfo::TypeParam(_) => None, - TypeInfo::SelfType => Some(self_type), - TypeInfo::Enum(decl_ref) => { - let mut decl = decl_engine.get_enum(&decl_ref); - let mut need_to_create_new = false; - - for variant in decl.variants.iter_mut() { - if let Some(type_id) = - helper(variant.type_argument.type_id, engines, self_type) - { - need_to_create_new = true; - variant.type_argument.type_id = type_id; - } - } - - for type_param in decl.type_parameters.iter_mut() { - if let Some(type_id) = helper(type_param.type_id, engines, self_type) { - need_to_create_new = true; - type_param.type_id = type_id; - } - } - - if need_to_create_new { - let new_decl_ref = decl_engine.insert(decl); - Some(type_engine.insert(engines, TypeInfo::Enum(new_decl_ref))) - } else { - None - } - } - TypeInfo::Struct(decl_ref) => { - let mut decl = decl_engine.get_struct(&decl_ref); - let mut need_to_create_new = false; - - for field in decl.fields.iter_mut() { - if let Some(type_id) = - helper(field.type_argument.type_id, engines, self_type) - { - need_to_create_new = true; - field.type_argument.type_id = type_id; - } - } - - for type_param in decl.type_parameters.iter_mut() { - if let Some(type_id) = helper(type_param.type_id, engines, self_type) { - need_to_create_new = true; - type_param.type_id = type_id; - } - } - - if need_to_create_new { - let new_decl_ref = decl_engine.insert(decl); - Some(type_engine.insert(engines, TypeInfo::Struct(new_decl_ref))) - } else { - None - } - } - TypeInfo::Tuple(fields) => { - let mut need_to_create_new = false; - let fields = fields - .into_iter() - .map(|mut field| { - if let Some(type_id) = helper(field.type_id, engines, self_type) { - need_to_create_new = true; - field.type_id = type_id; - } - field - }) - .collect::>(); - if need_to_create_new { - Some(type_engine.insert(engines, TypeInfo::Tuple(fields))) - } else { - None - } - } - TypeInfo::Custom { - call_path, - type_arguments, - root_type_id, - } => { - let mut need_to_create_new = false; - - let mut call_path = call_path; - let mut root_type_id = root_type_id; - if !call_path.prefixes.is_empty() && call_path.prefixes[0].as_str() == "Self" { - need_to_create_new = true; - call_path.prefixes.remove(0); - root_type_id = Some(self_type); - } - - let type_arguments = type_arguments.map(|type_arguments| { - type_arguments - .into_iter() - .map(|mut type_arg| { - if let Some(type_id) = helper(type_arg.type_id, engines, self_type) - { - need_to_create_new = true; - type_arg.type_id = type_id; - } - type_arg - }) - .collect::>() - }); - if need_to_create_new { - Some(type_engine.insert( - engines, - TypeInfo::Custom { - call_path, - type_arguments, - root_type_id, - }, - )) - } else { - None - } - } - TypeInfo::Array(mut elem_ty, count) => helper(elem_ty.type_id, engines, self_type) - .map(|type_id| { - elem_ty.type_id = type_id; - type_engine.insert(engines, TypeInfo::Array(elem_ty, count)) - }), - TypeInfo::Storage { fields } => { - let mut need_to_create_new = false; - let fields = fields - .into_iter() - .map(|mut field| { - if let Some(type_id) = - helper(field.type_argument.type_id, engines, self_type) - { - need_to_create_new = true; - field.type_argument.type_id = type_id; - } - field - }) - .collect::>(); - if need_to_create_new { - Some(type_engine.insert(engines, TypeInfo::Storage { fields })) - } else { - None - } - } - TypeInfo::Alias { name, mut ty } => { - helper(ty.type_id, engines, self_type).map(|type_id| { - ty.type_id = type_id; - type_engine.insert(engines, TypeInfo::Alias { name, ty }) - }) - } - TypeInfo::Ptr(mut ty) => helper(ty.type_id, engines, self_type).map(|type_id| { - ty.type_id = type_id; - type_engine.insert(engines, TypeInfo::Ptr(ty)) - }), - TypeInfo::Slice(mut ty) => helper(ty.type_id, engines, self_type).map(|type_id| { - ty.type_id = type_id; - type_engine.insert(engines, TypeInfo::Slice(ty)) - }), - TypeInfo::TraitType { - name, - mut trait_type_id, - } => helper(trait_type_id, engines, self_type).map(|type_id| { - trait_type_id = type_id; - type_engine.insert( - engines, - TypeInfo::TraitType { - name, - trait_type_id, - }, - ) - }), - TypeInfo::Unknown - | TypeInfo::UnknownGeneric { .. } - | TypeInfo::StringSlice - | TypeInfo::StringArray(_) - | TypeInfo::UnsignedInteger(_) - | TypeInfo::Boolean - | TypeInfo::ContractCaller { .. } - | TypeInfo::B256 - | TypeInfo::Numeric - | TypeInfo::RawUntypedPtr - | TypeInfo::RawUntypedSlice - | TypeInfo::Contract - | TypeInfo::ErrorRecovery(_) - | TypeInfo::Placeholder(_) => None, - } - } - - if let Some(type_id) = helper(*self, engines, self_type) { - *self = type_id; - } - } -} - impl SubstTypes for TypeId { fn subst_inner(&mut self, type_mapping: &TypeSubstMap, engines: &Engines) { let type_engine = engines.te(); diff --git a/sway-core/src/type_system/info.rs b/sway-core/src/type_system/info.rs index f9164a9cc16..d6c528e08ce 100644 --- a/sway-core/src/type_system/info.rs +++ b/sway-core/src/type_system/info.rs @@ -127,7 +127,6 @@ pub enum TypeInfo { /// such as Self::T. root_type_id: Option, }, - SelfType, B256, /// This means that specific type of a number is not yet known. It will be /// determined via inference at a later time. @@ -245,7 +244,6 @@ impl HashWithEngines for TypeInfo { | TypeInfo::Contract | TypeInfo::ErrorRecovery(_) | TypeInfo::Unknown - | TypeInfo::SelfType | TypeInfo::RawUntypedPtr | TypeInfo::RawUntypedSlice => {} } @@ -502,7 +500,6 @@ impl DisplayWithEngines for TypeInfo { .collect::>(); format!("({})", field_strs.join(", ")) } - SelfType => "Self".into(), B256 => "b256".into(), Numeric => "numeric".into(), Contract => "contract".into(), @@ -575,7 +572,6 @@ impl DebugWithEngines for TypeInfo { .collect::>(); format!("({})", field_strs.join(", ")) } - SelfType => "Self".into(), B256 => "b256".into(), Numeric => "numeric".into(), Contract => "contract".into(), @@ -648,21 +644,44 @@ impl TypeInfo { TypeInfo::Tuple(_) => 8, TypeInfo::ContractCaller { .. } => 9, TypeInfo::Custom { .. } => 10, - TypeInfo::SelfType => 11, - TypeInfo::B256 => 12, - TypeInfo::Numeric => 13, - TypeInfo::Contract => 14, - TypeInfo::ErrorRecovery(_) => 15, - TypeInfo::Array(_, _) => 16, - TypeInfo::Storage { .. } => 17, - TypeInfo::RawUntypedPtr => 18, - TypeInfo::RawUntypedSlice => 19, - TypeInfo::TypeParam(_) => 20, - TypeInfo::Alias { .. } => 21, - TypeInfo::Ptr(..) => 22, - TypeInfo::Slice(..) => 23, - TypeInfo::StringSlice => 24, - TypeInfo::TraitType { .. } => 25, + TypeInfo::B256 => 11, + TypeInfo::Numeric => 12, + TypeInfo::Contract => 13, + TypeInfo::ErrorRecovery(_) => 14, + TypeInfo::Array(_, _) => 15, + TypeInfo::Storage { .. } => 16, + TypeInfo::RawUntypedPtr => 17, + TypeInfo::RawUntypedSlice => 18, + TypeInfo::TypeParam(_) => 19, + TypeInfo::Alias { .. } => 20, + TypeInfo::Ptr(..) => 21, + TypeInfo::Slice(..) => 22, + TypeInfo::StringSlice => 23, + TypeInfo::TraitType { .. } => 24, + } + } + + pub(crate) fn new_self_type(span: Span) -> TypeInfo { + TypeInfo::Custom { + call_path: CallPath { + prefixes: vec![], + suffix: Ident::new_with_override("Self".into(), span), + is_absolute: false, + }, + type_arguments: None, + root_type_id: None, + } + } + + pub(crate) fn is_self_type(&self) -> bool { + match self { + TypeInfo::UnknownGeneric { name, .. } => { + name.as_str() == "Self" || name.as_str() == "self" + } + TypeInfo::Custom { call_path, .. } => { + call_path.suffix.as_str() == "Self" || call_path.suffix.as_str() == "self" + } + _ => false, } } @@ -1017,7 +1036,6 @@ impl TypeInfo { | TypeInfo::Boolean | TypeInfo::Tuple(_) | TypeInfo::ContractCaller { .. } - | TypeInfo::SelfType | TypeInfo::B256 | TypeInfo::Numeric | TypeInfo::RawUntypedPtr @@ -1083,7 +1101,6 @@ impl TypeInfo { | TypeInfo::Slice(..) | TypeInfo::ContractCaller { .. } | TypeInfo::Custom { .. } - | TypeInfo::SelfType | TypeInfo::StringArray(_) | TypeInfo::StringSlice | TypeInfo::Contract @@ -1106,6 +1123,10 @@ impl TypeInfo { handler: &Handler, span: &Span, ) -> Result<(), ErrorEmitted> { + if TypeInfo::is_self_type(self) { + return Err(handler + .emit_err(CompileError::SelfIsNotValidAsImplementingFor { span: span.clone() })); + } match self { TypeInfo::UnsignedInteger(_) | TypeInfo::Enum { .. } @@ -1128,7 +1149,6 @@ impl TypeInfo { | TypeInfo::TraitType { .. } => Ok(()), TypeInfo::Unknown | TypeInfo::ContractCaller { .. } - | TypeInfo::SelfType | TypeInfo::Storage { .. } | TypeInfo::Placeholder(_) | TypeInfo::TypeParam(_) => Err(handler.emit_err(CompileError::Unimplemented( @@ -1185,7 +1205,6 @@ impl TypeInfo { | TypeInfo::RawUntypedPtr | TypeInfo::RawUntypedSlice | TypeInfo::Boolean - | TypeInfo::SelfType | TypeInfo::B256 | TypeInfo::Numeric | TypeInfo::Contract @@ -1449,7 +1468,6 @@ impl TypeInfo { | TypeInfo::UnknownGeneric { .. } | TypeInfo::ContractCaller { .. } | TypeInfo::Custom { .. } - | TypeInfo::SelfType | TypeInfo::Tuple(_) | TypeInfo::Array(_, _) | TypeInfo::Contract diff --git a/sway-core/src/type_system/priv_prelude.rs b/sway-core/src/type_system/priv_prelude.rs index ed1d340582a..a00dd8bcf01 100644 --- a/sway-core/src/type_system/priv_prelude.rs +++ b/sway-core/src/type_system/priv_prelude.rs @@ -4,7 +4,6 @@ pub(crate) use super::{ ast_elements::{ binding::{TypeArgs, TypeBinding, TypeCheckTypeBinding}, create_type_id::CreateTypeId, - replace_self_type::ReplaceSelfType, }, info::VecSet, substitute::{subst_list::SubstList, subst_map::TypeSubstMap, subst_types::SubstTypes}, diff --git a/sway-core/src/type_system/substitute/subst_map.rs b/sway-core/src/type_system/substitute/subst_map.rs index aac6f9eaef1..e6d6fc2ec9f 100644 --- a/sway-core/src/type_system/substitute/subst_map.rs +++ b/sway-core/src/type_system/substitute/subst_map.rs @@ -250,7 +250,6 @@ impl TypeSubstMap { } (TypeInfo::Unknown, TypeInfo::Unknown) | (TypeInfo::Boolean, TypeInfo::Boolean) - | (TypeInfo::SelfType, TypeInfo::SelfType) | (TypeInfo::B256, TypeInfo::B256) | (TypeInfo::Numeric, TypeInfo::Numeric) | (TypeInfo::Contract, TypeInfo::Contract) @@ -442,7 +441,6 @@ impl TypeSubstMap { | TypeInfo::UnsignedInteger(..) | TypeInfo::Boolean | TypeInfo::ContractCaller { .. } - | TypeInfo::SelfType | TypeInfo::B256 | TypeInfo::Numeric | TypeInfo::RawUntypedPtr diff --git a/sway-core/src/type_system/unify/unifier.rs b/sway-core/src/type_system/unify/unifier.rs index 14277c1da22..d6a2b34affc 100644 --- a/sway-core/src/type_system/unify/unifier.rs +++ b/sway-core/src/type_system/unify/unifier.rs @@ -87,7 +87,6 @@ impl<'a> Unifier<'a> { // If they have the same `TypeInfo`, then we either compare them for // correctness or perform further unification. (Boolean, Boolean) => (), - (SelfType, SelfType) => (), (B256, B256) => (), (Numeric, Numeric) => (), (Contract, Contract) => (), @@ -125,6 +124,48 @@ impl<'a> Unifier<'a> { ) } + // When we don't know anything about either term, assume that + // they match and make the one we know nothing about reference the + // one we may know something about. + (Unknown, Unknown) => (), + (Unknown, e) => { + self.replace_received_with_expected(handler, received, expected, &Unknown, e, span) + } + (r, Unknown) => { + self.replace_expected_with_received(handler, received, expected, r, &Unknown, span) + } + + (r @ Placeholder(_), e @ Placeholder(_)) => { + self.replace_expected_with_received(handler, received, expected, r, &e, span) + } + (r @ Placeholder(_), e) => { + self.replace_received_with_expected(handler, received, expected, &r, e, span) + } + (r, e @ Placeholder(_)) => { + self.replace_expected_with_received(handler, received, expected, r, &e, span) + } + + // Generics are handled similarly to the case for unknowns, except + // we take more careful consideration for the type/purpose for the + // unification that we are performing. + ( + UnknownGeneric { + name: rn, + trait_constraints: rtc, + }, + UnknownGeneric { + name: en, + trait_constraints: etc, + }, + ) if rn.as_str() == en.as_str() && rtc.eq(&etc, self.engines) => (), + + (r @ UnknownGeneric { .. }, e) if !self.occurs_check(r.clone(), &e) => { + self.replace_received_with_expected(handler, received, expected, &r, e, span) + } + (r, e @ UnknownGeneric { .. }) if !self.occurs_check(e.clone(), &r) => { + self.replace_expected_with_received(handler, received, expected, r, &e, span) + } + // Type aliases and the types they encapsulate coerce to each other. (Alias { ty, .. }, _) => self.unify(handler, ty.type_id, expected, span), (_, Alias { ty, .. }) => self.unify(handler, received, ty.type_id, span), @@ -211,47 +252,6 @@ impl<'a> Unifier<'a> { // if they are the same, then it's ok } - // When we don't know anything about either term, assume that - // they match and make the one we know nothing about reference the - // one we may know something about. - (Unknown, Unknown) => (), - (Unknown, e) => { - self.replace_received_with_expected(handler, received, expected, &Unknown, e, span) - } - (r, Unknown) => { - self.replace_expected_with_received(handler, received, expected, r, &Unknown, span) - } - - (r @ Placeholder(_), e @ Placeholder(_)) => { - self.replace_expected_with_received(handler, received, expected, r, &e, span) - } - (r @ Placeholder(_), e) => { - self.replace_received_with_expected(handler, received, expected, &r, e, span) - } - (r, e @ Placeholder(_)) => { - self.replace_expected_with_received(handler, received, expected, r, &e, span) - } - - // Generics are handled similarly to the case for unknowns, except - // we take more careful consideration for the type/purpose for the - // unification that we are performing. - ( - UnknownGeneric { - name: rn, - trait_constraints: rtc, - }, - UnknownGeneric { - name: en, - trait_constraints: etc, - }, - ) if rn.as_str() == en.as_str() && rtc.eq(&etc, self.engines) => (), - (r @ UnknownGeneric { .. }, e) if !self.occurs_check(r.clone(), &e) => { - self.replace_received_with_expected(handler, received, expected, &r, e, span) - } - (r, e @ UnknownGeneric { .. }) if !self.occurs_check(e.clone(), &r) => { - self.replace_expected_with_received(handler, received, expected, r, &e, span) - } - // If no previous attempts to unify were successful, raise an error. (TypeInfo::ErrorRecovery(_), _) => (), (_, TypeInfo::ErrorRecovery(_)) => (), diff --git a/sway-core/src/type_system/unify/unify_check.rs b/sway-core/src/type_system/unify/unify_check.rs index 4863dc9727c..d30ce0cb9b5 100644 --- a/sway-core/src/type_system/unify/unify_check.rs +++ b/sway-core/src/type_system/unify/unify_check.rs @@ -1,6 +1,10 @@ -use crate::{engine_threading::*, type_system::priv_prelude::*}; +use crate::{ + engine_threading::*, + type_system::{priv_prelude::*, unify::occurs_check::OccursCheck}, +}; use sway_types::Spanned; +#[derive(Debug)] enum UnifyCheckMode { /// Given two [TypeId]'s `left` and `right`, check to see if `left` can be /// coerced into `right`. @@ -309,6 +313,11 @@ impl<'a> UnifyCheck<'a> { match self.mode { Coercion => { match (left_info, right_info) { + (r @ UnknownGeneric { .. }, e @ UnknownGeneric { .. }) + if TypeInfo::is_self_type(&r) || TypeInfo::is_self_type(&e) => + { + true + } ( UnknownGeneric { name: ln, @@ -319,8 +328,9 @@ impl<'a> UnifyCheck<'a> { trait_constraints: rtc, }, ) => ln == rn && rtc.eq(<c, self.engines), - // any type can be coerced into generic - (_, UnknownGeneric { .. }) => true, + // any type can be coerced into a generic, + // except if the type already contains the generic + (e, g @ UnknownGeneric { .. }) => !OccursCheck::new(self.engines).check(g, &e), // Let empty enums to coerce to any other type. This is useful for Never enum. (Enum(r_decl_ref), _) @@ -413,8 +423,9 @@ impl<'a> UnifyCheck<'a> { trait_constraints: rtc, }, ) => rtc.eq(<c, self.engines), - // any type can be coerced into generic - (_, UnknownGeneric { .. }) => true, + // any type can be coerced into a generic, + // except if the type already contains the generic + (e, g @ UnknownGeneric { .. }) => !OccursCheck::new(self.engines).check(g, &e), (Enum(l_decl_ref), Enum(r_decl_ref)) => { let l_decl = self.engines.de().get_enum(&l_decl_ref); @@ -462,7 +473,6 @@ impl<'a> UnifyCheck<'a> { // TypeId, they may later resolve to be different types in the type // engine (TypeInfo::Unknown, TypeInfo::Unknown) => false, - (TypeInfo::SelfType, TypeInfo::SelfType) => false, (TypeInfo::Numeric, TypeInfo::Numeric) => false, (TypeInfo::Storage { .. }, TypeInfo::Storage { .. }) => false, diff --git a/sway-error/src/error.rs b/sway-error/src/error.rs index e93058d8cdd..de6907729c2 100644 --- a/sway-error/src/error.rs +++ b/sway-error/src/error.rs @@ -176,8 +176,9 @@ pub enum CompileError { missing_functions: Vec, span: Span, }, - #[error("Expected {} type {}, but instead found {}.", expected, if *expected == 1usize { "argument" } else { "arguments" }, given)] + #[error("Expected {} type {} for \"{name}\", but instead found {}.", expected, if *expected == 1usize { "argument" } else { "arguments" }, given)] IncorrectNumberOfTypeArguments { + name: Ident, given: usize, expected: usize, span: Span, @@ -726,6 +727,8 @@ pub enum CompileError { AssociatedTypeNotSupportedInAbi { span: Span }, #[error("Cannot call ABI supertrait's method as a contract method: \"{fn_name}\"")] AbiSupertraitMethodCallAsContractCall { fn_name: Ident, span: Span }, + #[error("\"Self\" is not valid in the self type of an impl block")] + SelfIsNotValidAsImplementingFor { span: Span }, } impl std::convert::From for CompileError { @@ -910,6 +913,7 @@ impl Spanned for CompileError { AbiSupertraitMethodCallAsContractCall { span, .. } => span.clone(), TypeNotAllowed { span, .. } => span.clone(), ExpectedStringLiteral { span } => span.clone(), + SelfIsNotValidAsImplementingFor { span } => span.clone(), } } } diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index b01d3275967..bb520f49522 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -276,7 +276,6 @@ pub fn type_info_to_symbol_kind( let type_info = type_engine.get(elem_ty.type_id); type_info_to_symbol_kind(type_engine, &type_info, Some(&elem_ty.span())) } - TypeInfo::SelfType => SymbolKind::SelfTypeKeyword, _ => SymbolKind::Unknown, } } diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml index 7eaac884fa9..abe9b0b2ed0 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/disallow_turbofish/test.toml @@ -4,7 +4,7 @@ category = "fail" # nextln: $()"Data" does not take type arguments. # check: let _res1 = Result:: { -# nextln: $()Expected 2 type arguments, but instead found 1. +# nextln: $()Expected 2 type arguments for "Result", but instead found 1. # check: foo::(); # nextln: $()"foo" does not take type arguments. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/generic_traits/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/generic_traits/test.toml index c0fbbc8d821..ce286ad87dd 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/generic_traits/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/generic_traits/test.toml @@ -10,7 +10,7 @@ category = "fail" # check: $()Trait "OutOfScopeGetter" cannot be found in the current scope. # check: $()impl Getter for FooBarData { -# check: $()Expected 1 type argument, but instead found 2. +# check: $()Expected 1 type argument for "Getter", but instead found 2. # check: $()impl Getter for FooBarData { # check: $()"Getter" needs type arguments. @@ -23,7 +23,7 @@ category = "fail" # check: $()Conflicting implementations of trait "Multiple" for type "FooBarData". # check: $()impl Returner for Self { -# check: $()Unimplemented feature: implementing traits on this type is unsupported right now +# check: $()"Self" is not valid in the self type of an impl block # check: $()fn set_it(mut data: T, new_value: F) where T: Setter { # check: $()Unimplemented feature: Using generic traits in trait constraints is not supported yet. diff --git a/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml b/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml index 4283e8cd5fc..19d4cee17ab 100644 --- a/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_fail/generics_unhelpful_error/test.toml @@ -1,3 +1,3 @@ category = "fail" -# check: $()Expected 2 type arguments, but instead found 1. +# check: $()Expected 2 type arguments for "DoubleIdentity", but instead found 1. diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_and_associated_const/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_and_associated_const/test.toml index 7bbfbabcf22..073186bbdee 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_and_associated_const/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_and_associated_const/test.toml @@ -1,3 +1,3 @@ -category = "run" +category = "disabled" expected_result = { action = "return", value = 1 } expected_warnings = 1 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_container/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_container/test.toml index 7bbfbabcf22..073186bbdee 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_container/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_container/test.toml @@ -1,3 +1,3 @@ -category = "run" +category = "disabled" expected_result = { action = "return", value = 1 } expected_warnings = 1 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_iterator/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_iterator/test.toml index 7bbfbabcf22..073186bbdee 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_iterator/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_iterator/test.toml @@ -1,3 +1,3 @@ -category = "run" +category = "disabled" expected_result = { action = "return", value = 1 } expected_warnings = 1 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_method/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_method/test.toml index 7bbfbabcf22..073186bbdee 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_method/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/associated_type_method/test.toml @@ -1,3 +1,3 @@ -category = "run" +category = "disabled" expected_result = { action = "return", value = 1 } expected_warnings = 1