diff --git a/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs index 320b85e70c..0e26d0b5bd 100644 --- a/compiler/noirc_frontend/src/elaborator/types.rs +++ b/compiler/noirc_frontend/src/elaborator/types.rs @@ -30,7 +30,7 @@ use crate::{ traits::{NamedType, ResolvedTraitBound, Trait, TraitConstraint}, }, node_interner::{ - DependencyId, ExprId, GlobalValue, ImplSearchErrorKind, NodeInterner, TraitId, + DependencyId, ExprId, FuncId, GlobalValue, ImplSearchErrorKind, NodeInterner, TraitId, TraitImplKind, TraitMethodId, }, token::SecondaryAttribute, @@ -1426,7 +1426,7 @@ impl<'context> Elaborator<'context> { // Only keep unique trait IDs: multiple trait methods might come from the same trait // but implemented with different generics (like `Convert` and `Convert`). let traits: HashSet = - trait_methods.into_iter().map(|(_, trait_id)| trait_id).collect(); + trait_methods.iter().map(|(_, trait_id)| *trait_id).collect(); let traits_in_scope: Vec<_> = traits .iter() @@ -1457,15 +1457,18 @@ impl<'context> Elaborator<'context> { let trait_id = *traits.iter().next().unwrap(); let trait_ = self.interner.get_trait(trait_id); let trait_name = self.fully_qualified_trait_path(trait_); - let generics = trait_.as_constraint(span).trait_bound.trait_generics; - let trait_method_id = trait_.find_method(method_name).unwrap(); self.push_err(PathResolutionError::TraitMethodNotInScope { ident: Ident::new(method_name.into(), span), trait_name, }); - return Some(HirMethodReference::TraitMethodId(trait_method_id, generics, false)); + return Some(self.trait_hir_method_reference( + trait_id, + trait_methods, + method_name, + span, + )); } else { let traits = vecmap(traits, |trait_id| { let trait_ = self.interner.get_trait(trait_id); @@ -1491,12 +1494,28 @@ impl<'context> Elaborator<'context> { return None; } - // Return a TraitMethodId with unbound generics. These will later be bound by the type-checker. let trait_id = traits_in_scope[0].0; + Some(self.trait_hir_method_reference(trait_id, trait_methods, method_name, span)) + } + + fn trait_hir_method_reference( + &self, + trait_id: TraitId, + trait_methods: Vec<(FuncId, TraitId)>, + method_name: &str, + span: Span, + ) -> HirMethodReference { + // If we find a single trait impl method, return it so we don't have to later determine the impl + if trait_methods.len() == 1 { + let (func_id, _) = trait_methods[0]; + return HirMethodReference::FuncId(func_id); + } + + // Return a TraitMethodId with unbound generics. These will later be bound by the type-checker. let trait_ = self.interner.get_trait(trait_id); let generics = trait_.as_constraint(span).trait_bound.trait_generics; let trait_method_id = trait_.find_method(method_name).unwrap(); - Some(HirMethodReference::TraitMethodId(trait_method_id, generics, false)) + HirMethodReference::TraitMethodId(trait_method_id, generics, false) } fn lookup_method_in_trait_constraints(