From 19b64150a2031089f5a957d445a35030c666ae46 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 28 Oct 2024 06:54:24 -0300 Subject: [PATCH] fix: remove assumed parent traits --- compiler/noirc_frontend/src/node_interner.rs | 25 ++++++++++++++++++++ compiler/noirc_frontend/src/tests/traits.rs | 21 ++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 2183cfba0ef..5fe88ed4e23 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -1875,8 +1875,33 @@ impl NodeInterner { /// Removes all TraitImplKind::Assumed from the list of known impls for the given trait pub fn remove_assumed_trait_implementations_for_trait(&mut self, trait_id: TraitId) { + self.remove_assumed_trait_implementations_for_trait_and_parents(trait_id, trait_id); + } + + fn remove_assumed_trait_implementations_for_trait_and_parents( + &mut self, + trait_id: TraitId, + starting_trait_id: TraitId, + ) { let entries = self.trait_implementation_map.entry(trait_id).or_default(); entries.retain(|(_, kind)| matches!(kind, TraitImplKind::Normal(_))); + + // Also remove assumed implementations for the parent traits, if any + if let Some(trait_bounds) = + self.try_get_trait(trait_id).map(|the_trait| the_trait.trait_bounds.clone()) + { + for parent_trait_bound in trait_bounds { + // Avoid looping forever in case there are cycles + if parent_trait_bound.trait_id == starting_trait_id { + continue; + } + + self.remove_assumed_trait_implementations_for_trait_and_parents( + parent_trait_bound.trait_id, + starting_trait_id, + ); + } + } } /// Tags the given identifier with the selected trait_impl so that monomorphization diff --git a/compiler/noirc_frontend/src/tests/traits.rs b/compiler/noirc_frontend/src/tests/traits.rs index 88138ecde4d..dd6430a94cc 100644 --- a/compiler/noirc_frontend/src/tests/traits.rs +++ b/compiler/noirc_frontend/src/tests/traits.rs @@ -261,3 +261,24 @@ fn errors_if_impl_trait_constraint_is_not_satisfied() { assert_eq!(typ, "SomeGreeter"); assert_eq!(impl_trait, "Foo"); } + +#[test] +fn removes_assumed_parent_traits_after_function_ends() { + let src = r#" + trait Foo {} + trait Bar: Foo {} + + pub fn foo() + where + T: Bar, + {} + + pub fn bar() + where + T: Foo, + {} + + fn main() {} + "#; + assert_no_errors(src); +}