Skip to content

Commit

Permalink
Rework trait mapping code to be item-based. (FuelLabs#4179)
Browse files Browse the repository at this point in the history
## Description

This splits off the trait mapping refactoring changes out of
FuelLabs#4036.

No functional changes intended.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.
  • Loading branch information
tritao authored Feb 27, 2023
1 parent e8dee04 commit 10545f9
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 126 deletions.
38 changes: 31 additions & 7 deletions sway-core/src/decl_engine/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::fmt;

use super::{DeclId, MethodMap};
use crate::language::ty::{TyTraitInterfaceItem, TyTraitItem};

use super::{DeclId, InterfaceItemMap, ItemMap};

type SourceDecl = DeclId;
type DestinationDecl = DeclId;
Expand Down Expand Up @@ -46,14 +48,36 @@ impl DeclMapping {
self.mapping.is_empty()
}

pub(crate) fn from_stub_and_impld_decl_refs(
stub_decl_refs: MethodMap,
impld_decl_refs: MethodMap,
pub(crate) fn from_interface_and_item_and_impld_decl_refs(
interface_decl_refs: InterfaceItemMap,
item_decl_refs: ItemMap,
impld_decl_refs: ItemMap,
) -> DeclMapping {
let mut mapping = vec![];
for (stub_decl_name, stub_decl_ref) in stub_decl_refs.into_iter() {
if let Some(new_decl_ref) = impld_decl_refs.get(&stub_decl_name) {
mapping.push(((&stub_decl_ref).into(), new_decl_ref.into()));
for (interface_decl_name, interface_item) in interface_decl_refs.into_iter() {
if let Some(new_item) = impld_decl_refs.get(&interface_decl_name) {
#[allow(clippy::infallible_destructuring_match)]
let interface_decl_ref = match interface_item {
TyTraitInterfaceItem::TraitFn(decl_ref) => decl_ref,
};
#[allow(clippy::infallible_destructuring_match)]
let new_decl_ref = match new_item {
TyTraitItem::Fn(decl_ref) => decl_ref,
};
mapping.push(((&interface_decl_ref).into(), new_decl_ref.into()));
}
}
for (decl_name, item) in item_decl_refs.into_iter() {
if let Some(new_item) = impld_decl_refs.get(&decl_name) {
#[allow(clippy::infallible_destructuring_match)]
let interface_decl_ref = match item {
TyTraitItem::Fn(decl_ref) => decl_ref,
};
#[allow(clippy::infallible_destructuring_match)]
let new_decl_ref = match new_item {
TyTraitItem::Fn(decl_ref) => decl_ref,
};
mapping.push(((&interface_decl_ref).into(), new_decl_ref.into()));
}
}
DeclMapping { mapping }
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/decl_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ pub(crate) use replace_decls::*;
use sway_types::Ident;
pub(crate) use wrapper::*;

pub(crate) type MethodMap = BTreeMap<Ident, DeclRef>;
use crate::language::ty::{TyTraitInterfaceItem, TyTraitItem};

pub(crate) type InterfaceItemMap = BTreeMap<Ident, TyTraitInterfaceItem>;
pub(crate) type ItemMap = BTreeMap<Ident, TyTraitItem>;
69 changes: 34 additions & 35 deletions sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
error::*,
language::{
parsed::*,
ty::{self, TyImplItem, TyTraitInterfaceItem},
ty::{self, TyImplItem, TyTraitInterfaceItem, TyTraitItem},
*,
},
semantic_analysis::{Mode, TypeCheckContext},
Expand Down Expand Up @@ -597,19 +597,19 @@ fn type_check_trait_implementation(
// that still need to be implemented for the trait to be fully implemented.
let mut method_checklist: BTreeMap<Ident, ty::TyTraitFn> = BTreeMap::new();

// This map keeps track of the stub declaration id's of the trait
// This map keeps track of the interface declaration id's of the trait
// definition.
let mut stub_method_refs: MethodMap = BTreeMap::new();
let mut interface_item_refs: InterfaceItemMap = BTreeMap::new();

// This map keeps track of the new declaration ids of the implemented
// interface surface.
let mut impld_method_refs: MethodMap = BTreeMap::new();
let mut impld_item_refs: ItemMap = BTreeMap::new();

// This map keeps track of the stub declaration id's of the supertraits.
let mut supertrait_stub_method_refs: MethodMap = BTreeMap::new();
let mut supertrait_interface_item_refs: InterfaceItemMap = BTreeMap::new();

// This map keeps track of the new declaration ids of the supertraits.
let mut supertrait_impld_method_refs: MethodMap = BTreeMap::new();
let mut supertrait_impld_item_refs: ItemMap = BTreeMap::new();

// Insert the implemented methods for the supertraits into this namespace
// so that the methods defined in the impl block can use them.
Expand All @@ -632,15 +632,14 @@ fn type_check_trait_implementation(
&this_supertrait_impld_method_refs
.values()
.cloned()
.map(TyImplItem::Fn)
.collect::<Vec<_>>(),
&trait_name.span(),
false,
engines,
);

supertrait_stub_method_refs = this_supertrait_stub_method_refs;
supertrait_impld_method_refs = this_supertrait_impld_method_refs;
supertrait_interface_item_refs = this_supertrait_stub_method_refs;
supertrait_impld_item_refs = this_supertrait_impld_method_refs;
}

for item in trait_interface_surface.iter() {
Expand All @@ -657,8 +656,8 @@ fn type_check_trait_implementation(
// Add this method to the checklist.
method_checklist.insert(name.clone(), method);

// Add this method to the "stub methods".
stub_method_refs.insert(name, decl_ref.clone());
// Add this method to the "interface items".
interface_item_refs.insert(name, item.clone());
}
}
}
Expand All @@ -673,7 +672,7 @@ fn type_check_trait_implementation(
impl_method,
trait_name,
is_contract,
&impld_method_refs,
&impld_item_refs,
&method_checklist
),
ty::TyFunctionDeclaration::error(impl_method.clone()),
Expand All @@ -685,17 +684,14 @@ fn type_check_trait_implementation(
let name = impl_method.name.clone();
method_checklist.remove(&name);

// Add this method to the "impld methods".
// Add this method to the "impld items".
let decl_ref = decl_engine.insert(impl_method);
impld_method_refs.insert(name, decl_ref);
impld_item_refs.insert(name, TyTraitItem::Fn(decl_ref));
}
}
}

let mut all_items_refs: Vec<TyImplItem> = impld_method_refs
.values()
.map(|decl_ref| TyImplItem::Fn(decl_ref.clone()))
.collect();
let mut all_items_refs: Vec<TyImplItem> = impld_item_refs.values().cloned().collect();

// Retrieve the methods defined on the trait declaration and transform
// them into the correct typing for this impl block by using the type
Expand All @@ -713,10 +709,13 @@ fn type_check_trait_implementation(
.map(|type_arg| type_arg.type_id)
.collect(),
);
stub_method_refs.extend(supertrait_stub_method_refs);
impld_method_refs.extend(supertrait_impld_method_refs);
let decl_mapping =
DeclMapping::from_stub_and_impld_decl_refs(stub_method_refs, impld_method_refs);
interface_item_refs.extend(supertrait_interface_item_refs);
impld_item_refs.extend(supertrait_impld_item_refs);
let decl_mapping = DeclMapping::from_interface_and_item_and_impld_decl_refs(
interface_item_refs,
BTreeMap::new(),
impld_item_refs,
);
for item in trait_items.iter() {
match item {
TyImplItem::Fn(decl_ref) => {
Expand Down Expand Up @@ -763,7 +762,7 @@ fn type_check_impl_method(
impl_method: &FunctionDeclaration,
trait_name: &CallPath,
is_contract: bool,
impld_method_refs: &MethodMap,
impld_item_refs: &ItemMap,
method_checklist: &BTreeMap<Ident, ty::TyTraitFn>,
) -> CompileResult<ty::TyFunctionDeclaration> {
let mut warnings = vec![];
Expand Down Expand Up @@ -796,7 +795,7 @@ fn type_check_impl_method(
);

// Ensure that there aren't multiple definitions of this function impl'd
if impld_method_refs.contains_key(&impl_method.name.clone()) {
if impld_item_refs.contains_key(&impl_method.name.clone()) {
errors.push(CompileError::MultipleDefinitionsOfFunction {
name: impl_method.name.clone(),
span: impl_method.name.span(),
Expand Down Expand Up @@ -1094,14 +1093,14 @@ fn check_for_unconstrained_type_parameters(
fn handle_supertraits(
mut ctx: TypeCheckContext,
supertraits: &[Supertrait],
) -> CompileResult<(MethodMap, MethodMap)> {
) -> CompileResult<(InterfaceItemMap, ItemMap)> {
let mut warnings = Vec::new();
let mut errors = Vec::new();

let decl_engine = ctx.decl_engine;

let mut interface_surface_methods_ids: MethodMap = BTreeMap::new();
let mut impld_method_refs: MethodMap = BTreeMap::new();
let mut interface_surface_item_ids: InterfaceItemMap = BTreeMap::new();
let mut impld_item_refs: ItemMap = BTreeMap::new();
let self_type = ctx.self_type();

for supertrait in supertraits.iter() {
Expand Down Expand Up @@ -1143,25 +1142,25 @@ fn handle_supertraits(

// Retrieve the interface surface and implemented method ids for
// this trait.
let (trait_interface_surface_methods_ids, trait_impld_method_refs) = trait_decl
.retrieve_interface_surface_and_implemented_methods_for_type(
let (trait_interface_surface_items_ids, trait_impld_item_refs) = trait_decl
.retrieve_interface_surface_and_implemented_items_for_type(
ctx.by_ref(),
self_type,
&supertrait.name,
);
interface_surface_methods_ids.extend(trait_interface_surface_methods_ids);
impld_method_refs.extend(trait_impld_method_refs);
interface_surface_item_ids.extend(trait_interface_surface_items_ids);
impld_item_refs.extend(trait_impld_item_refs);

// Retrieve the interface surfaces and implemented methods for
// the supertraits of this type.
let (next_stub_supertrait_decl_refs, next_these_supertrait_decl_refs) = check!(
let (next_interface_supertrait_decl_refs, next_these_supertrait_decl_refs) = check!(
handle_supertraits(ctx.by_ref(), &trait_decl.supertraits),
continue,
warnings,
errors
);
interface_surface_methods_ids.extend(next_stub_supertrait_decl_refs);
impld_method_refs.extend(next_these_supertrait_decl_refs);
interface_surface_item_ids.extend(next_interface_supertrait_decl_refs);
impld_item_refs.extend(next_these_supertrait_decl_refs);
}
Some(ty::TyDeclaration::AbiDeclaration { .. }) => {
errors.push(CompileError::AbiAsSupertrait {
Expand All @@ -1177,7 +1176,7 @@ fn handle_supertraits(

if errors.is_empty() {
ok(
(interface_surface_methods_ids, impld_method_refs),
(interface_surface_item_ids, impld_item_refs),
warnings,
errors,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) fn insert_supertraits_into_namespace(
// Insert the interface surface and methods from this trait into
// the namespace.
check!(
trait_decl.insert_interface_surface_and_methods_into_namespace(
trait_decl.insert_interface_surface_and_items_into_namespace(
ctx.by_ref(),
&supertrait.name,
&type_arguments,
Expand Down
Loading

0 comments on commit 10545f9

Please sign in to comment.