Skip to content

Commit

Permalink
Fixes replace_decls issue with nested and multiple types.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
esdrubal committed Jul 31, 2023
1 parent b19174a commit 27a84cc
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 91 deletions.
28 changes: 26 additions & 2 deletions sway-core/src/decl_engine/mapping.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 }
}
}
9 changes: 6 additions & 3 deletions sway-core/src/decl_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ident, TyTraitInterfaceItem>;
pub(crate) type ItemMap = BTreeMap<Ident, TyTraitItem>;
pub(crate) type InterfaceItemMap = BTreeMap<(Ident, TypeId), TyTraitInterfaceItem>;
pub(crate) type ItemMap = BTreeMap<(Ident, TypeId), TyTraitItem>;
10 changes: 6 additions & 4 deletions sway-core/src/decl_engine/ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::{
self, TyAbiDecl, TyConstantDecl, TyEnumDecl, TyFunctionDecl, TyImplTrait, TyStorageDecl,
TyStructDecl, TyTraitDecl, TyTraitFn,
},
semantic_analysis::TypeCheckContext,
type_system::*,
};

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions sway-core/src/decl_engine/replace_decls.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions sway-core/src/language/ty/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
engine_threading::*,
error::*,
language::{parsed::TreeType, ty::*, Visibility},
semantic_analysis::TypeCheckContext,
transform::AttributeKind,
type_system::*,
types::*,
Expand Down Expand Up @@ -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(_) => (),
}
}
Expand Down
8 changes: 4 additions & 4 deletions sway-core/src/language/ty/code_block.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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));
}
}

Expand Down
5 changes: 3 additions & 2 deletions sway-core/src/language/ty/declaration/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
decl_engine::{DeclMapping, ReplaceDecls},
engine_threading::*,
language::{ty::*, CallPath, Visibility},
semantic_analysis::TypeCheckContext,
transform,
type_system::*,
};
Expand Down Expand Up @@ -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);
}
}
}
5 changes: 3 additions & 2 deletions sway-core/src/language/ty/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
engine_threading::*,
error::*,
language::{parsed, ty::*, Inline, Purity, Visibility},
semantic_analysis::TypeCheckContext,
transform,
type_system::*,
types::*,
Expand Down Expand Up @@ -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);
}
}

Expand Down
5 changes: 3 additions & 2 deletions sway-core/src/language/ty/expression/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
engine_threading::*,
error::*,
language::{ty::*, Literal},
semantic_analysis::TypeCheckContext,
type_system::*,
types::*,
};
Expand Down Expand Up @@ -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);
}
}

Expand Down
Loading

0 comments on commit 27a84cc

Please sign in to comment.