From 74ec7239fcc5664e97fd41b0987967e671c742b6 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 7 Jan 2025 15:58:38 -0300 Subject: [PATCH] fix: wrong module to lookup trait when using crate or super (#6974) --- .../src/elaborator/path_resolution.rs | 11 ++++--- compiler/noirc_frontend/src/tests/traits.rs | 32 ++++++++++++++++++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/compiler/noirc_frontend/src/elaborator/path_resolution.rs b/compiler/noirc_frontend/src/elaborator/path_resolution.rs index 0cf53fad0e4..f9f6fff56e0 100644 --- a/compiler/noirc_frontend/src/elaborator/path_resolution.rs +++ b/compiler/noirc_frontend/src/elaborator/path_resolution.rs @@ -286,7 +286,8 @@ impl<'context> Elaborator<'context> { // Check if namespace let found_ns = if current_module_id_is_struct { - match self.resolve_struct_function(starting_module, current_module, current_ident) { + match self.resolve_struct_function(importing_module, current_module, current_ident) + { StructMethodLookupResult::NotFound(vec) => { if vec.is_empty() { return Err(PathResolutionError::Unresolved(current_ident.clone())); @@ -306,7 +307,7 @@ impl<'context> Elaborator<'context> { StructMethodLookupResult::FoundStructMethod(per_ns) => per_ns, StructMethodLookupResult::FoundTraitMethod(per_ns, trait_id) => { let trait_ = self.interner.get_trait(trait_id); - self.usage_tracker.mark_as_used(starting_module, &trait_.name); + self.usage_tracker.mark_as_used(importing_module, &trait_.name); per_ns } StructMethodLookupResult::FoundOneTraitMethodButNotInScope( @@ -324,7 +325,7 @@ impl<'context> Elaborator<'context> { StructMethodLookupResult::FoundMultipleTraitMethods(vec) => { let traits = vecmap(vec, |trait_id| { let trait_ = self.interner.get_trait(trait_id); - self.usage_tracker.mark_as_used(starting_module, &trait_.name); + self.usage_tracker.mark_as_used(importing_module, &trait_.name); self.fully_qualified_trait_path(trait_) }); return Err(PathResolutionError::MultipleTraitsInScope { @@ -382,7 +383,7 @@ impl<'context> Elaborator<'context> { fn resolve_struct_function( &self, - starting_module_id: ModuleId, + importing_module_id: ModuleId, current_module: &ModuleData, ident: &Ident, ) -> StructMethodLookupResult { @@ -402,7 +403,7 @@ impl<'context> Elaborator<'context> { } // Otherwise, the function could be defined in zero, one or more traits. - let starting_module = self.get_module(starting_module_id); + let starting_module = self.get_module(importing_module_id); // Gather a list of items for which their trait is in scope. let mut results = Vec::new(); diff --git a/compiler/noirc_frontend/src/tests/traits.rs b/compiler/noirc_frontend/src/tests/traits.rs index a5d1591e012..ff4cd6929af 100644 --- a/compiler/noirc_frontend/src/tests/traits.rs +++ b/compiler/noirc_frontend/src/tests/traits.rs @@ -717,7 +717,7 @@ fn calls_trait_function_if_it_is_in_scope() { } #[test] -fn calls_trait_function_it_is_only_candidate_in_scope() { +fn calls_trait_function_if_it_is_only_candidate_in_scope() { let src = r#" use private_mod::Foo; @@ -753,6 +753,36 @@ fn calls_trait_function_it_is_only_candidate_in_scope() { assert_no_errors(src); } +#[test] +fn calls_trait_function_if_it_is_only_candidate_in_scope_in_nested_module_using_super() { + let src = r#" + mod moo { + use super::public_mod::Foo; + + pub fn method() { + let _ = super::Bar::foo(); + } + } + + fn main() {} + + pub struct Bar {} + + pub mod public_mod { + pub trait Foo { + fn foo() -> i32; + } + + impl Foo for super::Bar { + fn foo() -> i32 { + 42 + } + } + } + "#; + assert_no_errors(src); +} + #[test] fn errors_if_trait_is_not_in_scope_for_function_call_and_there_are_multiple_candidates() { let src = r#"