Skip to content

Commit

Permalink
chore: solve methods implemented for types that implement other traits (
Browse files Browse the repository at this point in the history
#4013)

Resolved: #3940

Functionality was already there, but a `?` operator was short circuiting
the resolution if the known type didn't have the implemented methods,
avoiding looking for the generic implementations.
  • Loading branch information
Thunkar authored Jan 15, 2024
1 parent 420a5c7 commit 0e91bb2
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
10 changes: 5 additions & 5 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,12 +1178,12 @@ impl NodeInterner {
method_name: &str,
force_type_check: bool,
) -> Option<FuncId> {
let methods = self.struct_methods.get(&(id, method_name.to_owned()))?;
let methods = self.struct_methods.get(&(id, method_name.to_owned()));

// If there is only one method, just return it immediately.
// It will still be typechecked later.
if !force_type_check {
if let Some(method) = methods.get_unambiguous() {
if let Some(method) = methods.and_then(|m| m.get_unambiguous()) {
return Some(method);
}
}
Expand All @@ -1195,10 +1195,10 @@ impl NodeInterner {
fn find_matching_method(
&self,
typ: &Type,
methods: &Methods,
methods: Option<&Methods>,
method_name: &str,
) -> Option<FuncId> {
if let Some(method) = methods.find_matching_method(typ, self) {
if let Some(method) = methods.and_then(|m| m.find_matching_method(typ, self)) {
Some(method)
} else {
// Failed to find a match for the type in question, switch to looking at impls
Expand All @@ -1213,7 +1213,7 @@ impl NodeInterner {
pub fn lookup_primitive_method(&self, typ: &Type, method_name: &str) -> Option<FuncId> {
let key = get_type_method_key(typ)?;
let methods = self.primitive_methods.get(&(key, method_name.to_owned()))?;
self.find_matching_method(typ, methods, method_name)
self.find_matching_method(typ, Some(methods), method_name)
}

pub fn lookup_primitive_trait_method_mut(
Expand Down
44 changes: 44 additions & 0 deletions compiler/noirc_frontend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,50 @@ mod test {
get_program(src).2
}

#[test]
fn check_trait_implemented_for_all_t() {
let src = "
trait Default {
fn default() -> Self;
}
trait Eq {
fn eq(self, other: Self) -> bool;
}
trait IsDefault {
fn is_default(self) -> bool;
}
impl<T> IsDefault for T where T: Default + Eq {
fn is_default(self) -> bool {
self.eq(T::default())
}
}
struct Foo {
a: u64,
}
impl Eq for Foo {
fn eq(self, other: Foo) -> bool { self.a == other.a }
}
impl Default for Foo {
fn default() -> Self {
Foo { a: Default::default() }
}
}
fn main(a: Foo) -> pub bool {
a.is_default()
}";

let errors = get_program_errors(src);
errors.iter().for_each(|err| println!("{:?}", err));
assert!(errors.is_empty());
}

#[test]
fn check_trait_implementation_duplicate_method() {
let src = "
Expand Down

0 comments on commit 0e91bb2

Please sign in to comment.