diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 955863a74e0..5e8ea9f08d3 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -859,7 +859,7 @@ impl<'interner> TypeChecker<'interner> { method_name: &str, expr_id: &ExprId, ) -> Option { - match object_type { + match object_type.follow_bindings() { Type::Struct(typ, _args) => { let id = typ.borrow().id; match self.interner.lookup_method(object_type, id, method_name, false) { @@ -914,12 +914,20 @@ impl<'interner> TypeChecker<'interner> { .interner .lookup_primitive_trait_method_mut(element.as_ref(), method_name) .map(HirMethodReference::FuncId) - .or_else(|| self.lookup_method(element, method_name, expr_id)), + .or_else(|| self.lookup_method(&element, method_name, expr_id)), + // If we fail to resolve the object to a struct type, we have no way of type // checking its arguments as we can't even resolve the name of the function Type::Error => None, - other => match self.interner.lookup_primitive_method(other, method_name) { + // The type variable must be unbound at this point since follow_bindings was called + Type::TypeVariable(_, TypeVariableKind::Normal) => { + let span = self.interner.expr_span(expr_id); + self.errors.push(TypeCheckError::TypeAnnotationsNeeded { span }); + None + } + + other => match self.interner.lookup_primitive_method(&other, method_name) { Some(method_id) => Some(HirMethodReference::FuncId(method_id)), None => { self.errors.push(TypeCheckError::UnresolvedMethodCall { diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index b9b11d8c99e..c46555e028c 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -30,8 +30,6 @@ pub enum ParserErrorReason { ComptimeDeprecated, #[error("{0} are experimental and aren't fully supported yet")] ExperimentalFeature(&'static str), - #[error("Where clauses are allowed only on functions with generic parameters")] - WhereClauseOnNonGenericFunction, #[error( "Multiple primary attributes found. Only one function attribute is allowed per function" )] diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 6d934421783..57363bc117f 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -177,12 +177,11 @@ fn function_definition(allow_self: bool) -> impl NoirParser { let ((((attributes, modifiers), name), generics), parameters) = args; // Validate collected attributes, filtering them into function and secondary variants - let attrs = validate_attributes(attributes, span, emit); - validate_where_clause(&generics, &where_clause, span, emit); + let attributes = validate_attributes(attributes, span, emit); FunctionDefinition { span: body_span, name, - attributes: attrs, + attributes, is_unconstrained: modifiers.0, is_open: modifiers.2, is_internal: modifiers.3, @@ -412,7 +411,6 @@ fn trait_definition() -> impl NoirParser { .then(trait_body()) .then_ignore(just(Token::RightBrace)) .validate(|(((name, generics), where_clause), items), span, emit| { - validate_where_clause(&generics, &where_clause, span, emit); emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); TopLevelStatement::Trait(NoirTrait { name, generics, where_clause, span, items }) }) @@ -451,12 +449,9 @@ fn trait_function_declaration() -> impl NoirParser { .then(function_return_type().map(|(_, typ)| typ)) .then(where_clause()) .then(trait_function_body_or_semicolon) - .validate( - |(((((name, generics), parameters), return_type), where_clause), body), span, emit| { - validate_where_clause(&generics, &where_clause, span, emit); - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } - }, - ) + .map(|(((((name, generics), parameters), return_type), where_clause), body)| { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } + }) } fn validate_attributes( @@ -514,17 +509,6 @@ fn validate_struct_attributes( struct_attributes } -fn validate_where_clause( - generics: &Vec, - where_clause: &Vec, - span: Span, - emit: &mut dyn FnMut(ParserError), -) { - if !where_clause.is_empty() && generics.is_empty() { - emit(ParserError::with_reason(ParserErrorReason::WhereClauseOnNonGenericFunction, span)); - } -} - /// Function declaration parameters differ from other parameters in that parameter /// patterns are not allowed in declarations. All parameters must be identifiers. fn function_declaration_parameters() -> impl NoirParser> { @@ -2133,7 +2117,6 @@ mod test { "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where SomeTrait {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) SomeTrait {}", - "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: SomeTrait {}", // A leading plus is not allowed. "fn func_name(f: Field, y : T) where T: + SomeTrait {}", "fn func_name(f: Field, y : T) where T: TraitX + {}", @@ -2164,11 +2147,7 @@ mod test { parse_all_failing( trait_definition(), - vec![ - "trait MissingBody", - "trait WrongDelimiter { fn foo() -> u8, fn bar() -> u8 }", - "trait WhereClauseWithoutGenerics where A: SomeTrait { }", - ], + vec!["trait MissingBody", "trait WrongDelimiter { fn foo() -> u8, fn bar() -> u8 }"], ); }