Skip to content

Commit 6785778

Browse files
committed
Adds tests and fixes find_method_for_type.
1 parent 70c95bf commit 6785778

File tree

14 files changed

+436
-103
lines changed

14 files changed

+436
-103
lines changed

sway-core/src/language/ty/declaration/function.rs

+19
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,25 @@ impl TyFunctionDecl {
487487
_ => Some(false),
488488
}
489489
}
490+
491+
pub fn is_from_blanket_impl(&self, engines: &Engines) -> bool {
492+
if let Some(TyDecl::ImplSelfOrTrait(existing_impl_trait)) = self.implementing_type.clone() {
493+
let existing_trait_decl = engines
494+
.de()
495+
.get_impl_self_or_trait(&existing_impl_trait.decl_id);
496+
if !existing_trait_decl.impl_type_parameters.is_empty()
497+
&& matches!(
498+
*engines
499+
.te()
500+
.get(existing_trait_decl.implementing_for.type_id),
501+
TypeInfo::UnknownGeneric { .. }
502+
)
503+
{
504+
return true;
505+
}
506+
}
507+
false
508+
}
490509
}
491510

492511
#[derive(Debug, Clone)]

sway-core/src/semantic_analysis/namespace/trait_map.rs

+60-15
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ enum TypeRootFilter {
198198
pub(crate) struct TraitMap {
199199
trait_impls: TraitImpls,
200200
satisfied_cache: im::HashSet<u64>,
201-
insert_for_type_cache: im::HashSet<TypeId>,
201+
insert_for_type_cache: im::HashMap<TypeRootFilter, im::Vector<TypeId>>,
202202
}
203203

204204
pub(crate) enum IsImplSelf {
@@ -247,8 +247,9 @@ impl TraitMap {
247247
.filter(|t| t.type_id == type_id_type_parameter.type_id)
248248
.last();
249249
if let Some(impl_type_parameter) = impl_type_parameter {
250-
type_id_type_parameter.trait_constraints =
251-
impl_type_parameter.trait_constraints.clone();
250+
type_id_type_parameter
251+
.trait_constraints
252+
.clone_from(&impl_type_parameter.trait_constraints);
252253
}
253254
}
254255
handler.scope(|handler| {
@@ -383,7 +384,7 @@ impl TraitMap {
383384
if type_id_type_parameter
384385
.type_id
385386
.is_concrete(engines, crate::TreatNumericAs::Abstract)
386-
&& !self
387+
&& self
387388
.check_if_trait_constraints_are_satisfied_for_type(
388389
&Handler::default(),
389390
type_id_type_parameter.type_id,
@@ -393,7 +394,7 @@ impl TraitMap {
393394
TryInsertingTraitImplOnFailure::Yes,
394395
CodeBlockFirstPass::No,
395396
)
396-
.is_ok()
397+
.is_err()
397398
{
398399
trait_constraints_safified = false;
399400
}
@@ -508,6 +509,7 @@ impl TraitMap {
508509
})
509510
}
510511

512+
#[allow(clippy::too_many_arguments)]
511513
fn insert_inner(
512514
&mut self,
513515
trait_name: TraitName,
@@ -519,15 +521,16 @@ impl TraitMap {
519521
engines: &Engines,
520522
) {
521523
let key = TraitKey {
522-
name: trait_name,
524+
name: trait_name.clone(),
523525
type_id,
524526
type_id_type_parameters,
525527
trait_decl_span,
526528
};
527529
let value = TraitValue {
528-
trait_items: trait_methods,
530+
trait_items: trait_methods.clone(),
529531
impl_span,
530532
};
533+
531534
let entry = TraitEntry { key, value };
532535
let mut trait_impls: TraitImpls =
533536
im::HashMap::<TypeRootFilter, im::Vector<TraitEntry>>::new();
@@ -539,7 +542,7 @@ impl TraitMap {
539542
let trait_map = TraitMap {
540543
trait_impls,
541544
satisfied_cache: im::HashSet::default(),
542-
insert_for_type_cache: im::HashSet::default(),
545+
insert_for_type_cache: im::HashMap::<TypeRootFilter, im::Vector<TypeId>>::new(),
543546
};
544547

545548
self.extend(trait_map, engines);
@@ -637,10 +640,18 @@ impl TraitMap {
637640
type_id: TypeId,
638641
code_block_first_pass: CodeBlockFirstPass,
639642
) {
640-
if self.insert_for_type_cache.contains(&type_id) {
641-
return;
643+
let root_filter = TraitMap::get_type_root_filter(engines, type_id);
644+
if let Some(values) = self.insert_for_type_cache.get_mut(&root_filter) {
645+
let unify_checker = UnifyCheck::non_dynamic_equality(engines).with_unify_ref_mut(false);
646+
if values.iter().any(|v| unify_checker.check(type_id, *v)) {
647+
return;
648+
} else {
649+
values.push_back(type_id);
650+
}
651+
} else {
652+
self.insert_for_type_cache
653+
.insert(root_filter, vec![type_id].into());
642654
}
643-
self.insert_for_type_cache.insert(type_id);
644655

645656
self.extend(
646657
self.filter_by_type(type_id, engines, code_block_first_pass),
@@ -666,10 +677,44 @@ impl TraitMap {
666677
});
667678

668679
match pos {
669-
Ok(pos) => self_vec[pos]
670-
.value
671-
.trait_items
672-
.extend(oe.value.trait_items.clone()),
680+
Ok(pos) => {
681+
let mut skip_insert = false;
682+
683+
// If we have the same method in: impl<T> FromBytes for T
684+
// and: impl FromBytes for DataPoint
685+
// We keep the second implementation.
686+
for (name, item) in oe.value.trait_items.iter() {
687+
for (existing_name, existing_item) in
688+
self_vec[pos].value.trait_items.iter()
689+
{
690+
if name == existing_name {
691+
if let (
692+
TyTraitItem::Fn(fn_ref),
693+
TyTraitItem::Fn(existing_fn_ref),
694+
) = (
695+
item.clone().expect_typed(),
696+
existing_item.clone().expect_typed(),
697+
) {
698+
let method = engines.de().get_function(fn_ref.id());
699+
let existing_method =
700+
engines.de().get_function(existing_fn_ref.id());
701+
if !existing_method.is_from_blanket_impl(engines)
702+
&& method.is_from_blanket_impl(engines)
703+
{
704+
skip_insert = true;
705+
}
706+
}
707+
}
708+
}
709+
}
710+
711+
if !skip_insert {
712+
self_vec[pos]
713+
.value
714+
.trait_items
715+
.extend(oe.value.trait_items.clone())
716+
}
717+
}
673718
Err(pos) => self_vec.insert(pos, oe.clone()),
674719
}
675720
}

0 commit comments

Comments
 (0)