Skip to content

Commit

Permalink
fix: return trait impl method as FuncId if there's only one (#6989)
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored Jan 8, 2025
1 parent 101f2d4 commit 8d7f1f9
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Field>` and `Convert<i32>`).
let traits: HashSet<TraitId> =
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()
Expand Down Expand Up @@ -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);
Expand All @@ -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(
Expand Down

0 comments on commit 8d7f1f9

Please sign in to comment.