Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 39 additions & 19 deletions compiler/noirc_frontend/src/elaborator/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1004,8 +1004,47 @@ impl Elaborator<'_> {
let (typ, bindings) =
self.instantiate(t, bindings, generics, function_generic_count, location);

if let ImplKind::TraitItem(mut method) = ident.impl_kind {
method.constraint.apply_bindings(&bindings);
if method.assumed {
let trait_generics = method.constraint.trait_bound.trait_generics.clone();
let object_type = method.constraint.typ;
let trait_impl = TraitImplKind::Assumed { object_type, trait_generics };
self.interner.select_impl_for_expression(expr_id, trait_impl);
} else {
self.push_trait_constraint(
method.constraint,
expr_id,
true, // this constraint should lead to choosing a trait impl method
);
}
}

// Push any trait constraints required by this definition to the context
// to be checked later when the type of this variable is further constrained.
//
// This must be done before the above trait constraint in case the above one further
// restricts types.
//
// For example, in this code:
//
// ```noir
// trait One {}
//
// trait Two<O: One> {
// fn new() -> Self;
// }
//
// fn foo<O: One, T: Two<O>>() {
// let _: T = Two::new();
// }
// ```
//
// when type-checking `Two::new` we'll have a return type `'2` which is constrained by `'2: Two<'1>`.
// Then the definition for `new` has a constraint on it, `O: One`, which translates to `'1: One`.
//
// If we try to find a trait implementation for `'1` before finding one for `'2` we'll never find it:
// once we find one for `'2`, `'1` will become bound and a trait implementation will be found.
if let Some(definition) = self.interner.try_definition(ident.id) {
if let DefinitionKind::Function(function) = definition.kind {
let function = self.interner.function_meta(&function);
Expand All @@ -1021,25 +1060,6 @@ impl Elaborator<'_> {
}
}

if let ImplKind::TraitItem(mut method) = ident.impl_kind {
method.constraint.apply_bindings(&bindings);
if method.assumed {
let trait_generics = method.constraint.trait_bound.trait_generics.clone();
let object_type = method.constraint.typ;
let trait_impl = TraitImplKind::Assumed { object_type, trait_generics };
self.interner.select_impl_for_expression(expr_id, trait_impl);
} else {
// Currently only one impl can be selected per expr_id, so this
// constraint needs to be pushed after any other constraints so
// that monomorphization can resolve this trait method to the correct impl.
self.push_trait_constraint(
method.constraint,
expr_id,
true, // this constraint should lead to choosing a trait impl method
);
}
}

if push_required_type_variables {
for (type_variable, _kind, typ) in bindings.values() {
self.push_required_type_variable(
Expand Down
22 changes: 22 additions & 0 deletions compiler/noirc_frontend/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2021,3 +2021,25 @@ fn associated_constant_mul_of_other_constants() {
"#;
assert_no_errors!(src);
}

#[named]
#[test]
fn trait_method_call_when_it_has_bounds_on_generic() {
let src = r#"
trait BigNum {}

trait BigCurve<B>
where
B: BigNum,
{
fn new() -> Self;
}

pub fn foo<B: BigNum, Curve: BigCurve<B>>() {
let _: Curve = BigCurve::new();
}

fn main() {}
"#;
assert_no_errors!(src);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

[package]
name = "noirc_frontend_tests_traits_trait_method_call_when_it_has_bounds_on_generic"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

trait BigNum {}

trait BigCurve<B>
where
B: BigNum,
{
fn new() -> Self;
}

pub fn foo<B: BigNum, Curve: BigCurve<B>>() {
let _: Curve = BigCurve::new();
}

fn main() {}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
13386000313017476697

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading