diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index 096e5cbad86..398e5267695 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -930,6 +930,13 @@ impl FunctionReturnType { FunctionReturnType::Ty(typ) => Cow::Borrowed(typ), } } + + pub fn location(&self) -> Location { + match self { + FunctionReturnType::Default(location) => *location, + FunctionReturnType::Ty(typ) => typ.location, + } + } } impl Display for FunctionReturnType { diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index ea784812aaf..27726744fd2 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -1264,9 +1264,13 @@ impl<'context> Elaborator<'context> { self.check_parent_traits_are_implemented(&trait_impl); self.remove_trait_impl_assumed_trait_implementations(trait_impl.impl_id); - for (module, function, _) in &trait_impl.methods.functions { + for (module, function, noir_function) in &trait_impl.methods.functions { self.local_module = *module; - let errors = check_trait_impl_method_matches_declaration(self.interner, *function); + let errors = check_trait_impl_method_matches_declaration( + self.interner, + *function, + noir_function, + ); self.push_errors(errors.into_iter().map(|error| error.into())); } diff --git a/compiler/noirc_frontend/src/elaborator/statements.rs b/compiler/noirc_frontend/src/elaborator/statements.rs index 5402a682cdb..0c969e5059d 100644 --- a/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/compiler/noirc_frontend/src/elaborator/statements.rs @@ -91,6 +91,7 @@ impl Elaborator<'_> { let type_contains_unspecified = let_stmt.r#type.contains_unspecified(); let annotated_type = self.resolve_inferred_type(let_stmt.r#type); + let pattern_location = let_stmt.pattern.location(); let expr_location = let_stmt.expression.location; let (expression, expr_type) = self.elaborate_expression_with_target_type(let_stmt.expression, Some(&annotated_type)); @@ -98,8 +99,11 @@ impl Elaborator<'_> { // Require the top-level of a global's type to be fully-specified if type_contains_unspecified && global_id.is_some() { let expected_type = annotated_type.clone(); - let error = - ResolverError::UnspecifiedGlobalType { location: expr_location, expected_type }; + let error = ResolverError::UnspecifiedGlobalType { + pattern_location, + expr_location, + expected_type, + }; self.push_err(error); } @@ -202,11 +206,10 @@ impl Elaborator<'_> { ); // Check that start range and end range have the same types - let range_location = start_location.merge(end_location); self.unify(&start_range_type, &end_range_type, || TypeCheckError::TypeMismatch { expected_typ: start_range_type.to_string(), expr_typ: end_range_type.to_string(), - expr_location: range_location, + expr_location: end_location, }); let expected_type = self.polymorphic_integer(); @@ -214,7 +217,7 @@ impl Elaborator<'_> { self.unify(&start_range_type, &expected_type, || TypeCheckError::TypeCannotBeUsed { typ: start_range_type.clone(), place: "for loop", - location: range_location, + location: start_location, }); self.interner.push_definition_type(identifier.id, start_range_type); diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 0ddef96c46a..a931dde93de 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -273,6 +273,7 @@ impl Elaborator<'_> { pub(crate) fn check_trait_impl_method_matches_declaration( interner: &mut NodeInterner, function: FuncId, + noir_function: &NoirFunction, ) -> Vec { let meta = interner.function_meta(&function); let modifiers = interner.function_modifiers(&function); @@ -349,6 +350,8 @@ pub(crate) fn check_trait_impl_method_matches_declaration( definition_type, method_name, &meta.parameters, + &meta.return_type, + noir_function, meta.name.location, &trait_info.name.0.contents, &mut errors, @@ -358,11 +361,14 @@ pub(crate) fn check_trait_impl_method_matches_declaration( errors } +#[allow(clippy::too_many_arguments)] fn check_function_type_matches_expected_type( expected: &Type, actual: &Type, method_name: &str, actual_parameters: &Parameters, + actual_return_type: &FunctionReturnType, + noir_function: &NoirFunction, location: Location, trait_name: &str, errors: &mut Vec, @@ -381,11 +387,16 @@ fn check_function_type_matches_expected_type( if params_a.len() == params_b.len() { for (i, (a, b)) in params_a.iter().zip(params_b.iter()).enumerate() { if a.try_unify(b, &mut bindings).is_err() { + let parameter_location = noir_function.def.parameters.get(i); + let parameter_location = parameter_location.map(|param| param.typ.location); + let parameter_location = + parameter_location.unwrap_or_else(|| actual_parameters.0[i].0.location()); + errors.push(TypeCheckError::TraitMethodParameterTypeMismatch { method_name: method_name.to_string(), expected_typ: a.to_string(), actual_typ: b.to_string(), - parameter_location: actual_parameters.0[i].0.location(), + parameter_location, parameter_index: i + 1, }); } @@ -395,7 +406,7 @@ fn check_function_type_matches_expected_type( errors.push(TypeCheckError::TypeMismatch { expected_typ: ret_a.to_string(), expr_typ: ret_b.to_string(), - expr_location: location, + expr_location: actual_return_type.location(), }); } } else { diff --git a/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs index 82b26e8b7f5..b5f06cd0654 100644 --- a/compiler/noirc_frontend/src/elaborator/types.rs +++ b/compiler/noirc_frontend/src/elaborator/types.rs @@ -174,8 +174,8 @@ impl Elaborator<'_> { if !kind.unifies(&resolved_type.kind()) { let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch { - expected_kind: kind.to_string(), - expr_kind: resolved_type.kind().to_string(), + expected_kind: kind.clone(), + expr_kind: resolved_type.kind(), expr_location: location, }); self.push_err(expected_typ_err); @@ -523,8 +523,8 @@ impl Elaborator<'_> { (Type::Constant(lhs, lhs_kind), Type::Constant(rhs, rhs_kind)) => { if !lhs_kind.unifies(&rhs_kind) { self.push_err(TypeCheckError::TypeKindMismatch { - expected_kind: lhs_kind.to_string(), - expr_kind: rhs_kind.to_string(), + expected_kind: lhs_kind, + expr_kind: rhs_kind, expr_location: location, }); return Type::Error; @@ -557,8 +557,8 @@ impl Elaborator<'_> { fn check_kind(&mut self, typ: Type, expected_kind: &Kind, location: Location) -> Type { if !typ.kind().unifies(expected_kind) { self.push_err(TypeCheckError::TypeKindMismatch { - expected_kind: expected_kind.to_string(), - expr_kind: typ.kind().to_string(), + expected_kind: expected_kind.clone(), + expr_kind: typ.kind(), expr_location: location, }); return Type::Error; diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index 239c7a7ee12..7f17b1e3043 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -77,7 +77,7 @@ pub enum DefCollectorErrorKind { impl DefCollectorErrorKind { pub fn location(&self) -> Location { match self { - DefCollectorErrorKind::Duplicate { first_def: ident, .. } + DefCollectorErrorKind::Duplicate { second_def: ident, .. } | DefCollectorErrorKind::UnresolvedModuleDecl { mod_name: ident, .. } | DefCollectorErrorKind::CannotReexportItemWithLessVisibility { item_name: ident, @@ -160,10 +160,10 @@ impl<'a> From<&'a DefCollectorErrorKind> for Diagnostic { let second_location = second_def.0.location(); let mut diag = Diagnostic::simple_error( primary_message, - format!("First {} found here", &typ), - first_location, + format!("Second {} found here", &typ), + second_location, ); - diag.add_secondary(format!("Second {} found here", &typ), second_location); + diag.add_secondary(format!("First {} found here", &typ), first_location); diag } } diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index ec2ffda8f3b..1a8bb1ba2e2 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -109,7 +109,11 @@ pub enum ResolverError { #[error("Only `comptime` globals can be mutable")] MutableGlobal { location: Location }, #[error("Globals must have a specified type")] - UnspecifiedGlobalType { location: Location, expected_type: Type }, + UnspecifiedGlobalType { + pattern_location: Location, + expr_location: Location, + expected_type: Type, + }, #[error("Global failed to evaluate")] UnevaluatedGlobalType { location: Location }, #[error("Globals used in a type position must be non-negative")] @@ -168,7 +172,7 @@ pub enum ResolverError { AttributeFunctionIsNotAPath { function: String, location: Location }, #[error("Attribute function `{name}` is not in scope")] AttributeFunctionNotInScope { name: String, location: Location }, - #[error("The trait `{missing_trait}` is not implemented for `{type_missing_trait}")] + #[error("The trait `{missing_trait}` is not implemented for `{type_missing_trait}`")] TraitNotImplemented { impl_trait: String, missing_trait: String, @@ -197,7 +201,7 @@ pub enum ResolverError { impl ResolverError { pub fn location(&self) -> Location { match self { - ResolverError::DuplicateDefinition { first_location: location, .. } + ResolverError::DuplicateDefinition { second_location: location, .. } | ResolverError::UnconditionalRecursion { location, .. } | ResolverError::PathIsNotIdent { location } | ResolverError::Expected { location, .. } @@ -233,7 +237,7 @@ impl ResolverError { | ResolverError::WhileInConstrainedFn { location } | ResolverError::JumpOutsideLoop { location, .. } | ResolverError::MutableGlobal { location } - | ResolverError::UnspecifiedGlobalType { location, .. } + | ResolverError::UnspecifiedGlobalType { pattern_location: location, .. } | ResolverError::UnevaluatedGlobalType { location } | ResolverError::NegativeGlobalType { location, .. } | ResolverError::NonIntegralGlobalType { location, .. } @@ -292,10 +296,10 @@ impl<'a> From<&'a ResolverError> for Diagnostic { ResolverError::DuplicateDefinition { name, first_location, second_location} => { let mut diag = Diagnostic::simple_error( format!("duplicate definitions of {name} found"), - "first definition found here".to_string(), - *first_location, + "second definition found here".to_string(), + *second_location, ); - diag.add_secondary("second definition found here".to_string(), *second_location); + diag.add_secondary("first definition found here".to_string(), *first_location); diag } ResolverError::UnusedVariable { ident } => { @@ -573,12 +577,14 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *location, ) }, - ResolverError::UnspecifiedGlobalType { location, expected_type } => { - Diagnostic::simple_error( + ResolverError::UnspecifiedGlobalType { pattern_location, expr_location, expected_type } => { + let mut diagnostic = Diagnostic::simple_error( "Globals must have a specified type".to_string(), - format!("Inferred type is `{expected_type}`"), - *location, - ) + String::new(), + *pattern_location, + ); + diagnostic.add_secondary(format!("Inferred type is `{expected_type}`"), *expr_location); + diagnostic }, ResolverError::UnevaluatedGlobalType { location } => { Diagnostic::simple_error( @@ -763,9 +769,9 @@ impl<'a> From<&'a ResolverError> for Diagnostic { ResolverError::TraitNotImplemented { impl_trait, missing_trait: the_trait, type_missing_trait: typ, location, missing_trait_location} => { let mut diagnostic = Diagnostic::simple_error( format!("The trait bound `{typ}: {the_trait}` is not satisfied"), - format!("The trait `{the_trait}` is not implemented for `{typ}") + format!("The trait `{the_trait}` is not implemented for `{typ}`") , *location); - diagnostic.add_secondary(format!("required by this bound in `{impl_trait}"), *missing_trait_location); + diagnostic.add_secondary(format!("required by this bound in `{impl_trait}`"), *missing_trait_location); diagnostic }, ResolverError::LoopNotYetSupported { location } => { diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index cba5c1f791d..2af687eda10 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -63,7 +63,7 @@ pub enum TypeCheckError { #[error("Expected type {expected} is not the same as {actual}")] TypeMismatchWithSource { expected: Type, actual: Type, location: Location, source: Source }, #[error("Expected type {expected_kind:?} is not the same as {expr_kind:?}")] - TypeKindMismatch { expected_kind: String, expr_kind: String, expr_location: Location }, + TypeKindMismatch { expected_kind: Kind, expr_kind: Kind, expr_location: Location }, #[error("Evaluating {to} resulted in {to_value}, but {from_value} was expected")] TypeCanonicalizationMismatch { to: Type, @@ -369,11 +369,37 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { ) } TypeCheckError::TypeKindMismatch { expected_kind, expr_kind, expr_location } => { - Diagnostic::simple_error( - format!("Expected kind {expected_kind}, found kind {expr_kind}"), - String::new(), - *expr_location, - ) + // Try to improve the error message for some kind combinations + match (expected_kind, expr_kind) { + (Kind::Normal, Kind::Numeric(_)) => { + Diagnostic::simple_error( + "Expected type, found numeric generic".into(), + "not a type".into(), + *expr_location, + ) + } + (Kind::Numeric(typ), Kind::Normal) => { + Diagnostic::simple_error( + "Type provided when a numeric generic was expected".into(), + format!("the numeric generic is not of type `{typ}`"), + *expr_location, + ) + } + (Kind::Numeric(expected_type), Kind::Numeric(found_type)) => { + Diagnostic::simple_error( + format!("The numeric generic is not of type `{expected_type}`"), + format!("expected `{expected_type}`, found `{found_type}`"), + *expr_location, + ) + } + _ => { + Diagnostic::simple_error( + format!("Expected kind {expected_kind}, found kind {expr_kind}"), + String::new(), + *expr_location, + ) + } + } } TypeCheckError::TypeCanonicalizationMismatch { to, from, to_value, from_value, location } => { Diagnostic::simple_error( diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 4fd5b46657e..30f533fda22 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -858,8 +858,8 @@ impl TypeVariable { ) -> Result<(), TypeCheckError> { if !binding.kind().unifies(kind) { return Err(TypeCheckError::TypeKindMismatch { - expected_kind: format!("{}", kind), - expr_kind: format!("{}", binding.kind()), + expected_kind: kind.clone(), + expr_kind: binding.kind(), expr_location: location, }); } @@ -2144,8 +2144,8 @@ impl Type { kind.ensure_value_fits(x, location) } else { Err(TypeCheckError::TypeKindMismatch { - expected_kind: format!("{}", constant_kind), - expr_kind: format!("{}", kind), + expected_kind: constant_kind, + expr_kind: kind.clone(), expr_location: location, }) } @@ -2166,8 +2166,8 @@ impl Type { op.function(lhs_value, rhs_value, &infix_kind, location) } else { Err(TypeCheckError::TypeKindMismatch { - expected_kind: format!("{}", kind), - expr_kind: format!("{}", infix_kind), + expected_kind: kind.clone(), + expr_kind: infix_kind, expr_location: location, }) } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 2d208e329f8..e599b99b3fd 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -765,7 +765,7 @@ impl NodeInterner { id: type_id, name: unresolved_trait.trait_def.name.clone(), crate_id: unresolved_trait.crate_id, - location: unresolved_trait.trait_def.location, + location: unresolved_trait.trait_def.name.location(), generics, visibility: ItemVisibility::Private, self_type_typevar: TypeVariable::unbound(self.next_type_variable_id(), Kind::Normal), diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 0f152e64e9f..f10b790e63f 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -109,10 +109,24 @@ impl Parser<'_> { let visibility = self.parse_visibility(); (FunctionReturnType::Ty(self.parse_type_or_error()), visibility) } else { - ( - FunctionReturnType::Default(self.location_at_previous_token_end()), - Visibility::Private, - ) + // This will return the span between `)` and `{` + // + // fn foo() { } + // ^^^ + let mut location = self.previous_token_location.merge(self.current_token_location); + + // Here we change it to this (if there's space) + // + // fn foo() { } + // ^ + if location.span.end() - location.span.start() >= 3 { + location = Location::new( + Span::from(location.span.start() + 1..location.span.end() - 1), + location.file, + ); + } + + (FunctionReturnType::Default(location), Visibility::Private) }; let where_clause = self.parse_where_clause(); diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 7bbe1f60873..a72bb8f994b 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -362,12 +362,12 @@ fn check_trait_implementation_duplicate_method() { impl Default for Foo { // Duplicate trait methods should not compile fn default(x: Field, y: Field) -> Field { - ^^^^^^^ Duplicate definitions of trait associated function with name default found ~~~~~~~ First trait associated function found here y + 2 * x } // Duplicate trait methods should not compile fn default(x: Field, y: Field) -> Field { + ^^^^^^^ Duplicate definitions of trait associated function with name default found ~~~~~~~ Second trait associated function found here x + 2 * y } @@ -381,7 +381,6 @@ fn check_trait_implementation_duplicate_method() { #[test] fn check_trait_wrong_method_return_type() { - // TODO: improve the error location let src = " trait Default { fn default() -> Self; @@ -392,7 +391,7 @@ fn check_trait_wrong_method_return_type() { impl Default for Foo { fn default() -> Field { - ^^^^^^^ Expected type Foo, found type Field + ^^^^^ Expected type Foo, found type Field 0 } } @@ -406,7 +405,6 @@ fn check_trait_wrong_method_return_type() { #[test] fn check_trait_wrong_method_return_type2() { - // TODO: improve the error location let src = " trait Default { fn default(x: Field, y: Field) -> Self; @@ -419,7 +417,7 @@ fn check_trait_wrong_method_return_type2() { impl Default for Foo { fn default(x: Field, _y: Field) -> Field { - ^^^^^^^ Expected type Foo, found type Field + ^^^^^ Expected type Foo, found type Field x } } @@ -430,6 +428,31 @@ fn check_trait_wrong_method_return_type2() { check_errors(src); } +#[test] +fn check_trait_wrong_method_return_type3() { + let src = " + trait Default { + fn default(x: Field, y: Field) -> Self; + } + + struct Foo { + bar: Field, + array: [Field; 2], + } + + impl Default for Foo { + fn default(_x: Field, _y: Field) { + ^ Expected type Foo, found type () + } + } + + fn main() { + let _ = Foo { bar: 1, array: [2, 3] }; // silence Foo never constructed warning + } + "; + check_errors(src); +} + #[test] fn check_trait_missing_implementation() { let src = " @@ -506,7 +529,6 @@ fn check_trait_wrong_method_name() { #[test] fn check_trait_wrong_parameter() { - // TODO: improve the error location let src = " trait Default { fn default(x: Field) -> Self; @@ -518,7 +540,7 @@ fn check_trait_wrong_parameter() { impl Default for Foo { fn default(x: u32) -> Self { - ^ Parameter #1 of method `default` must be of type Field, not u32 + ^^^ Parameter #1 of method `default` must be of type Field, not u32 Foo {bar: x} } } @@ -543,7 +565,7 @@ fn check_trait_wrong_parameter2() { impl Default for Foo { fn default(x: Field, y: Foo) -> Self { - ^ Parameter #2 of method `default` must be of type Field, not Foo + ^^^ Parameter #2 of method `default` must be of type Field, not Foo Self { bar: x, array: [x, y.bar] } } } @@ -644,7 +666,6 @@ fn check_impl_struct_not_trait() { fn check_trait_duplicate_declaration() { let src = " trait Default { - ^^^^^^^ Duplicate definitions of trait definition with name Default found ~~~~~~~ First trait definition found here fn default(x: Field, y: Field) -> Self; } @@ -661,6 +682,7 @@ fn check_trait_duplicate_declaration() { } trait Default { + ^^^^^^^ Duplicate definitions of trait definition with name Default found ~~~~~~~ Second trait definition found here fn default(x: Field) -> Self; } @@ -1499,15 +1521,15 @@ fn numeric_generic_binary_operation_type_mismatch() { #[test] fn bool_generic_as_loop_bound() { - // TODO: improve the error location of the last error (should be just on N) let src = r#" pub fn read() { ^ N has a type of bool. The only supported numeric generic types are `u1`, `u8`, `u16`, and `u32`. ~ Unsupported numeric generic type let mut fields = [0; N]; - ^ Expected kind numeric u32, found kind numeric bool + ^ The numeric generic is not of type `u32` + ~ expected `u32`, found `bool` for i in 0..N { - ^^^^ Expected type Field, found type bool + ^ Expected type Field, found type bool fields[i] = i + 1; } assert(fields[0] == 1); @@ -1516,6 +1538,19 @@ fn bool_generic_as_loop_bound() { check_errors(src); } +#[test] +fn wrong_type_in_for_range() { + let src = r#" + pub fn foo() { + for _ in true..false { + ^^^^ The type bool cannot be used in a for loop + + } + } + "#; + check_errors(src); +} + #[test] fn numeric_generic_in_function_signature() { let src = r#" @@ -1526,13 +1561,12 @@ fn numeric_generic_in_function_signature() { #[test] fn numeric_generic_as_struct_field_type_fails() { - // TODO: improve error message, in Rust it says "expected type, found const parameter `N`" - // which might be more understandable let src = r#" pub struct Foo { a: Field, b: N, - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type } "#; check_errors(src); @@ -1545,7 +1579,8 @@ fn normal_generic_as_array_length() { pub struct Foo { a: Field, b: [Field; N], - ^^^^^^^^^^ Expected kind numeric u32, found kind normal + ^^^^^^^^^^ Type provided when a numeric generic was expected + ~~~~~~~~~~ the numeric generic is not of type `u32` } "#; check_errors(src); @@ -1553,13 +1588,17 @@ fn normal_generic_as_array_length() { #[test] fn numeric_generic_as_param_type() { - // TODO: improve the error message, see what Rust does let src = r#" pub fn foo(x: I) -> I { - ^ Expected kind normal, found kind numeric u32 - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type + ^ Expected type, found numeric generic + ~ not a type + + let _q: I = 5; - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type x } "#; @@ -1568,23 +1607,23 @@ fn numeric_generic_as_param_type() { #[test] fn numeric_generic_as_unused_param_type() { - // TODO: improve the error message let src = r#" pub fn foo(_x: I) { } - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type "#; check_errors(src); } #[test] fn numeric_generic_as_unused_trait_fn_param_type() { - // TODO: improve the error message let src = r#" trait Foo { ^^^ unused trait Foo ~~~ unused trait fn foo(_x: I) { } - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type } "#; check_errors(src); @@ -1592,7 +1631,6 @@ fn numeric_generic_as_unused_trait_fn_param_type() { #[test] fn numeric_generic_as_return_type() { - // TODO: improve the error message let src = r#" // std::mem::zeroed() without stdlib trait Zeroed { @@ -1600,7 +1638,8 @@ fn numeric_generic_as_return_type() { } fn foo(x: T) -> I where T: Zeroed { - ^ Expected kind normal, found kind numeric Field + ^ Expected type, found numeric generic + ~ not a type ^^^ unused function foo ~~~ unused function x.zeroed() @@ -1613,7 +1652,6 @@ fn numeric_generic_as_return_type() { #[test] fn numeric_generic_used_in_nested_type_fails() { - // TODO: improve the error message let src = r#" pub struct Foo { a: Field, @@ -1621,7 +1659,8 @@ fn numeric_generic_used_in_nested_type_fails() { } pub struct Bar { inner: N - ^ Expected kind normal, found kind numeric u32 + ^ Expected type, found numeric generic + ~ not a type } "#; check_errors(src); @@ -1629,12 +1668,12 @@ fn numeric_generic_used_in_nested_type_fails() { #[test] fn normal_generic_used_in_nested_array_length_fail() { - // TODO: improve the error message let src = r#" pub struct Foo { a: Field, b: Bar, - ^ Expected kind numeric u32, found kind normal + ^ Type provided when a numeric generic was expected + ~ the numeric generic is not of type `u32` } pub struct Bar { inner: [Field; N] @@ -1755,7 +1794,7 @@ fn numeric_generic_used_in_turbofish() { // allow u16 to be used as an array size #[test] fn numeric_generic_u16_array_size() { - // TODO: improve the error location (and maybe the message) + // TODO: improve the error location let src = r#" fn len(_arr: [Field; N]) -> u32 { N @@ -1763,8 +1802,10 @@ fn numeric_generic_u16_array_size() { pub fn foo() -> u32 { let fields: [Field; N] = [0; N]; - ^^^^^^^^^^ Expected kind numeric u32, found kind numeric u16 - ^ Expected kind numeric u32, found kind numeric u16 + ^ The numeric generic is not of type `u32` + ~ expected `u32`, found `u16` + ^^^^^^^^^^ The numeric generic is not of type `u32` + ~~~~~~~~~~ expected `u32`, found `u16` len(fields) } "#; @@ -1864,7 +1905,8 @@ fn normal_generic_used_when_numeric_expected_in_where_clause() { } pub fn read() -> T where T: Deserialize { - ^ Expected kind numeric u32, found kind normal + ^ Type provided when a numeric generic was expected + ~ the numeric generic is not of type `u32` T::deserialize([0, 1]) } "#; @@ -1877,10 +1919,13 @@ fn normal_generic_used_when_numeric_expected_in_where_clause() { } pub fn read() -> T where T: Deserialize { - ^ Expected kind numeric u32, found kind normal + ^ Type provided when a numeric generic was expected + ~ the numeric generic is not of type `u32` let mut fields: [Field; N] = [0; N]; - ^ Expected kind numeric u32, found kind normal - ^^^^^^^^^^ Expected kind numeric u32, found kind normal + ^ Type provided when a numeric generic was expected + ~ the numeric generic is not of type `u32` + ^^^^^^^^^^ Type provided when a numeric generic was expected + ~~~~~~~~~~ the numeric generic is not of type `u32` for i in 0..N { ^ cannot find `N` in this scope ~ not found in this scope @@ -1903,7 +1948,8 @@ fn numeric_generics_type_kind_mismatch() { fn bar() -> u16 { foo::() - ^ Expected kind numeric u32, found kind numeric u16 + ^ The numeric generic is not of type `u32` + ~ expected `u32`, found `u16` } global M: u16 = 3; @@ -2421,13 +2467,12 @@ fn bit_not_on_untyped_integer() { #[test] fn duplicate_struct_field() { - // TODO: the primary error location should be on the second field let src = r#" pub struct Foo { x: i32, - ^ Duplicate definitions of struct field with name x found ~ First struct field found here x: i32, + ^ Duplicate definitions of struct field with name x found ~ Second struct field found here } @@ -2546,7 +2591,7 @@ fn uses_self_type_in_trait_where_clause() { } pub trait Foo where Self: Trait { - ~~~~~ required by this bound in `Foo + ~~~~~ required by this bound in `Foo` fn foo(self) -> bool { self.trait_func() ^^^^^^^^^^^^^^^^^ No method named 'trait_func' found for type 'Bar' @@ -2557,7 +2602,7 @@ fn uses_self_type_in_trait_where_clause() { impl Foo for Bar { ^^^ The trait bound `_: Trait` is not satisfied - ~~~ The trait `Trait` is not implemented for `_ + ~~~ The trait `Trait` is not implemented for `_` } @@ -2735,25 +2780,27 @@ fn as_trait_path_syntax_no_impl() { #[test] fn do_not_infer_globals_to_u32_from_type_use() { - // TODO: improve the error location (maybe it should be on the global name) let src = r#" global ARRAY_LEN = 3; - ^ Globals must have a specified type + ^^^^^^^^^ Globals must have a specified type ~ Inferred type is `Field` global STR_LEN: _ = 2; - ^ Globals must have a specified type + ^^^^^^^ Globals must have a specified type ~ Inferred type is `Field` global FMT_STR_LEN = 2; - ^ Globals must have a specified type + ^^^^^^^^^^^ Globals must have a specified type ~ Inferred type is `Field` fn main() { let _a: [u32; ARRAY_LEN] = [1, 2, 3]; - ^^^^^^^^^^^^^^^^ Expected kind numeric u32, found kind numeric Field + ^^^^^^^^^^^^^^^^ The numeric generic is not of type `u32` + ~~~~~~~~~~~~~~~~ expected `u32`, found `Field` let _b: str = "hi"; - ^^^^^^^^^^^^ Expected kind numeric u32, found kind numeric Field + ^^^^^^^^^^^^ The numeric generic is not of type `u32` + ~~~~~~~~~~~~ expected `u32`, found `Field` let _c: fmtstr = f"hi"; - ^^^^^^^^^^^^^^^^^^^^^^ Expected kind numeric u32, found kind numeric Field + ^^^^^^^^^^^^^^^^^^^^^^ The numeric generic is not of type `u32` + ~~~~~~~~~~~~~~~~~~~~~~ expected `u32`, found `Field` } "#; check_errors(src); @@ -2763,25 +2810,25 @@ fn do_not_infer_globals_to_u32_from_type_use() { fn do_not_infer_partial_global_types() { let src = r#" pub global ARRAY: [Field; _] = [0; 3]; - ^^^^^^ Globals must have a specified type + ^^^^^ Globals must have a specified type ~~~~~~ Inferred type is `[Field; 3]` pub global NESTED_ARRAY: [[Field; _]; 3] = [[]; 3]; - ^^^^^^^ Globals must have a specified type + ^^^^^^^^^^^^ Globals must have a specified type ~~~~~~~ Inferred type is `[[Field; 0]; 3]` pub global STR: str<_> = "hi"; - ^^^^ Globals must have a specified type + ^^^ Globals must have a specified type ~~~~ Inferred type is `str<2>` pub global NESTED_STR: [str<_>] = &["hi"]; - ^^^^^^^ Globals must have a specified type + ^^^^^^^^^^ Globals must have a specified type ~~~~~~~ Inferred type is `[str<2>]` pub global FORMATTED_VALUE: str<5> = "there"; pub global FMT_STR: fmtstr<_, _> = f"hi {FORMATTED_VALUE}"; - ^^^^^^^^^^^^^^^^^^^^^^^ Globals must have a specified type + ^^^^^^^ Globals must have a specified type ~~~~~~~~~~~~~~~~~~~~~~~ Inferred type is `fmtstr<20, (str<5>)>` pub global TUPLE_WITH_MULTIPLE: ([str<_>], [[Field; _]; 3]) = + ^^^^^^^^^^^^^^^^^^^ Globals must have a specified type (&["hi"], [[]; 3]); - ^^^^^^^^^^^^^^^^^^ Globals must have a specified type ~~~~~~~~~~~~~~~~~~ Inferred type is `([str<2>], [[Field; 0]; 3])` fn main() { } @@ -2839,7 +2886,8 @@ fn non_u32_as_array_length() { fn main() { let _a: [u32; ARRAY_LEN] = [1, 2, 3]; - ^^^^^^^^^^^^^^^^ Expected kind numeric u32, found kind numeric u8 + ^^^^^^^^^^^^^^^^ The numeric generic is not of type `u32` + ~~~~~~~~~~~~~~~~ expected `u32`, found `u8` } "#; check_errors(src); @@ -3850,15 +3898,14 @@ fn errors_if_while_body_type_is_not_unit() { #[test] fn check_impl_duplicate_method_without_self() { - // TODO: the primary error location should be n the second `foo` let src = " pub struct Foo {} impl Foo { fn foo() {} - ^^^ duplicate definitions of foo found ~~~ first definition found here fn foo() {} + ^^^ duplicate definitions of foo found ~~~ second definition found here } diff --git a/compiler/noirc_frontend/src/tests/enums.rs b/compiler/noirc_frontend/src/tests/enums.rs index 78f0442bc9f..6163b34003e 100644 --- a/compiler/noirc_frontend/src/tests/enums.rs +++ b/compiler/noirc_frontend/src/tests/enums.rs @@ -8,13 +8,12 @@ use super::{check_errors, check_errors_using_features}; #[test] fn error_with_duplicate_enum_variant() { - // TODO: the primary error should be on the second `Bar` let src = r#" pub enum Foo { Bar(i32), - ^^^ Duplicate definitions of enum variant with name Bar found ~~~ First enum variant found here Bar(u8), + ^^^ Duplicate definitions of enum variant with name Bar found ~~~ Second enum variant found here } diff --git a/compiler/noirc_frontend/src/tests/traits.rs b/compiler/noirc_frontend/src/tests/traits.rs index f9adf764fb3..d2f9d9a9672 100644 --- a/compiler/noirc_frontend/src/tests/traits.rs +++ b/compiler/noirc_frontend/src/tests/traits.rs @@ -102,11 +102,10 @@ fn trait_inheritance_with_generics_4() { #[test] fn trait_inheritance_dependency_cycle() { - // TODO: maybe the error location should be just on Foo let src = r#" trait Foo: Bar {} - ^^^^^^^^^^^^^^^^^ Dependency cycle found - ~~~~~~~~~~~~~~~~~ 'Foo' recursively depends on itself: Foo -> Bar -> Foo + ^^^ Dependency cycle found + ~~~ 'Foo' recursively depends on itself: Foo -> Bar -> Foo trait Bar: Foo {} fn main() {} "#; @@ -115,18 +114,17 @@ fn trait_inheritance_dependency_cycle() { #[test] fn trait_inheritance_missing_parent_implementation() { - // TODO: the secondary errors are missing a closing backtick let src = r#" pub trait Foo {} pub trait Bar: Foo {} - ~~~ required by this bound in `Bar + ~~~ required by this bound in `Bar` pub struct Struct {} impl Bar for Struct {} ^^^^^^ The trait bound `Struct: Foo` is not satisfied - ~~~~~~ The trait `Foo` is not implemented for `Struct + ~~~~~~ The trait `Foo` is not implemented for `Struct` fn main() { let _ = Struct {}; // silence Struct never constructed warning @@ -214,7 +212,7 @@ fn errors_if_impl_trait_constraint_is_not_satisfied() { pub trait Foo where T: Greeter, - ~~~~~~~ required by this bound in `Foo + ~~~~~~~ required by this bound in `Foo` { fn greet(object: U) where @@ -230,7 +228,7 @@ fn errors_if_impl_trait_constraint_is_not_satisfied() { impl Foo for Bar {} ^^^ The trait bound `SomeGreeter: Greeter` is not satisfied - ~~~ The trait `Greeter` is not implemented for `SomeGreeter + ~~~ The trait `Greeter` is not implemented for `SomeGreeter` fn main() {} "#; diff --git a/tooling/lsp/src/requests/document_symbol.rs b/tooling/lsp/src/requests/document_symbol.rs index 1d36aabdbe7..4827d8827af 100644 --- a/tooling/lsp/src/requests/document_symbol.rs +++ b/tooling/lsp/src/requests/document_symbol.rs @@ -660,7 +660,7 @@ mod document_symbol_tests { deprecated: None, range: Range { start: Position { line: 15, character: 7 }, - end: Position { line: 15, character: 24 }, + end: Position { line: 15, character: 25 }, }, selection_range: Range { start: Position { line: 15, character: 7 },