diff --git a/compiler/noirc_frontend/src/parser/parser/type_expression.rs b/compiler/noirc_frontend/src/parser/parser/type_expression.rs index 0e1bd80186a..6770d072815 100644 --- a/compiler/noirc_frontend/src/parser/parser/type_expression.rs +++ b/compiler/noirc_frontend/src/parser/parser/type_expression.rs @@ -143,6 +143,7 @@ impl Parser<'_> { /// AtomTypeExpression /// = ConstantTypeExpression /// | VariableTypeExpression + /// | AsTraitPathTypeExpression /// | ParenthesizedTypeExpression fn parse_atom_type_expression(&mut self) -> Option { if let Some(type_expr) = self.parse_constant_type_expression() { @@ -153,6 +154,10 @@ impl Parser<'_> { return Some(type_expr); } + if let Some(as_trait_path) = self.parse_as_trait_path() { + return Some(UnresolvedTypeExpression::AsTraitPath(Box::new(as_trait_path))); + } + if let Some(type_expr) = self.parse_parenthesized_type_expression() { return Some(type_expr); } @@ -474,6 +479,18 @@ mod tests { assert_eq!(expr.to_string(), "(0 - N)"); } + #[test] + fn parses_as_trait_path_type_expression() { + let src = "::AssociatedType"; + let typ = parse_type_expression_no_errors(src); + let UnresolvedTypeExpression::AsTraitPath(as_trait_path) = typ else { + panic!("Expected AsTraitPath"); + }; + assert_eq!(as_trait_path.typ.to_string(), "Type"); + assert_eq!(as_trait_path.trait_path.to_string(), "Trait"); + assert_eq!(as_trait_path.impl_item.to_string(), "AssociatedType"); + } + #[test] fn parse_type_or_type_expression_constant() { let src = "42"; diff --git a/test_programs/compile_success_empty/as_trait_path_type_expression/Nargo.toml b/test_programs/compile_success_empty/as_trait_path_type_expression/Nargo.toml new file mode 100644 index 00000000000..a37c42fb676 --- /dev/null +++ b/test_programs/compile_success_empty/as_trait_path_type_expression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "as_trait_path_type_expression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/as_trait_path_type_expression/src/main.nr b/test_programs/compile_success_empty/as_trait_path_type_expression/src/main.nr new file mode 100644 index 00000000000..f800992aa00 --- /dev/null +++ b/test_programs/compile_success_empty/as_trait_path_type_expression/src/main.nr @@ -0,0 +1,14 @@ +use std::mem::zeroed; + +trait Trait { + let N: u32; +} + +impl Trait for Field { + let N: u32 = 10; +} + +fn main() { + let something: [Field; ::N] = zeroed(); + assert_eq(something.len(), ::N); +} diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 2b2b6d13582..3a718f47b14 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -178,7 +178,7 @@ const TESTS_WITHOUT_STDOUT_CHECK: [&str; 0] = []; /// These tests are ignored because of existing bugs in `nargo expand`. /// As the bugs are fixed these tests should be removed from this list. /// (some are ignored on purpose for the same reason as `IGNORED_NARGO_EXPAND_EXECUTION_TESTS`) -const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_EMPTY_TESTS: [&str; 14] = [ +const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_EMPTY_TESTS: [&str; 8] = [ // bug "associated_type_bounds", // bug @@ -189,14 +189,6 @@ const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_EMPTY_TESTS: [&str; 14] = [ // because it references another project by a relative path "reexports", // bug - "serialize_1", - // bug - "serialize_2", - // bug - "serialize_3", - // bug - "serialize_4", - // bug "trait_function_calls", // bug "trait_method_mut_self", @@ -204,10 +196,6 @@ const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_EMPTY_TESTS: [&str; 14] = [ "trait_static_methods", // There's no "src/main.nr" here so it's trickier to make this work "workspace_reexport_bug", - // bug - "type_trait_method_call_multiple_candidates", - // bug - "alias_trait_method_call_multiple_candidates", ]; /// These tests are ignored because of existing bugs in `nargo expand`. @@ -223,8 +211,6 @@ const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_NO_BUG_TESTS: [&str; 10] = [ "noirc_frontend_tests_traits_accesses_associated_type_inside_trait_impl_using_self", "noirc_frontend_tests_traits_accesses_associated_type_inside_trait_using_self", "noirc_frontend_tests_u32_globals_as_sizes_in_types", - // "noirc_frontend_tests_traits_as_trait_path_called_multiple_times_for_different_t_1", - // "noirc_frontend_tests_traits_as_trait_path_called_multiple_times_for_different_t_2", ]; const IGNORED_NARGO_EXPAND_COMPILE_SUCCESS_WITH_BUG_TESTS: [&str; 1] = diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__expanded.snap new file mode 100644 index 00000000000..a289f2edd41 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__expanded.snap @@ -0,0 +1,18 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: expanded_code +--- +use std::mem::zeroed; + +trait Trait { + let N: u32; +} + +impl Trait for Field { + let N: u32 = 10; +} + +fn main() { + let something: [Field; 10] = zeroed(); + assert(something.len() == ::N); +} diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__force_brillig_false_inliner_0.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__force_brillig_false_inliner_0.snap new file mode 100644 index 00000000000..7de940827c8 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/as_trait_path_type_expression/execute__tests__force_brillig_false_inliner_0.snap @@ -0,0 +1,26 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: artifact +--- +{ + "noir_version": "[noir_version]", + "hash": "[hash]", + "abi": { + "parameters": [], + "return_type": null, + "error_types": {} + }, + "bytecode": [ + "func 0", + "current witness index : _0", + "private parameters indices : []", + "public parameters indices : []", + "return value indices : []" + ], + "debug_symbols": "XY5BCsQwCEXv4rqLWfcqw1BsaosgJtikMITefWyYQOlK/3/6tcJCc9km1jXuML4rzMYivE0SA2aO6m49B+hyykbkFty4byU00gyjFpEBDpTShvaE2mpGc/oagHTx6oErC13d+XGBge158UBjnIX+ci0abjR/Uyf942Qx0FKMrqTGPPsH", + "file_map": {}, + "names": [ + "main" + ], + "brillig_names": [] +} diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap new file mode 100644 index 00000000000..476ae4e6705 --- /dev/null +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_1/execute__tests__expanded.snap @@ -0,0 +1,74 @@ +--- +source: tooling/nargo_cli/tests/execute.rs +expression: expanded_code +--- +trait Serialize { + let Size: u32; + + fn serialize(self) -> [Field; Size]; +} + +impl Serialize for (A, B) +where + A: Serialize, + B: Serialize, +{ + let Size: u32 = ::Size + ::Size; + + fn serialize(self) -> [Field; ::Size + ::Size] { + let mut array: [Field; ::Size + ::Size] = + std::mem::zeroed(); + let a: [Field; ::Size] = self.0.serialize(); + let b: [Field; ::Size] = self.1.serialize(); + for i in 0_u32..a.len() { + array[i] = a[i]; + } + for i in 0_u32..b.len() { + { + let i_3798: u32 = i + a.len(); + array[i_3798] = b[i]; + } + } + array + } +} + +impl Serialize for [T; N] +where + T: Serialize, +{ + let Size: u32 = N * ::Size; + + fn serialize(self) -> [Field; N * ::Size] { + let mut array: [Field; N * ::Size] = std::mem::zeroed(); + let mut array_i: u32 = 0_u32; + { + let ___i0: Self = self; + for ___i1 in 0_u32..___i0.len() { + let elem: T = ___i0[___i1]; + { + let elem_fields: [Field; ::Size] = elem.serialize(); + for i in 0_u32..elem_fields.len() { + array[array_i] = elem_fields[i]; + array_i = array_i + 1_u32; + } + } + } + }; + array + } +} + +impl Serialize for Field { + let Size: u32 = 1; + + fn serialize(self) -> [Self; 1] { + [self] + } +} + +fn main() { + let x: (((Field, [Field; 3]), [Field; 4]), Field) = + (((1_Field, [2_Field, 3_Field, 4_Field]), [5_Field, 6_Field, 7_Field, 8_Field]), 9_Field); + assert(x.serialize().len() == 9_u32); +} diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_2/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_2/execute__tests__expanded.snap index ba5ebb3d93c..163de61e9fd 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_2/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_2/execute__tests__expanded.snap @@ -5,63 +5,27 @@ expression: expanded_code trait Serialize { let Size: u32; - fn serialize(self) -> [Field; Size]; + fn serialize(self); } -impl Serialize for (A, B) where A: Serialize, B: Serialize { - type Size = ::Size + ::Size; - - fn serialize(self) -> [Field; ::Size + ::Size] where A: Serialize, B: Serialize { - let mut array: [Field; ::Size + ::Size] = std::mem::zeroed(); - let a: [Field; ::Size] = Serialize::serialize(self.0); - let b: [Field; ::Size] = Serialize::serialize(self.1); - for i in 0..a.len() { - array[i] = a[i]; - }; - for i in 0..b.len() { - { - let i_3793: u32 = i + a.len(); - array[i_3793] = b[i]; - } - }; - array - } -} - -impl Serialize for [T; N] where T: Serialize { - type Size = N * ::Size; +impl Serialize for Field { + let Size: u32 = 1; - fn serialize(self) -> [Field; N * ::Size] where T: Serialize { - let mut array: [Field; N * ::Size] = std::mem::zeroed(); - let mut array_i: Field = 0; - { - let ___i0: Self = self; - for ___i1 in 0..___i0.len() { - let elem: T = ___i0[___i1]; - { - let elem_fields: [Field; ::Size] = Serialize::serialize(elem); - for i in 0..elem_fields.len() { - array[array_i] = elem_fields[i]; - array_i = array_i + 1; - } - } - } - }; - array - } + fn serialize(self) {} } -impl Serialize for Field { - let Size: u32 = 1; +impl Serialize for (A,) +where + A: Serialize, +{ + let Size: u32 = ::Size; - fn serialize(self) -> [Self; 1] { - [self] + fn serialize(self) { + self.0.serialize(); } } fn main() { - let x: (((Field, [Field; 3]), [Field; 4]), Field) = (((1, [2, 3, 4]), [5, 6, 7, 8]), 9); - assert(x.serialize().len() == 9); + let x: ((Field,),) = ((1_Field,),); + x.serialize(); } - -// Warning: the generated code has syntax errors diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_3/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_3/execute__tests__expanded.snap index 7d4d0ef29c9..73eb18999db 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_3/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_3/execute__tests__expanded.snap @@ -5,30 +5,43 @@ expression: expanded_code trait Serialize { let Size: u32; - fn serialize(self); + fn serialize(self) -> [Field; Size]; } -impl Serialize for Field { - let Size: u32 = 1; +impl Serialize for (A, B) +where + A: Serialize, + B: Serialize, +{ + let Size: u32 = ::Size + ::Size; - fn serialize(self) {} + fn serialize(self) -> [Field; ::Size + ::Size] { + let _: [Field; ::Size] = self.0.serialize(); + [0_Field; ::Size + ::Size] + } } -impl Serialize for (A,) +impl Serialize for [T; N] where - A: Serialize, + T: Serialize, { - type Size = ::Size; + let Size: u32 = N * ::Size; + + fn serialize(self) -> [Field; N * ::Size] { + [0_Field; N * ::Size] + } +} + +impl Serialize for Field { + let Size: u32 = 1; - fn serialize(self) - where - A: Serialize, - { - Serialize::serialize(self.0); + fn serialize(self) -> [Self; 1] { + [self] } } fn main() { - let x: ((Field,),) = ((1,),); - x.serialize(); + let x: (((Field, [Field; 3]), [Field; 4]), Field) = + (((1_Field, [2_Field, 3_Field, 4_Field]), [5_Field, 6_Field, 7_Field, 8_Field]), 9_Field); + assert(x.serialize().len() == 9_u32); } diff --git a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap index 0040ddafe24..c96f5bcdbc2 100644 --- a/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap +++ b/tooling/nargo_cli/tests/snapshots/compile_success_empty/serialize_4/execute__tests__expanded.snap @@ -8,20 +8,54 @@ trait Serialize { fn serialize(self) -> [Field; Size]; } -impl Serialize for (A, B) where A: Serialize, B: Serialize { - type Size = ::Size + ::Size; +impl Serialize for (A, B) +where + A: Serialize, + B: Serialize, +{ + let Size: u32 = ::Size + ::Size; - fn serialize(self) -> [Field; ::Size + ::Size] where A: Serialize, B: Serialize { - let _: [Field; ::Size] = Serialize::serialize(self.0); - [0; ::Size + ::Size] + fn serialize(self) -> [Field; ::Size + ::Size] { + let mut array: [Field; ::Size + ::Size] = + std::mem::zeroed(); + let a: [Field; ::Size] = self.0.serialize(); + let b: [Field; ::Size] = self.1.serialize(); + for i in 0_u32..a.len() { + array[i] = a[i]; + } + for i in 0_u32..b.len() { + { + let i_3798: u32 = i + a.len(); + array[i_3798] = b[i]; + } + } + array } } -impl Serialize for [T; N] where T: Serialize { - type Size = N * ::Size; +impl Serialize for [T; N] +where + T: Serialize, +{ + let Size: u32 = N * ::Size; - fn serialize(self) -> [Field; N * ::Size] where T: Serialize { - [0; N * ::Size] + fn serialize(self) -> [Field; N * ::Size] { + let mut array: [Field; N * ::Size] = std::mem::zeroed(); + let mut array_i: u32 = 0_u32; + { + let ___i0: Self = self; + for ___i1 in 0_u32..___i0.len() { + let elem: T = ___i0[___i1]; + { + let elem_fields: [Field; ::Size] = elem.serialize(); + for i in 0_u32..elem_fields.len() { + array[array_i] = elem_fields[i]; + array_i = array_i + 1_u32; + } + } + } + }; + array } } @@ -34,8 +68,6 @@ impl Serialize for Field { } fn main() { - let x: (((Field, [Field; 3]), [Field; 4]), Field) = (((1, [2, 3, 4]), [5, 6, 7, 8]), 9); - assert(x.serialize().len() == 9); + let x: (Field, [Field; 3]) = (1_Field, [2_Field, 3_Field, 4_Field]); + assert(x.serialize().len() == 4_u32); } - -// Warning: the generated code has syntax errors diff --git a/tooling/nargo_fmt/src/formatter/type_expression.rs b/tooling/nargo_fmt/src/formatter/type_expression.rs index 8bebfd42f0c..97f50ddc162 100644 --- a/tooling/nargo_fmt/src/formatter/type_expression.rs +++ b/tooling/nargo_fmt/src/formatter/type_expression.rs @@ -23,8 +23,8 @@ impl Formatter<'_> { self.write_space(); self.format_type_expression(*rhs); } - UnresolvedTypeExpression::AsTraitPath(..) => { - unreachable!("Should not be present in the AST") + UnresolvedTypeExpression::AsTraitPath(as_trait_path) => { + self.format_as_trait_path(*as_trait_path); } } diff --git a/tooling/nargo_fmt/src/formatter/types.rs b/tooling/nargo_fmt/src/formatter/types.rs index 237ab76ea11..aca3be7ae68 100644 --- a/tooling/nargo_fmt/src/formatter/types.rs +++ b/tooling/nargo_fmt/src/formatter/types.rs @@ -354,4 +354,11 @@ mod tests { let expected = "::baz"; assert_format_type(src, expected); } + + #[test] + fn format_as_trait_path_type_expression() { + let src = "[ Field ; < Field as foo :: Bar> :: baz ]"; + let expected = "[Field; ::baz]"; + assert_format_type(src, expected); + } }