diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 60b5eece795..8346cfc546d 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -263,7 +263,13 @@ impl Kind { match self { Kind::IntegerOrField => Some(Type::default_int_or_field_type()), Kind::Integer => Some(Type::default_int_type()), - Kind::Numeric(typ) => Some(*typ.clone()), + Kind::Numeric(_typ) => { + // Even though we have a type here, that type cannot be used as + // the default type of a numeric generic. + // For example, if we have `let N: u32` and we don't know + // what `N` is, we can't assume it's `u32`. + None + } Kind::Any | Kind::Normal => None, } } diff --git a/compiler/noirc_frontend/src/monomorphization/errors.rs b/compiler/noirc_frontend/src/monomorphization/errors.rs index 03a93d8fc85..3329a7b342d 100644 --- a/compiler/noirc_frontend/src/monomorphization/errors.rs +++ b/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -23,6 +23,7 @@ pub enum MonomorphizationError { generic_name: String, item_kind: &'static str, item_name: String, + is_numeric: bool, }, InternalError { message: &'static str, @@ -96,10 +97,12 @@ impl From for CustomDiagnostic { generic_name, item_kind, item_name, + is_numeric, } => { let message = "Type annotation needed".into(); + let type_or_value = if *is_numeric { "value" } else { "type" }; let secondary = format!( - "Could not determine the type of the generic argument `{generic_name}` declared on the {item_kind} `{item_name}`" + "Could not determine the {type_or_value} of the generic argument `{generic_name}` declared on the {item_kind} `{item_name}`", ); return CustomDiagnostic::simple_error(message, secondary, *location); } diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index b87908c68b2..eb0f62e2f68 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -1386,11 +1386,13 @@ impl<'interner> Monomorphizer<'interner> { for generic in &meta.direct_generics { if generic.type_var.id() == id { let item_name = self.interner.definition_name(ident.id).to_string(); + let is_numeric = matches!(generic.type_var.kind(), Kind::Numeric(..)); return Err(MonomorphizationError::NoDefaultTypeInItem { location, generic_name: generic.name.to_string(), item_kind: "function", item_name, + is_numeric, }); } } @@ -1402,11 +1404,13 @@ impl<'interner> Monomorphizer<'interner> { let typ = typ.borrow(); let item_name = typ.name.to_string(); let item_kind = if typ.is_struct() { "struct" } else { "enum" }; + let is_numeric = matches!(generic.type_var.kind(), Kind::Numeric(..)); return Err(MonomorphizationError::NoDefaultTypeInItem { location, generic_name: generic.name.to_string(), item_kind, item_name, + is_numeric, }); } } @@ -1429,11 +1433,13 @@ impl<'interner> Monomorphizer<'interner> { let def = def.borrow(); for generic in &def.generics { if generic.type_var.id() == id { + let is_numeric = matches!(generic.type_var.kind(), Kind::Numeric(..)); return Err(MonomorphizationError::NoDefaultTypeInItem { location, generic_name: generic.name.to_string(), item_kind: "enum", item_name: def.name.to_string(), + is_numeric, }); } } @@ -1458,7 +1464,7 @@ impl<'interner> Monomorphizer<'interner> { | HirType::Error | HirType::Quoted(_) => Ok(()), HirType::Constant(_value, kind) => { - if kind.is_error() || kind.default_type().is_none() { + if kind.is_error() { Err(MonomorphizationError::UnknownConstant { location }) } else { Ok(()) @@ -2478,11 +2484,13 @@ fn check_struct_generic_type( let def = def.borrow(); if let Some(generic) = def.generics.get(index) { + let is_numeric = matches!(generic.type_var.kind(), Kind::Numeric(..)); return Err(MonomorphizationError::NoDefaultTypeInItem { location, generic_name: generic.name.to_string(), item_kind: "struct", item_name: def.name.to_string(), + is_numeric, }); } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 0ecb52d21fa..a22b4d3b5fe 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -4702,3 +4702,31 @@ fn only_one_private_error_when_name_in_types_and_values_namespace_collides() { "; check_errors!(src); } + +#[named] +#[test] +fn cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic() { + let src = r#" + struct Foo { + array: [Field; N], + } + + impl Foo { + fn new() -> Self { + Self { array: [0; N] } + } + } + + fn foo() -> Foo { + Foo::new() + } + + fn main() { + let _ = foo(); + ^^^ Type annotation needed + ~~~ Could not determine the value of the generic argument `N` declared on the function `foo` + } + "#; + let features = vec![UnstableFeature::Enums]; + check_monomorphization_error_using_features!(src, &features); +} diff --git a/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/Nargo.toml b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/Nargo.toml new file mode 100644 index 00000000000..9d863231e98 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/Nargo.toml @@ -0,0 +1,7 @@ + + [package] + name = "noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic" + type = "bin" + authors = [""] + + [dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src/main.nr b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src/main.nr new file mode 100644 index 00000000000..d73d2f2ec95 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src/main.nr @@ -0,0 +1,19 @@ + + struct Foo { + array: [Field; N], + } + + impl Foo { + fn new() -> Self { + Self { array: [0; N] } + } + } + + fn foo() -> Foo { + Foo::new() + } + + fn main() { + let _ = foo(); + } + \ No newline at end of file diff --git a/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src_hash.txt b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src_hash.txt new file mode 100644 index 00000000000..accede56629 --- /dev/null +++ b/test_programs/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/src_hash.txt @@ -0,0 +1 @@ +7627233576545093977 \ No newline at end of file diff --git a/test_programs/noir_test_success/ski_calculus/src/main.nr b/test_programs/noir_test_success/ski_calculus/src/main.nr index 44aa2754c28..87ae912e5e7 100644 --- a/test_programs/noir_test_success/ski_calculus/src/main.nr +++ b/test_programs/noir_test_success/ski_calculus/src/main.nr @@ -115,7 +115,7 @@ impl From for ShowState { } impl ShowState { - pub fn step(&mut self) -> Option { + pub fn step(&mut self) -> Option { if self.done { Option::none() } else { diff --git a/tooling/lsp/src/requests/inlay_hint.rs b/tooling/lsp/src/requests/inlay_hint.rs index 9ce4d7437e9..3ddaf3f21e5 100644 --- a/tooling/lsp/src/requests/inlay_hint.rs +++ b/tooling/lsp/src/requests/inlay_hint.rs @@ -525,10 +525,11 @@ fn push_type_parts(typ: &Type, parts: &mut Vec, files: &File } Type::TypeVariable(binding) => match &*binding.borrow() { TypeBinding::Unbound(_, kind) => match kind { - Kind::Any | Kind::Normal => push_type_variable_parts(binding, parts, files), + Kind::Any | Kind::Normal | Kind::Numeric(..) => { + push_type_variable_parts(binding, parts, files); + } Kind::Integer => push_type_parts(&Type::default_int_type(), parts, files), Kind::IntegerOrField => parts.push(string_part("Field")), - Kind::Numeric(typ) => push_type_parts(typ, parts, files), }, _ => { push_type_variable_parts(binding, parts, files); diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/cannot_deduce_numeric_generic/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/cannot_deduce_numeric_generic/execute__tests__stderr.snap index ff8b55894b5..e09190f1862 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_failure/cannot_deduce_numeric_generic/execute__tests__stderr.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/cannot_deduce_numeric_generic/execute__tests__stderr.snap @@ -2,11 +2,11 @@ source: tooling/nargo_cli/tests/execute.rs expression: stderr --- -error: Could not determine array length `_`, encountered error: `Expected a constant, but found `_`` - ┌─ src/main.nr:2:5 +error: Type annotation needed + ┌─ src/main.nr:6:13 │ -2 │ N - │ - +6 │ let _ = foo(); + │ --- Could not determine the value of the generic argument `N` declared on the function `foo` │ Aborting due to 1 previous error diff --git a/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/execute__tests__stderr.snap b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/execute__tests__stderr.snap new file mode 100644 index 00000000000..caa6da8bf56 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_failure/noirc_frontend_tests_cannot_determine_type_of_generic_argument_in_function_call_when_it_is_a_numeric_generic/execute__tests__stderr.snap @@ -0,0 +1,12 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: stderr +--- +error: Type annotation needed + ┌─ src/main.nr:17:17 + │ +17 │ let _ = foo(); + │ --- Could not determine the value of the generic argument `N` declared on the function `foo` + │ + +Aborting due to 1 previous error