Skip to content

Commit 8d7f1f9

Browse files
authored
fix: return trait impl method as FuncId if there's only one (#6989)
1 parent 101f2d4 commit 8d7f1f9

1 file changed

Lines changed: 26 additions & 7 deletions

File tree

  • compiler/noirc_frontend/src/elaborator

compiler/noirc_frontend/src/elaborator/types.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::{
3030
traits::{NamedType, ResolvedTraitBound, Trait, TraitConstraint},
3131
},
3232
node_interner::{
33-
DependencyId, ExprId, GlobalValue, ImplSearchErrorKind, NodeInterner, TraitId,
33+
DependencyId, ExprId, FuncId, GlobalValue, ImplSearchErrorKind, NodeInterner, TraitId,
3434
TraitImplKind, TraitMethodId,
3535
},
3636
token::SecondaryAttribute,
@@ -1426,7 +1426,7 @@ impl<'context> Elaborator<'context> {
14261426
// Only keep unique trait IDs: multiple trait methods might come from the same trait
14271427
// but implemented with different generics (like `Convert<Field>` and `Convert<i32>`).
14281428
let traits: HashSet<TraitId> =
1429-
trait_methods.into_iter().map(|(_, trait_id)| trait_id).collect();
1429+
trait_methods.iter().map(|(_, trait_id)| *trait_id).collect();
14301430

14311431
let traits_in_scope: Vec<_> = traits
14321432
.iter()
@@ -1457,15 +1457,18 @@ impl<'context> Elaborator<'context> {
14571457
let trait_id = *traits.iter().next().unwrap();
14581458
let trait_ = self.interner.get_trait(trait_id);
14591459
let trait_name = self.fully_qualified_trait_path(trait_);
1460-
let generics = trait_.as_constraint(span).trait_bound.trait_generics;
1461-
let trait_method_id = trait_.find_method(method_name).unwrap();
14621460

14631461
self.push_err(PathResolutionError::TraitMethodNotInScope {
14641462
ident: Ident::new(method_name.into(), span),
14651463
trait_name,
14661464
});
14671465

1468-
return Some(HirMethodReference::TraitMethodId(trait_method_id, generics, false));
1466+
return Some(self.trait_hir_method_reference(
1467+
trait_id,
1468+
trait_methods,
1469+
method_name,
1470+
span,
1471+
));
14691472
} else {
14701473
let traits = vecmap(traits, |trait_id| {
14711474
let trait_ = self.interner.get_trait(trait_id);
@@ -1491,12 +1494,28 @@ impl<'context> Elaborator<'context> {
14911494
return None;
14921495
}
14931496

1494-
// Return a TraitMethodId with unbound generics. These will later be bound by the type-checker.
14951497
let trait_id = traits_in_scope[0].0;
1498+
Some(self.trait_hir_method_reference(trait_id, trait_methods, method_name, span))
1499+
}
1500+
1501+
fn trait_hir_method_reference(
1502+
&self,
1503+
trait_id: TraitId,
1504+
trait_methods: Vec<(FuncId, TraitId)>,
1505+
method_name: &str,
1506+
span: Span,
1507+
) -> HirMethodReference {
1508+
// If we find a single trait impl method, return it so we don't have to later determine the impl
1509+
if trait_methods.len() == 1 {
1510+
let (func_id, _) = trait_methods[0];
1511+
return HirMethodReference::FuncId(func_id);
1512+
}
1513+
1514+
// Return a TraitMethodId with unbound generics. These will later be bound by the type-checker.
14961515
let trait_ = self.interner.get_trait(trait_id);
14971516
let generics = trait_.as_constraint(span).trait_bound.trait_generics;
14981517
let trait_method_id = trait_.find_method(method_name).unwrap();
1499-
Some(HirMethodReference::TraitMethodId(trait_method_id, generics, false))
1518+
HirMethodReference::TraitMethodId(trait_method_id, generics, false)
15001519
}
15011520

15021521
fn lookup_method_in_trait_constraints(

0 commit comments

Comments
 (0)