Skip to content

Commit

Permalink
Merge branch 'master' into michaeljklein/test-binary-ops
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljklein authored Jul 23, 2024
2 parents fc72df0 + cec6390 commit a30e55f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 37 deletions.
80 changes: 43 additions & 37 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,37 +1211,7 @@ impl<'context> Elaborator<'context> {
None
}
Type::NamedGeneric(_, _, _) => {
let func_id = match self.current_item {
Some(DependencyId::Function(id)) => id,
_ => panic!("unexpected method outside a function"),
};
let func_meta = self.interner.function_meta(&func_id);

for constraint in &func_meta.trait_constraints {
if *object_type == constraint.typ {
if let Some(the_trait) = self.interner.try_get_trait(constraint.trait_id) {
for (method_index, method) in the_trait.methods.iter().enumerate() {
if method.name.0.contents == method_name {
let trait_method = TraitMethodId {
trait_id: constraint.trait_id,
method_index,
};
return Some(HirMethodReference::TraitMethodId(
trait_method,
constraint.trait_generics.clone(),
));
}
}
}
}
}

self.push_err(TypeCheckError::UnresolvedMethodCall {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
None
self.lookup_method_in_trait_constraints(object_type, method_name, span)
}
// Mutable references to another type should resolve to methods of their element type.
// This may be a struct or a primitive type.
Expand All @@ -1264,17 +1234,53 @@ impl<'context> Elaborator<'context> {
other => match self.interner.lookup_primitive_method(&other, method_name) {
Some(method_id) => Some(HirMethodReference::FuncId(method_id)),
None => {
self.push_err(TypeCheckError::UnresolvedMethodCall {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});
None
// It could be that this type is a composite type that is bound to a trait,
// for example `x: (T, U) ... where (T, U): SomeTrait`
// (so this case is a generalization of the NamedGeneric case)
self.lookup_method_in_trait_constraints(object_type, method_name, span)
}
},
}
}

fn lookup_method_in_trait_constraints(
&mut self,
object_type: &Type,
method_name: &str,
span: Span,
) -> Option<HirMethodReference> {
let func_id = match self.current_item {
Some(DependencyId::Function(id)) => id,
_ => panic!("unexpected method outside a function"),
};
let func_meta = self.interner.function_meta(&func_id);

for constraint in &func_meta.trait_constraints {
if *object_type == constraint.typ {
if let Some(the_trait) = self.interner.try_get_trait(constraint.trait_id) {
for (method_index, method) in the_trait.methods.iter().enumerate() {
if method.name.0.contents == method_name {
let trait_method =
TraitMethodId { trait_id: constraint.trait_id, method_index };
return Some(HirMethodReference::TraitMethodId(
trait_method,
constraint.trait_generics.clone(),
));
}
}
}
}
}

self.push_err(TypeCheckError::UnresolvedMethodCall {
method_name: method_name.to_string(),
object_type: object_type.clone(),
span,
});

None
}

pub(super) fn type_check_call(
&mut self,
call: &HirCallExpression,
Expand Down
15 changes: 15 additions & 0 deletions compiler/noirc_frontend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2522,3 +2522,18 @@ fn duplicate_struct_field() {
assert_eq!(first_def.span().start(), 26);
assert_eq!(second_def.span().start(), 42);
}

#[test]
fn trait_constraint_on_tuple_type() {
let src = r#"
trait Foo<A> {
fn foo(self, x: A) -> bool;
}
fn bar<T, U, V>(x: (T, U), y: V) -> bool where (T, U): Foo<V> {
x.foo(y)
}
fn main() {}"#;
assert_no_errors(src);
}

0 comments on commit a30e55f

Please sign in to comment.