Skip to content

Commit

Permalink
Adds TypeFilter to TraitMap.
Browse files Browse the repository at this point in the history
  • Loading branch information
esdrubal committed Nov 25, 2024
1 parent 465d3fc commit 63e964b
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 15 deletions.
122 changes: 119 additions & 3 deletions sway-core/src/semantic_analysis/namespace/trait_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,37 @@ enum TypeRootFilter {
TraitType(String),
}

#[derive(Clone, Hash, Eq, PartialEq, Debug)]
enum TypeFilter {
Unknown,
Never,
Placeholder,
TypeParam(usize),
StringSlice,
StringArray(usize),
U8,
U16,
U32,
U64,
U256,
Bool,
Custom(String),
B256,
Contract,
ErrorRecovery,
Tuple(usize, Vec<Box<TypeFilter>>),
Enum(ParsedDeclId<EnumDeclaration>, Vec<Box<TypeFilter>>),
Struct(ParsedDeclId<StructDeclaration>, Vec<Box<TypeFilter>>),
ContractCaller(String),
Array(usize, Box<TypeFilter>),
Storage,
RawUntypedPtr,
RawUntypedSlice,
Ptr(Box<TypeFilter>),
Slice(Box<TypeFilter>),
TraitType(String),
}

/// Map holding trait implementations for types.
///
/// Note: "impl self" blocks are considered traits and are stored in the
Expand All @@ -198,7 +229,7 @@ enum TypeRootFilter {
pub(crate) struct TraitMap {
trait_impls: TraitImpls,
satisfied_cache: im::HashSet<u64>,
insert_for_type_cache: im::HashMap<TypeRootFilter, im::Vector<TypeId>>,
insert_for_type_cache: im::HashMap<TypeFilter, im::Vector<TypeId>>,
}

pub(crate) enum IsImplSelf {
Expand Down Expand Up @@ -542,7 +573,7 @@ impl TraitMap {
let trait_map = TraitMap {
trait_impls,
satisfied_cache: im::HashSet::default(),
insert_for_type_cache: im::HashMap::<TypeRootFilter, im::Vector<TypeId>>::new(),
insert_for_type_cache: im::HashMap::<TypeFilter, im::Vector<TypeId>>::new(),
};

self.extend(trait_map, engines);
Expand Down Expand Up @@ -640,7 +671,7 @@ impl TraitMap {
type_id: TypeId,
code_block_first_pass: CodeBlockFirstPass,
) {
let root_filter = TraitMap::get_type_root_filter(engines, type_id);
let root_filter = TraitMap::get_type_filter(engines, type_id);
if let Some(values) = self.insert_for_type_cache.get_mut(&root_filter) {
let unify_checker = UnifyCheck::non_dynamic_equality(engines).with_unify_ref_mut(false);
if values.iter().any(|v| unify_checker.check(type_id, *v)) {
Expand Down Expand Up @@ -1732,4 +1763,89 @@ impl TraitMap {
} => Self::get_type_root_filter(engines, referenced_type.type_id),
}
}

// This is used by the trait map to filter the entries into a HashMap with the return type string as key.
fn get_type_filter(engines: &Engines, type_id: TypeId) -> TypeFilter {
use TypeInfo::*;
match &*engines.te().get(type_id) {
Unknown => TypeFilter::Unknown,
Never => TypeFilter::Never,
UnknownGeneric { .. } | Placeholder(_) => TypeFilter::Placeholder,
TypeParam(n) => TypeFilter::TypeParam(*n),
StringSlice => TypeFilter::StringSlice,
StringArray(x) => TypeFilter::StringArray(x.val()),
UnsignedInteger(x) => match x {
IntegerBits::Eight => TypeFilter::U8,
IntegerBits::Sixteen => TypeFilter::U16,
IntegerBits::ThirtyTwo => TypeFilter::U32,
IntegerBits::SixtyFour => TypeFilter::U64,
IntegerBits::V256 => TypeFilter::U256,
},
Boolean => TypeFilter::Bool,
Custom {
qualified_call_path: call_path,
..
} => TypeFilter::Custom(call_path.call_path.suffix.to_string()),
B256 => TypeFilter::B256,
Numeric => TypeFilter::U64, // u64 is the default
Contract => TypeFilter::Contract,
ErrorRecovery(_) => TypeFilter::ErrorRecovery,
Tuple(fields) => TypeFilter::Tuple(
fields.len(),
fields
.iter()
.map(|f| Box::new(Self::get_type_filter(engines, f.type_id)))
.collect::<Vec<_>>(),
),
UntypedEnum(_) => unreachable!(),
UntypedStruct(_) => unreachable!(),
Enum(decl_id) => {
// TODO Remove unwrap once #6475 is fixed
TypeFilter::Enum(
engines.de().get_parsed_decl_id(decl_id).unwrap(),
engines
.de()
.get_enum(decl_id)
.type_parameters
.iter()
.map(|f| Box::new(Self::get_type_filter(engines, f.type_id)))
.collect::<Vec<_>>(),
)
}
Struct(decl_id) => {
// TODO Remove unwrap once #6475 is fixed
TypeFilter::Struct(
engines.de().get_parsed_decl_id(decl_id).unwrap(),
engines
.de()
.get_struct(decl_id)
.type_parameters
.iter()
.map(|f| Box::new(Self::get_type_filter(engines, f.type_id)))
.collect::<Vec<_>>(),
)
}
ContractCaller { abi_name, .. } => TypeFilter::ContractCaller(abi_name.to_string()),
Array(type_argument, length) => TypeFilter::Array(
length.val(),
Box::new(Self::get_type_filter(engines, type_argument.type_id)),
),
Storage { .. } => TypeFilter::Storage,
RawUntypedPtr => TypeFilter::RawUntypedPtr,
RawUntypedSlice => TypeFilter::RawUntypedSlice,
Ptr(type_argument) => TypeFilter::Ptr(Box::new(Self::get_type_filter(
engines,
type_argument.type_id,
))),
Slice(type_argument) => TypeFilter::Slice(Box::new(Self::get_type_filter(
engines,
type_argument.type_id,
))),
Alias { ty, .. } => Self::get_type_filter(engines, ty.type_id),
TraitType { name, .. } => TypeFilter::TraitType(name.to_string()),
Ref {
referenced_type, ..
} => Self::get_type_filter(engines, referenced_type.type_id),
}
}
}
12 changes: 0 additions & 12 deletions sway-core/src/semantic_analysis/type_check_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,18 +1224,6 @@ impl<'a> TypeCheckContext<'a> {
.values()
.filter_map(|method_ref| {
let method = decl_engine.get_function(method_ref);

//if method.name.clone().as_str() == "new" {
println!(
"find_method_for_type {:?} {:?}",
method.implementing_for_typeid.map(|t| {
self.engines
.help_out((*self.engines.te().get(t)).clone())
}),
method.name.clone(),
);
//}

method
.span()
.to_string_path_with_line_col(self.engines().se())
Expand Down

0 comments on commit 63e964b

Please sign in to comment.