Skip to content

Commit

Permalink
fix: let a trait impl that relies on another trait work
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Jul 31, 2024
1 parent f656681 commit e6b57d3
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
11 changes: 7 additions & 4 deletions compiler/noirc_frontend/src/node_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,8 @@ impl NodeInterner {

let mut matching_impls = Vec::new();

let mut where_clause_errors = Vec::new();

for (existing_object_type2, impl_kind) in impls {
// Bug: We're instantiating only the object type's generics here, not all of the trait's generics like we need to
let (existing_object_type, instantiation_bindings) =
Expand Down Expand Up @@ -1471,14 +1473,14 @@ impl NodeInterner {
let trait_impl = self.get_trait_implementation(*impl_id);
let trait_impl = trait_impl.borrow();

if let Err(mut errors) = self.validate_where_clause(
if let Err(errors) = self.validate_where_clause(
&trait_impl.where_clause,
&mut fresh_bindings,
&instantiation_bindings,
recursion_limit,
) {
errors.push(make_constraint());
return Err(errors);
where_clause_errors.extend(errors);
continue;
}
}

Expand All @@ -1491,7 +1493,8 @@ impl NodeInterner {
*type_bindings = fresh_bindings;
Ok(impl_)
} else if matching_impls.is_empty() {
Err(vec![make_constraint()])
where_clause_errors.push(make_constraint());
Err(where_clause_errors)
} else {
// multiple matching impls, type annotations needed
Err(vec![])
Expand Down
72 changes: 72 additions & 0 deletions compiler/noirc_frontend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2729,3 +2729,75 @@ fn incorrect_generic_count_on_type_alias() {
assert_eq!(actual, 1);
assert_eq!(expected, 0);
}

#[test]
fn trait_impl_for_a_type_that_implements_another_trait() {
let src = r#"
trait One {
fn one(self) -> i32;
}
impl One for i32 {
fn one(self) -> i32 {
self
}
}
trait Two {
fn two(self) -> i32;
}
impl<T> Two for T where T: One {
fn two(self) -> i32 {
self.one() + 1
}
}
fn use_it<T>(t: T) -> i32 where T: Two {
Two::two(t)
}
fn main() {}
"#;
assert_no_errors(src);
}

#[test]
fn trait_impl_for_a_type_that_implements_another_trait_with_another_impl_used() {
let src = r#"
trait One {
fn one(self) -> i32;
}
impl One for i32 {
fn one(self) -> i32 {
let _ = self;
1
}
}
trait Two {
fn two(self) -> i32;
}
impl<T> Two for T where T: One {
fn two(self) -> i32 {
self.one() + 1
}
}
impl Two for u32 {
fn two(self) -> i32 {
let _ = self;
0
}
}
fn use_it(t: u32) -> i32 {
Two::two(t)
}
fn main() {}
"#;
assert_no_errors(src);
}

0 comments on commit e6b57d3

Please sign in to comment.