From 27a84cc27da45c61b85740a05037bdaa01ec8cc7 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 31 Jul 2023 10:12:08 +0100 Subject: [PATCH] Fixes replace_decls issue with nested and multiple types. When a single method uses multiple trait implementation errors are thrown by the compiler similar issue occurs when a method requires a trait implementation and then calls another method that requires another implementaion of the same trait. This PR fixes both issues by filtering traits to be replaced by the arguments type used and trait method self type, and by gathering decl mapping of nested methods. Fixes #4852 --- sway-core/src/decl_engine/mapping.rs | 28 ++++- sway-core/src/decl_engine/mod.rs | 9 +- sway-core/src/decl_engine/ref.rs | 10 +- sway-core/src/decl_engine/replace_decls.rs | 7 +- sway-core/src/language/ty/ast_node.rs | 9 +- sway-core/src/language/ty/code_block.rs | 8 +- .../src/language/ty/declaration/constant.rs | 5 +- .../src/language/ty/declaration/function.rs | 5 +- .../src/language/ty/expression/expression.rs | 5 +- .../ty/expression/expression_variant.rs | 100 ++++++++++++------ .../language/ty/expression/reassignment.rs | 9 +- .../ty/expression/struct_exp_field.rs | 9 +- .../ast_node/declaration/impl_trait.rs | 16 +-- .../ast_node/declaration/trait.rs | 26 +++-- .../typed_expression/function_application.rs | 4 +- .../typed_expression/method_application.rs | 4 +- .../semantic_analysis/namespace/namespace.rs | 2 +- .../ast_elements/type_parameter.rs | 10 +- .../language/generic_tuple_trait/src/main.sw | 12 +++ 19 files changed, 187 insertions(+), 91 deletions(-) diff --git a/sway-core/src/decl_engine/mapping.rs b/sway-core/src/decl_engine/mapping.rs index 4b68d0632ff..cae3b2b775d 100644 --- a/sway-core/src/decl_engine/mapping.rs +++ b/sway-core/src/decl_engine/mapping.rs @@ -1,8 +1,11 @@ use std::fmt; -use crate::language::ty::{TyTraitInterfaceItem, TyTraitItem}; +use crate::{ + language::ty::{TyTraitInterfaceItem, TyTraitItem}, + Engines, TypeId, UnifyCheck, +}; -use super::{AssociatedItemDeclId, InterfaceItemMap, ItemMap}; +use super::{AssociatedItemDeclId, DeclEngineGet, InterfaceItemMap, ItemMap}; type SourceDecl = AssociatedItemDeclId; type DestinationDecl = AssociatedItemDeclId; @@ -99,4 +102,25 @@ impl DeclMapping { } None } + + pub(crate) fn filter(&self, self_type: TypeId, engines: &Engines) -> DeclMapping { + let mut mapping: Vec<(SourceDecl, DestinationDecl)> = vec![]; + for (source_decl_ref, dest_decl_ref) in self.mapping.iter().cloned() { + match dest_decl_ref { + AssociatedItemDeclId::TraitFn(_) => mapping.push((source_decl_ref, dest_decl_ref)), + AssociatedItemDeclId::Function(func_id) => { + let func = engines.de().get(&func_id); + + let unify_check = UnifyCheck::non_dynamic_equality(engines); + if let (left, Some(right)) = (self_type, func.parameters.get(0)) { + if unify_check.check(left, right.type_argument.type_id) { + mapping.push((source_decl_ref, dest_decl_ref)); + } + } + } + AssociatedItemDeclId::Constant(_) => mapping.push((source_decl_ref, dest_decl_ref)), + } + } + DeclMapping { mapping } + } } diff --git a/sway-core/src/decl_engine/mod.rs b/sway-core/src/decl_engine/mod.rs index bf7a2dd6db0..020b5779ec9 100644 --- a/sway-core/src/decl_engine/mod.rs +++ b/sway-core/src/decl_engine/mod.rs @@ -30,7 +30,10 @@ pub(crate) use replace_decls::*; use sway_types::Ident; pub(crate) use template::*; -use crate::language::ty::{TyTraitInterfaceItem, TyTraitItem}; +use crate::{ + language::ty::{TyTraitInterfaceItem, TyTraitItem}, + TypeId, +}; -pub(crate) type InterfaceItemMap = BTreeMap; -pub(crate) type ItemMap = BTreeMap; +pub(crate) type InterfaceItemMap = BTreeMap<(Ident, TypeId), TyTraitInterfaceItem>; +pub(crate) type ItemMap = BTreeMap<(Ident, TypeId), TyTraitItem>; diff --git a/sway-core/src/decl_engine/ref.rs b/sway-core/src/decl_engine/ref.rs index 8898a7d4701..8ae043420ce 100644 --- a/sway-core/src/decl_engine/ref.rs +++ b/sway-core/src/decl_engine/ref.rs @@ -31,6 +31,7 @@ use crate::{ self, TyAbiDecl, TyConstantDecl, TyEnumDecl, TyFunctionDecl, TyImplTrait, TyStorageDecl, TyStructDecl, TyTraitDecl, TyTraitFn, }, + semantic_analysis::TypeCheckContext, type_system::*, }; @@ -195,11 +196,11 @@ where pub(crate) fn replace_decls_and_insert_new_with_parent( &self, decl_mapping: &DeclMapping, - engines: &Engines, + ctx: &TypeCheckContext, ) -> Self { - let decl_engine = engines.de(); + let decl_engine = ctx.engines().de(); let mut decl = decl_engine.get(&self.id); - decl.replace_decls(decl_mapping, engines); + decl.replace_decls(decl_mapping, ctx); decl_engine .insert(decl) .with_parent(decl_engine, self.id.into()) @@ -334,7 +335,8 @@ where } impl ReplaceDecls for DeclRefFunction { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { + let engines = ctx.engines(); let decl_engine = engines.de(); if let Some(new_decl_ref) = decl_mapping.find_match(self.id.into()) { if let AssociatedItemDeclId::Function(new_decl_ref) = new_decl_ref { diff --git a/sway-core/src/decl_engine/replace_decls.rs b/sway-core/src/decl_engine/replace_decls.rs index b35b898342b..a9c0dd313fb 100644 --- a/sway-core/src/decl_engine/replace_decls.rs +++ b/sway-core/src/decl_engine/replace_decls.rs @@ -1,16 +1,17 @@ use crate::{ engine_threading::Engines, language::ty::{self, TyDecl}, + semantic_analysis::TypeCheckContext, }; use super::DeclMapping; pub trait ReplaceDecls { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines); + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext); - fn replace_decls(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { if !decl_mapping.is_empty() { - self.replace_decls_inner(decl_mapping, engines); + self.replace_decls_inner(decl_mapping, ctx); } } } diff --git a/sway-core/src/language/ty/ast_node.rs b/sway-core/src/language/ty/ast_node.rs index 3d17dd0f441..bea10f649f2 100644 --- a/sway-core/src/language/ty/ast_node.rs +++ b/sway-core/src/language/ty/ast_node.rs @@ -10,6 +10,7 @@ use crate::{ engine_threading::*, error::*, language::{parsed::TreeType, ty::*, Visibility}, + semantic_analysis::TypeCheckContext, transform::AttributeKind, type_system::*, types::*, @@ -87,16 +88,16 @@ impl ReplaceSelfType for TyAstNode { } impl ReplaceDecls for TyAstNode { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { match self.content { TyAstNodeContent::ImplicitReturnExpression(ref mut exp) => { - exp.replace_decls(decl_mapping, engines) + exp.replace_decls(decl_mapping, ctx) } TyAstNodeContent::Declaration(TyDecl::VariableDecl(ref mut decl)) => { - decl.body.replace_decls(decl_mapping, engines); + decl.body.replace_decls(decl_mapping, ctx); } TyAstNodeContent::Declaration(_) => {} - TyAstNodeContent::Expression(ref mut expr) => expr.replace_decls(decl_mapping, engines), + TyAstNodeContent::Expression(ref mut expr) => expr.replace_decls(decl_mapping, ctx), TyAstNodeContent::SideEffect(_) => (), } } diff --git a/sway-core/src/language/ty/code_block.rs b/sway-core/src/language/ty/code_block.rs index 4c91d726578..ff8baf59102 100644 --- a/sway-core/src/language/ty/code_block.rs +++ b/sway-core/src/language/ty/code_block.rs @@ -1,8 +1,8 @@ use std::hash::Hasher; use crate::{ - decl_engine::*, engine_threading::*, language::ty::*, type_system::*, - types::DeterministicallyAborts, + decl_engine::*, engine_threading::*, language::ty::*, semantic_analysis::TypeCheckContext, + type_system::*, types::DeterministicallyAborts, }; #[derive(Clone, Debug)] @@ -41,10 +41,10 @@ impl ReplaceSelfType for TyCodeBlock { } impl ReplaceDecls for TyCodeBlock { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { self.contents .iter_mut() - .for_each(|x| x.replace_decls(decl_mapping, engines)); + .for_each(|x| x.replace_decls(decl_mapping, ctx)); } } diff --git a/sway-core/src/language/ty/declaration/constant.rs b/sway-core/src/language/ty/declaration/constant.rs index 86fea6fb9d2..da2a272af88 100644 --- a/sway-core/src/language/ty/declaration/constant.rs +++ b/sway-core/src/language/ty/declaration/constant.rs @@ -6,6 +6,7 @@ use crate::{ decl_engine::{DeclMapping, ReplaceDecls}, engine_threading::*, language::{ty::*, CallPath, Visibility}, + semantic_analysis::TypeCheckContext, transform, type_system::*, }; @@ -103,9 +104,9 @@ impl ReplaceSelfType for TyConstantDecl { } impl ReplaceDecls for TyConstantDecl { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { if let Some(expr) = &mut self.value { - expr.replace_decls(decl_mapping, engines); + expr.replace_decls(decl_mapping, ctx); } } } diff --git a/sway-core/src/language/ty/declaration/function.rs b/sway-core/src/language/ty/declaration/function.rs index f9f5519fa73..bfc29cdac88 100644 --- a/sway-core/src/language/ty/declaration/function.rs +++ b/sway-core/src/language/ty/declaration/function.rs @@ -10,6 +10,7 @@ use crate::{ engine_threading::*, error::*, language::{parsed, ty::*, Inline, Purity, Visibility}, + semantic_analysis::TypeCheckContext, transform, type_system::*, types::*, @@ -123,8 +124,8 @@ impl ReplaceSelfType for TyFunctionDecl { } impl ReplaceDecls for TyFunctionDecl { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { - self.body.replace_decls(decl_mapping, engines); + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { + self.body.replace_decls(decl_mapping, ctx); } } diff --git a/sway-core/src/language/ty/expression/expression.rs b/sway-core/src/language/ty/expression/expression.rs index 9caf72acc32..fb2cdc0512c 100644 --- a/sway-core/src/language/ty/expression/expression.rs +++ b/sway-core/src/language/ty/expression/expression.rs @@ -7,6 +7,7 @@ use crate::{ engine_threading::*, error::*, language::{ty::*, Literal}, + semantic_analysis::TypeCheckContext, type_system::*, types::*, }; @@ -59,8 +60,8 @@ impl ReplaceSelfType for TyExpression { } impl ReplaceDecls for TyExpression { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { - self.expression.replace_decls(decl_mapping, engines); + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { + self.expression.replace_decls(decl_mapping, ctx); } } diff --git a/sway-core/src/language/ty/expression/expression_variant.rs b/sway-core/src/language/ty/expression/expression_variant.rs index 652c29ecb36..c618d72de8b 100644 --- a/sway-core/src/language/ty/expression/expression_variant.rs +++ b/sway-core/src/language/ty/expression/expression_variant.rs @@ -4,12 +4,13 @@ use std::{ hash::{Hash, Hasher}, }; -use sway_types::{Ident, Named, Span}; +use sway_types::{Ident, Named, Span, Spanned}; use crate::{ decl_engine::*, engine_threading::*, language::{ty::*, *}, + semantic_analysis::TypeCheckContext, type_system::*, }; @@ -880,7 +881,7 @@ impl ReplaceSelfType for TyExpressionVariant { } impl ReplaceDecls for TyExpressionVariant { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { use TyExpressionVariant::*; match self { Literal(..) => (), @@ -889,35 +890,74 @@ impl ReplaceDecls for TyExpressionVariant { ref mut arguments, .. } => { - fn_ref.replace_decls(decl_mapping, engines); + 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); + } + } + } + + if let Some(filter_type) = filter_type_opt { + let filtered_decl_mapping = decl_mapping.filter(filter_type, ctx.engines()); + fn_ref.replace_decls(&filtered_decl_mapping, ctx); + } else { + fn_ref.replace_decls(decl_mapping, ctx); + }; + let new_decl_ref = fn_ref .clone() - .replace_decls_and_insert_new_with_parent(decl_mapping, engines); + .replace_decls_and_insert_new_with_parent(decl_mapping, ctx); fn_ref.replace_id(*new_decl_ref.id()); for (_, arg) in arguments.iter_mut() { - arg.replace_decls(decl_mapping, engines); + arg.replace_decls(decl_mapping, ctx); } + + let decl_engine = ctx.engines().de(); + let mut method = ctx.engines().de().get(fn_ref); + // Handle the trait constraints. This includes checking to see if the trait + // constraints are satisfied and replacing old decl ids based on the + // constraint with new decl ids based on the new type. + let mut errors = vec![]; + let mut warnings = vec![]; + let inner_decl_mapping = check!( + TypeParameter::gather_decl_mapping_from_trait_constraints( + ctx, + &method.type_parameters, + &method.name.span() + ), + return, // we can ignore error as this is already checked in its own type_check_method_application, + warnings, + errors + ); + method.replace_decls(&inner_decl_mapping, ctx); + let new_decl_ref = decl_engine + .insert(method) + .with_parent(decl_engine, (*fn_ref.id()).into()); + fn_ref.replace_id(*new_decl_ref.id()); } LazyOperator { lhs, rhs, .. } => { - (*lhs).replace_decls(decl_mapping, engines); - (*rhs).replace_decls(decl_mapping, engines); - } - ConstantExpression { const_decl, .. } => { - const_decl.replace_decls(decl_mapping, engines) + (*lhs).replace_decls(decl_mapping, ctx); + (*rhs).replace_decls(decl_mapping, ctx); } + ConstantExpression { const_decl, .. } => const_decl.replace_decls(decl_mapping, ctx), VariableExpression { .. } => (), Tuple { fields } => fields .iter_mut() - .for_each(|x| x.replace_decls(decl_mapping, engines)), + .for_each(|x| x.replace_decls(decl_mapping, ctx)), Array { elem_type: _, contents, } => contents .iter_mut() - .for_each(|x| x.replace_decls(decl_mapping, engines)), + .for_each(|x| x.replace_decls(decl_mapping, ctx)), ArrayIndex { prefix, index } => { - (*prefix).replace_decls(decl_mapping, engines); - (*index).replace_decls(decl_mapping, engines); + (*prefix).replace_decls(decl_mapping, ctx); + (*index).replace_decls(decl_mapping, ctx); } StructExpression { struct_ref: _, @@ -926,29 +966,29 @@ impl ReplaceDecls for TyExpressionVariant { call_path_binding: _, } => fields .iter_mut() - .for_each(|x| x.replace_decls(decl_mapping, engines)), + .for_each(|x| x.replace_decls(decl_mapping, ctx)), CodeBlock(block) => { - block.replace_decls(decl_mapping, engines); + block.replace_decls(decl_mapping, ctx); } FunctionParameter => (), - MatchExp { desugared, .. } => desugared.replace_decls(decl_mapping, engines), + MatchExp { desugared, .. } => desugared.replace_decls(decl_mapping, ctx), IfExp { condition, then, r#else, } => { - condition.replace_decls(decl_mapping, engines); - then.replace_decls(decl_mapping, engines); + condition.replace_decls(decl_mapping, ctx); + then.replace_decls(decl_mapping, ctx); if let Some(ref mut r#else) = r#else { - r#else.replace_decls(decl_mapping, engines); + r#else.replace_decls(decl_mapping, ctx); } } AsmExpression { .. } => {} StructFieldAccess { prefix, .. } => { - prefix.replace_decls(decl_mapping, engines); + prefix.replace_decls(decl_mapping, ctx); } TupleElemAccess { prefix, .. } => { - prefix.replace_decls(decl_mapping, engines); + prefix.replace_decls(decl_mapping, ctx); } EnumInstantiation { enum_ref: _, @@ -958,30 +998,30 @@ impl ReplaceDecls for TyExpressionVariant { // TODO: replace enum decl //enum_decl.replace_decls(decl_mapping); if let Some(ref mut contents) = contents { - contents.replace_decls(decl_mapping, engines); + contents.replace_decls(decl_mapping, ctx); }; } - AbiCast { address, .. } => address.replace_decls(decl_mapping, engines), + AbiCast { address, .. } => address.replace_decls(decl_mapping, ctx), StorageAccess { .. } => (), IntrinsicFunction(_) => {} EnumTag { exp } => { - exp.replace_decls(decl_mapping, engines); + exp.replace_decls(decl_mapping, ctx); } UnsafeDowncast { exp, .. } => { - exp.replace_decls(decl_mapping, engines); + exp.replace_decls(decl_mapping, ctx); } AbiName(_) => (), WhileLoop { ref mut condition, ref mut body, } => { - condition.replace_decls(decl_mapping, engines); - body.replace_decls(decl_mapping, engines); + condition.replace_decls(decl_mapping, ctx); + body.replace_decls(decl_mapping, ctx); } Break => (), Continue => (), - Reassignment(reassignment) => reassignment.replace_decls(decl_mapping, engines), - Return(stmt) => stmt.replace_decls(decl_mapping, engines), + Reassignment(reassignment) => reassignment.replace_decls(decl_mapping, ctx), + Return(stmt) => stmt.replace_decls(decl_mapping, ctx), } } } diff --git a/sway-core/src/language/ty/expression/reassignment.rs b/sway-core/src/language/ty/expression/reassignment.rs index 3c63cd95692..d69a4521691 100644 --- a/sway-core/src/language/ty/expression/reassignment.rs +++ b/sway-core/src/language/ty/expression/reassignment.rs @@ -5,7 +5,10 @@ use std::{ use sway_types::{Ident, Span, Spanned}; -use crate::{decl_engine::*, engine_threading::*, language::ty::*, type_system::*}; +use crate::{ + decl_engine::*, engine_threading::*, language::ty::*, semantic_analysis::TypeCheckContext, + type_system::*, +}; #[derive(Clone, Debug)] pub struct TyReassignment { @@ -61,8 +64,8 @@ impl ReplaceSelfType for TyReassignment { } impl ReplaceDecls for TyReassignment { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { - self.rhs.replace_decls(decl_mapping, engines); + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { + self.rhs.replace_decls(decl_mapping, ctx); } } 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 7e7dd518cd2..2706394e376 100644 --- a/sway-core/src/language/ty/expression/struct_exp_field.rs +++ b/sway-core/src/language/ty/expression/struct_exp_field.rs @@ -2,7 +2,10 @@ use std::hash::{Hash, Hasher}; use sway_types::Ident; -use crate::{decl_engine::*, engine_threading::*, language::ty::*, type_system::*}; +use crate::{ + decl_engine::*, engine_threading::*, language::ty::*, semantic_analysis::TypeCheckContext, + type_system::*, +}; #[derive(Clone, Debug)] pub struct TyStructExpressionField { @@ -38,7 +41,7 @@ impl ReplaceSelfType for TyStructExpressionField { } impl ReplaceDecls for TyStructExpressionField { - fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, engines: &Engines) { - self.value.replace_decls(decl_mapping, engines); + fn replace_decls_inner(&mut self, decl_mapping: &DeclMapping, ctx: &TypeCheckContext) { + self.value.replace_decls(decl_mapping, ctx); } } 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 3d0aaaf875b..3848f32c054 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 @@ -505,13 +505,13 @@ fn type_check_trait_implementation( let method = decl_engine.get_trait_fn(decl_ref); let name = method.name.clone(); method_checklist.insert(name.clone(), method); - interface_item_refs.insert(name, item.clone()); + interface_item_refs.insert((name, self_type), item.clone()); } TyTraitInterfaceItem::Constant(decl_ref) => { 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, item.clone()); + interface_item_refs.insert((name, self_type), item.clone()); } } } @@ -540,7 +540,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, TyTraitItem::Fn(decl_ref)); + impld_item_refs.insert((name, self_type), TyTraitItem::Fn(decl_ref)); } ImplItem::Constant(const_decl) => { let const_decl = check!( @@ -563,7 +563,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, TyTraitItem::Constant(decl_ref)); + impld_item_refs.insert((name, self_type), TyTraitItem::Constant(decl_ref)); } } } @@ -597,7 +597,7 @@ fn type_check_trait_implementation( match item { TyImplItem::Fn(decl_ref) => { let mut method = decl_engine.get_function(decl_ref); - method.replace_decls(&decl_mapping, engines); + method.replace_decls(&decl_mapping, &ctx); method.subst(&type_mapping, engines); method.replace_self_type(engines, ctx.self_type()); all_items_refs.push(TyImplItem::Fn( @@ -608,7 +608,7 @@ 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, engines); + const_decl.replace_decls(&decl_mapping, &ctx); const_decl.subst(&type_mapping, engines); const_decl.replace_self_type(engines, ctx.self_type()); all_items_refs.push(TyImplItem::Constant(decl_engine.insert(const_decl))); @@ -684,7 +684,7 @@ fn type_check_impl_method( ); // Ensure that there aren't multiple definitions of this function impl'd - if impld_item_refs.contains_key(&impl_method.name.clone()) { + if impld_item_refs.contains_key(&(impl_method.name.clone(), self_type)) { errors.push(CompileError::MultipleDefinitionsOfFunction { name: impl_method.name.clone(), span: impl_method.name.span(), @@ -903,7 +903,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) { + if impld_constant_ids.contains_key(&(const_name.clone(), self_type)) { errors.push(CompileError::MultipleDefinitionsOfConstant { name: const_name.clone(), span: const_name.span(), 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 192aa63fcc7..c2282a68034 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -202,10 +202,12 @@ impl ty::TyTraitDecl { for item in interface_surface.iter() { match item { ty::TyTraitInterfaceItem::TraitFn(decl_ref) => { - interface_surface_item_refs.insert(decl_ref.name().clone(), item.clone()); + interface_surface_item_refs + .insert((decl_ref.name().clone(), type_id), item.clone()); } ty::TyTraitInterfaceItem::Constant(decl_ref) => { - interface_surface_item_refs.insert(decl_ref.name().clone(), item.clone()); + interface_surface_item_refs + .insert((decl_ref.name().clone(), type_id), item.clone()); } } } @@ -218,10 +220,10 @@ impl ty::TyTraitDecl { { match &item { ty::TyTraitItem::Fn(decl_ref) => { - impld_item_refs.insert(decl_ref.name().clone(), item.clone()); + impld_item_refs.insert((decl_ref.name().clone(), type_id), item.clone()); } ty::TyTraitItem::Constant(decl_ref) => { - impld_item_refs.insert(decl_ref.name().clone(), item.clone()); + impld_item_refs.insert((decl_ref.name().clone(), type_id), item.clone()); } }; } @@ -233,7 +235,7 @@ impl ty::TyTraitDecl { /// this trait. pub(crate) fn retrieve_interface_surface_and_items_and_implemented_items_for_type( &self, - ctx: TypeCheckContext, + ctx: &TypeCheckContext, type_id: TypeId, call_path: &CallPath, type_arguments: &[TypeArgument], @@ -256,10 +258,12 @@ impl ty::TyTraitDecl { for item in interface_surface.iter() { match item { ty::TyTraitInterfaceItem::TraitFn(decl_ref) => { - interface_surface_item_refs.insert(decl_ref.name().clone(), item.clone()); + interface_surface_item_refs + .insert((decl_ref.name().clone(), type_id), item.clone()); } ty::TyTraitInterfaceItem::Constant(decl_ref) => { - interface_surface_item_refs.insert(decl_ref.name().clone(), item.clone()); + interface_surface_item_refs + .insert((decl_ref.name().clone(), type_id), item.clone()); } } } @@ -268,10 +272,10 @@ impl ty::TyTraitDecl { for item in items.iter() { match item { ty::TyTraitItem::Fn(decl_ref) => { - item_refs.insert(decl_ref.name().clone(), item.clone()); + item_refs.insert((decl_ref.name().clone(), type_id), item.clone()); } ty::TyTraitItem::Constant(decl_ref) => { - item_refs.insert(decl_ref.name().clone(), item.clone()); + item_refs.insert((decl_ref.name().clone(), type_id), item.clone()); } } } @@ -297,7 +301,7 @@ impl ty::TyTraitDecl { let mut method = decl_engine.get_function(&decl_ref); method.subst(&type_mapping, engines); impld_item_refs.insert( - method.name.clone(), + (method.name.clone(), type_id), TyTraitItem::Fn( decl_engine .insert(method) @@ -309,7 +313,7 @@ impl ty::TyTraitDecl { let mut const_decl = decl_engine.get_constant(&decl_ref); const_decl.subst(&type_mapping, engines); impld_item_refs.insert( - const_decl.call_path.suffix.clone(), + (const_decl.call_path.suffix.clone(), type_id), TyTraitItem::Constant(decl_engine.insert(const_decl)), ); } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs index 173c73b7eaf..bb0dda9f4dd 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs @@ -78,7 +78,7 @@ pub(crate) fn instantiate_function_application( // constraint with new decl ids based on the new type. let decl_mapping = check!( TypeParameter::gather_decl_mapping_from_trait_constraints( - ctx.by_ref(), + &ctx, &function_decl.type_parameters, &call_path_binding.span() ), @@ -86,7 +86,7 @@ pub(crate) fn instantiate_function_application( warnings, errors ); - function_decl.replace_decls(&decl_mapping, engines); + function_decl.replace_decls(&decl_mapping, &ctx); let return_type = function_decl.return_type.clone(); let new_decl_ref = decl_engine .insert(function_decl) 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 28a629f706a..f29b295f032 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 @@ -352,7 +352,7 @@ pub(crate) fn type_check_method_application( // constraint with new decl ids based on the new type. let decl_mapping = check!( TypeParameter::gather_decl_mapping_from_trait_constraints( - ctx.by_ref(), + &ctx, &method.type_parameters, &call_path.span() ), @@ -360,7 +360,7 @@ pub(crate) fn type_check_method_application( warnings, errors ); - method.replace_decls(&decl_mapping, ctx.engines()); + method.replace_decls(&decl_mapping, &ctx); let return_type = method.return_type.type_id; let new_decl_ref = decl_engine .insert(method) diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index e7181f52ad1..e241e725497 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -665,7 +665,7 @@ impl Namespace { } pub(crate) fn get_items_for_type_and_trait_name( - &mut self, + &self, engines: &Engines, type_id: TypeId, trait_name: &CallPath, 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 96b06550058..798625724fd 100644 --- a/sway-core/src/type_system/ast_elements/type_parameter.rs +++ b/sway-core/src/type_system/ast_elements/type_parameter.rs @@ -257,7 +257,7 @@ impl TypeParameter { /// Creates a [DeclMapping] from a list of [TypeParameter]s. pub(crate) fn gather_decl_mapping_from_trait_constraints( - mut ctx: TypeCheckContext, + ctx: &TypeCheckContext, type_parameters: &[TypeParameter], access_span: &Span, ) -> CompileResult { @@ -297,7 +297,7 @@ impl TypeParameter { } = trait_constraint; let (trait_interface_item_refs, trait_item_refs, trait_impld_item_refs) = check!( - handle_trait(ctx.by_ref(), *type_id, trait_name, trait_type_arguments), + handle_trait(ctx, *type_id, trait_name, trait_type_arguments), continue, warnings, errors @@ -322,7 +322,7 @@ impl TypeParameter { } fn handle_trait( - mut ctx: TypeCheckContext, + ctx: &TypeCheckContext, type_id: TypeId, trait_name: &CallPath, type_arguments: &[TypeArgument], @@ -347,7 +347,7 @@ fn handle_trait( let (trait_interface_item_refs, trait_item_refs, trait_impld_item_refs) = trait_decl .retrieve_interface_surface_and_items_and_implemented_items_for_type( - ctx.by_ref(), + ctx, type_id, trait_name, type_arguments, @@ -362,7 +362,7 @@ fn handle_trait( supertrait_item_refs, supertrait_impld_item_refs, ) = check!( - handle_trait(ctx.by_ref(), type_id, &supertrait.name, &[]), + handle_trait(ctx, type_id, &supertrait.name, &[]), continue, warnings, errors diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_tuple_trait/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_tuple_trait/src/main.sw index 499773982d4..1f5f470720b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_tuple_trait/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_tuple_trait/src/main.sw @@ -22,6 +22,14 @@ impl Trait2 for u64 { } } +struct S {} + +impl Trait2 for S { + fn method2(self) -> u64 { + 2 + } +} + impl Trait2 for (A, B) where A: Trait2, B: Trait2 { fn method2(self) -> u64 { self.0.method2() + self.1.method2() @@ -31,5 +39,9 @@ impl Trait2 for (A, B) where A: Trait2, B: Trait2 { fn main() -> bool { assert((1,2).method() == 42); assert((1,2).method2() == 3); + assert((1, S{}).method2() == 3); + assert(((1,2),(1,2)).method2() == 6); + assert(((1, S{}),(1,(1,2))).method2() == 7); + true }