From 9b5b5f6ba8830f1c7d0eb46b0888f15f9fe6b5d7 Mon Sep 17 00:00:00 2001 From: jfecher Date: Fri, 10 Mar 2023 04:42:18 -0600 Subject: [PATCH] fix: Improve member access error (#940) * Improve member access error * Fix broken error * cargo fmt * Feedback --- crates/noirc_frontend/src/hir/type_check/errors.rs | 7 +++++++ crates/noirc_frontend/src/hir/type_check/expr.rs | 9 +++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/noirc_frontend/src/hir/type_check/errors.rs b/crates/noirc_frontend/src/hir/type_check/errors.rs index 33e98e3d6af..5e35d30d22c 100644 --- a/crates/noirc_frontend/src/hir/type_check/errors.rs +++ b/crates/noirc_frontend/src/hir/type_check/errors.rs @@ -32,6 +32,8 @@ pub enum TypeCheckError { second_type: String, second_index: usize, }, + #[error("Cannot infer type of expression, type annotations needed before this point")] + TypeAnnotationsNeeded { span: Span }, } impl TypeCheckError { @@ -96,6 +98,11 @@ impl From for Diagnostic { format!("return type is {typ}"), span, ), + TypeCheckError::TypeAnnotationsNeeded { span } => Diagnostic::simple_error( + "Expression type is ambiguous".to_string(), + "Type must be known at this point".to_string(), + span, + ), } } } diff --git a/crates/noirc_frontend/src/hir/type_check/expr.rs b/crates/noirc_frontend/src/hir/type_check/expr.rs index 4f5ddbca9d8..48ba39d980f 100644 --- a/crates/noirc_frontend/src/hir/type_check/expr.rs +++ b/crates/noirc_frontend/src/hir/type_check/expr.rs @@ -695,7 +695,7 @@ pub fn check_member_access( expr_id: ExprId, errors: &mut Vec, ) -> Type { - let lhs_type = type_check_expression(interner, &access.lhs, errors); + let lhs_type = type_check_expression(interner, &access.lhs, errors).follow_bindings(); if let Type::Struct(s, args) = &lhs_type { let s = s.borrow(); @@ -712,7 +712,12 @@ pub fn check_member_access( } } - if lhs_type != Type::Error { + // If we get here the type has no field named 'access.rhs'. + // Now we specialize the error message based on whether we know the object type in question yet. + if let Type::TypeVariable(..) = &lhs_type { + errors + .push(TypeCheckError::TypeAnnotationsNeeded { span: interner.expr_span(&access.lhs) }); + } else if lhs_type != Type::Error { errors.push(TypeCheckError::Unstructured { msg: format!("Type {lhs_type} has no member named {}", access.rhs), span: interner.expr_span(&access.lhs),