diff --git a/README.md b/README.md index 4b93832a58..1150569cb2 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ cd leo $ cargo build --release ``` -This will generate an executable under the `./target/release` directory. To run snarkOS, run the following command: +This will generate an executable under the `./target/release` directory. To run Leo, run the following command: ```bash ./target/release/leo ``` diff --git a/ast/src/leo.pest b/ast/src/leo.pest index 2d763db9ff..4bf42da3cf 100644 --- a/ast/src/leo.pest +++ b/ast/src/leo.pest @@ -197,15 +197,7 @@ type_self = { "Self" } type_circuit = { identifier } // Declared in types/array_type.rs -type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" } - -// Declared in types/array_element.rs -array_element = { - type_self - | type_tuple - | type_data - | type_circuit -} +type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" } // Declared in types/array_dimensions.rs array_dimensions = { diff --git a/ast/src/types/array_element.rs b/ast/src/types/array_element.rs deleted file mode 100644 index cbc37a12d8..0000000000 --- a/ast/src/types/array_element.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{ast::Rule, types::*}; - -use pest_ast::FromPest; -use serde::Serialize; - -#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] -#[pest_ast(rule(Rule::array_element))] -pub enum ArrayElement<'ast> { - Basic(DataType), - Tuple(TupleType<'ast>), - Circuit(CircuitType<'ast>), - SelfType(SelfType<'ast>), -} diff --git a/ast/src/types/array_type.rs b/ast/src/types/array_type.rs index 017dc5f661..04ba864f17 100644 --- a/ast/src/types/array_type.rs +++ b/ast/src/types/array_type.rs @@ -16,7 +16,7 @@ use crate::{ ast::Rule, - types::{ArrayDimensions, ArrayElement}, + types::{ArrayDimensions, Type}, SpanDef, }; @@ -27,7 +27,7 @@ use serde::Serialize; #[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[pest_ast(rule(Rule::type_array))] pub struct ArrayType<'ast> { - pub type_: ArrayElement<'ast>, + pub type_: Box>, pub dimensions: ArrayDimensions<'ast>, #[pest_ast(outer())] #[serde(with = "SpanDef")] diff --git a/ast/src/types/mod.rs b/ast/src/types/mod.rs index 00f1c46815..e00ea64af2 100644 --- a/ast/src/types/mod.rs +++ b/ast/src/types/mod.rs @@ -20,9 +20,6 @@ pub use address_type::*; pub mod array_dimensions; pub use array_dimensions::*; -pub mod array_element; -pub use array_element::*; - pub mod array_type; pub use array_type::*; diff --git a/compiler/tests/array/input/type_nested_value_nested_3x2.in b/compiler/tests/array/input/type_nested_value_nested_3x2.in new file mode 100644 index 0000000000..21fc9b953f --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [[0; 2]; 3]; diff --git a/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in b/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in new file mode 100644 index 0000000000..280b38b909 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_nested_value_nested_4x3x2.in b/compiler/tests/array/input/type_nested_value_nested_4x3x2.in new file mode 100644 index 0000000000..53ca13b024 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4]; diff --git a/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in b/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in new file mode 100644 index 0000000000..11f44a76a4 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_nested_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_nested_value_tuple_3x2.in b/compiler/tests/array/input/type_nested_value_tuple_3x2.in new file mode 100644 index 0000000000..689e164b73 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [0; (3, 2)]; diff --git a/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in b/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in new file mode 100644 index 0000000000..4a43d7d816 --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in b/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in new file mode 100644 index 0000000000..649a7154ad --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)]; diff --git a/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in b/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in new file mode 100644 index 0000000000..eed469d6ac --- /dev/null +++ b/compiler/tests/array/input/type_nested_value_tuple_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_tuple_value_nested_3x2.in b/compiler/tests/array/input/type_tuple_value_nested_3x2.in new file mode 100644 index 0000000000..cb3943365b --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [[0; 2]; 3]; diff --git a/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in b/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in new file mode 100644 index 0000000000..c787cbffd9 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in b/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in new file mode 100644 index 0000000000..8105eae543 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4]; diff --git a/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in b/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in new file mode 100644 index 0000000000..3e194e590d --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_nested_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_tuple_value_tuple_3x2.in b/compiler/tests/array/input/type_tuple_value_tuple_3x2.in new file mode 100644 index 0000000000..cbfeb6d5f1 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [0; (3, 2)]; diff --git a/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in b/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in new file mode 100644 index 0000000000..3409e8aaa9 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (3, 2)] = [0; (2, 3)]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in new file mode 100644 index 0000000000..6fd97ee2d2 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [0; (4, 3, 2)]; diff --git a/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in new file mode 100644 index 0000000000..d6de4af3c5 --- /dev/null +++ b/compiler/tests/array/input/type_tuple_value_tuple_4x3x2_fail.in @@ -0,0 +1,2 @@ +[main] +a: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering) diff --git a/compiler/tests/array/input_nested_3x2.leo b/compiler/tests/array/input_nested_3x2.leo index 88777e90f7..b7e59a5dc0 100644 --- a/compiler/tests/array/input_nested_3x2.leo +++ b/compiler/tests/array/input_nested_3x2.leo @@ -1,3 +1,3 @@ function main(a: [u8; (3, 2)]) { - console.assert(a == [[0u8; 2]; 3)]); + console.assert(a == [[0u8; 2]; 3]); } diff --git a/compiler/tests/array/mod.rs b/compiler/tests/array/mod.rs index cee31fec09..62a18bd541 100644 --- a/compiler/tests/array/mod.rs +++ b/compiler/tests/array/mod.rs @@ -58,14 +58,6 @@ fn test_registers() { // Expressions -#[test] -fn test_type_fail() { - let program_bytes = include_bytes!("type_fail.leo"); - let syntax_error = parse_program(program_bytes).is_err(); - - assert!(syntax_error); -} - #[test] fn test_inline() { let program_bytes = include_bytes!("inline.leo"); @@ -120,8 +112,6 @@ fn test_initializer_input_fail() { } #[test] -#[ignore] -// TODO (howardwu): Add support for this syntax. fn test_input_nested_3x2() { let program_bytes = include_bytes!("input_nested_3x2.leo"); let input_bytes = include_bytes!("input/input_nested_3x2.in"); @@ -238,3 +228,289 @@ fn test_slice() { assert_satisfied(program); } + +// Array type tests + +#[test] +fn test_type_fail() { + let program_bytes = include_bytes!("type_fail.leo"); + let syntax_error = parse_program(program_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_type_nested_value_nested_3x2() { + let program_bytes = include_bytes!("type_nested_value_nested_3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_nested_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_nested_value_nested_3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_nested_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_nested_value_nested_4x3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_nested_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_nested_value_nested_4x3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_nested_value_tuple_3x2() { + let program_bytes = include_bytes!("type_nested_value_tuple_3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_nested_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_nested_value_tuple_3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_nested_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_nested_value_tuple_4x3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_nested_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_nested_value_tuple_4x3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_tuple_value_nested_3x2() { + let program_bytes = include_bytes!("type_tuple_value_nested_3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_tuple_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_tuple_value_nested_3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_tuple_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_tuple_value_nested_4x3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_tuple_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_tuple_value_nested_4x3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_tuple_value_tuple_3x2() { + let program_bytes = include_bytes!("type_tuple_value_tuple_3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_tuple_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_tuple_value_tuple_3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +#[test] +fn test_type_tuple_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_tuple_value_tuple_4x3x2.leo"); + let program = parse_program(program_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_type_tuple_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_tuple_value_tuple_4x3x2_fail.leo"); + let program = parse_program(program_bytes).unwrap(); + + expect_compiler_error(program); +} + +// Tests for nested multi-dimensional arrays as input to the program + +#[test] +fn test_input_type_nested_value_nested_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_nested_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_tuple_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_nested_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_nested_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program) +} + +#[test] +fn test_input_type_nested_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_nested_value_tuple_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +// Tests for multi-dimensional arrays using tuple syntax as input to the program + +#[test] +fn test_input_type_tuple_value_nested_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_nested_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_nested_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_nested_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_nested_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_tuple_3x2() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_tuple_3x2_fail() { + let program_bytes = include_bytes!("type_input_3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} + +#[test] +fn test_input_type_tuple_value_tuple_4x3x2() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_4x3x2.in"); + let program = parse_program_with_input(program_bytes, input_bytes).unwrap(); + + assert_satisfied(program); +} + +#[test] +fn test_input_type_tuple_value_tuple_4x3x2_fail() { + let program_bytes = include_bytes!("type_input_4x3x2.leo"); + let input_bytes = include_bytes!("input/type_tuple_value_tuple_4x3x2_fail.in"); + let syntax_error = parse_program_with_input(program_bytes, input_bytes).is_err(); + + assert!(syntax_error); +} diff --git a/compiler/tests/array/type_fail.leo b/compiler/tests/array/type_fail.leo index 0b8e467e33..1402ceba4c 100644 --- a/compiler/tests/array/type_fail.leo +++ b/compiler/tests/array/type_fail.leo @@ -1,3 +1,3 @@ -let main() { +function main() { let a: [u8; -2] = [0u32; 2]; } \ No newline at end of file diff --git a/compiler/tests/array/type_input_3x2.leo b/compiler/tests/array/type_input_3x2.leo new file mode 100644 index 0000000000..ea60a0cc24 --- /dev/null +++ b/compiler/tests/array/type_input_3x2.leo @@ -0,0 +1,5 @@ +function main(a: [[u8; 2]; 3]) { + const b = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_input_4x3x2.leo b/compiler/tests/array/type_input_4x3x2.leo new file mode 100644 index 0000000000..2d9c4cff22 --- /dev/null +++ b/compiler/tests/array/type_input_4x3x2.leo @@ -0,0 +1,8 @@ +function main(a: [[[u8; 2]; 3]; 4]) { + const b = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_nested_3x2.leo b/compiler/tests/array/type_nested_value_nested_3x2.leo new file mode 100644 index 0000000000..bcf5bae674 --- /dev/null +++ b/compiler/tests/array/type_nested_value_nested_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [[u8; 2]; 3] = [[0; 2]; 3]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_nested_3x2_fail.leo b/compiler/tests/array/type_nested_value_nested_3x2_fail.leo new file mode 100644 index 0000000000..56c8916fb0 --- /dev/null +++ b/compiler/tests/array/type_nested_value_nested_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_nested_4x3x2.leo b/compiler/tests/array/type_nested_value_nested_4x3x2.leo new file mode 100644 index 0000000000..1691fa26c7 --- /dev/null +++ b/compiler/tests/array/type_nested_value_nested_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_nested_4x3x2_fail.leo b/compiler/tests/array/type_nested_value_nested_4x3x2_fail.leo new file mode 100644 index 0000000000..480327a91d --- /dev/null +++ b/compiler/tests/array/type_nested_value_nested_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_tuple_3x2.leo b/compiler/tests/array/type_nested_value_tuple_3x2.leo new file mode 100644 index 0000000000..5f14084d55 --- /dev/null +++ b/compiler/tests/array/type_nested_value_tuple_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [[u8; 2]; 3] = [0; (3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_tuple_3x2_fail.leo b/compiler/tests/array/type_nested_value_tuple_3x2_fail.leo new file mode 100644 index 0000000000..3bfb559615 --- /dev/null +++ b/compiler/tests/array/type_nested_value_tuple_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_tuple_4x3x2.leo b/compiler/tests/array/type_nested_value_tuple_4x3x2.leo new file mode 100644 index 0000000000..88a5143bd2 --- /dev/null +++ b/compiler/tests/array/type_nested_value_tuple_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_nested_value_tuple_4x3x2_fail.leo b/compiler/tests/array/type_nested_value_tuple_4x3x2_fail.leo new file mode 100644 index 0000000000..ce1219a37b --- /dev/null +++ b/compiler/tests/array/type_nested_value_tuple_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_nested_3x2.leo b/compiler/tests/array/type_tuple_value_nested_3x2.leo new file mode 100644 index 0000000000..0b960c6b44 --- /dev/null +++ b/compiler/tests/array/type_tuple_value_nested_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (2, 3)] = [[0; 3]; 2]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_nested_3x2_fail.leo b/compiler/tests/array/type_tuple_value_nested_3x2_fail.leo new file mode 100644 index 0000000000..e84f025a9f --- /dev/null +++ b/compiler/tests/array/type_tuple_value_nested_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (2, 3)] = [[0; 2]; 3]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_nested_4x3x2.leo b/compiler/tests/array/type_tuple_value_nested_4x3x2.leo new file mode 100644 index 0000000000..322a6f7601 --- /dev/null +++ b/compiler/tests/array/type_tuple_value_nested_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_nested_4x3x2_fail.leo b/compiler/tests/array/type_tuple_value_nested_4x3x2_fail.leo new file mode 100644 index 0000000000..cbb7ccbf76 --- /dev/null +++ b/compiler/tests/array/type_tuple_value_nested_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_tuple_3x2.leo b/compiler/tests/array/type_tuple_value_tuple_3x2.leo new file mode 100644 index 0000000000..d742a544a7 --- /dev/null +++ b/compiler/tests/array/type_tuple_value_tuple_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (2, 3)] = [0; (2, 3)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_tuple_3x2_fail.leo b/compiler/tests/array/type_tuple_value_tuple_3x2_fail.leo new file mode 100644 index 0000000000..884a75db9d --- /dev/null +++ b/compiler/tests/array/type_tuple_value_tuple_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (2, 3)] = [0; (3, 2)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_tuple_4x3x2.leo b/compiler/tests/array/type_tuple_value_tuple_4x3x2.leo new file mode 100644 index 0000000000..1205b1dc9c --- /dev/null +++ b/compiler/tests/array/type_tuple_value_tuple_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [u8; (4, 3, 2)] = [0; (4, 3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/compiler/tests/array/type_tuple_value_tuple_4x3x2_fail.leo b/compiler/tests/array/type_tuple_value_tuple_4x3x2_fail.leo new file mode 100644 index 0000000000..31e2a5e552 --- /dev/null +++ b/compiler/tests/array/type_tuple_value_tuple_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed order) +} \ No newline at end of file diff --git a/compiler/tests/input_files/program_input_and_program_state/input/token_withdraw.state b/compiler/tests/input_files/program_input_and_program_state/input/token_withdraw.state index f2fcd27992..219fc44776 100644 --- a/compiler/tests/input_files/program_input_and_program_state/input/token_withdraw.state +++ b/compiler/tests/input_files/program_input_and_program_state/input/token_withdraw.state @@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32]; commitment_randomness: [u8; 32] = [0u8; 32]; [state_leaf] -path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ]; +path: [u8; 128] = [0u8; 128]; memo: [u8; 32] = [0u8; 32]; network_id: u8 = 0; leaf_randomness: [u8; 32] = [0u8; 32]; \ No newline at end of file diff --git a/compiler/tests/input_files/program_state/input/token_withdraw.state b/compiler/tests/input_files/program_state/input/token_withdraw.state index f2fcd27992..219fc44776 100644 --- a/compiler/tests/input_files/program_state/input/token_withdraw.state +++ b/compiler/tests/input_files/program_state/input/token_withdraw.state @@ -18,7 +18,7 @@ serial_number_nonce: [u8; 32] = [0u8; 32]; commitment_randomness: [u8; 32] = [0u8; 32]; [state_leaf] -path: [u8; (32, 2)] = [ [0u8; 32], [0u8; 32] ]; +path: [u8; 128] = [0u8; 128]; memo: [u8; 32] = [0u8; 32]; network_id: u8 = 0; leaf_randomness: [u8; 32] = [0u8; 32]; \ No newline at end of file diff --git a/input/src/leo-input.pest b/input/src/leo-input.pest index ec2574644b..f82f51f1a6 100644 --- a/input/src/leo-input.pest +++ b/input/src/leo-input.pest @@ -89,13 +89,7 @@ type_address = { "address" } type_data = { type_field | type_group | type_boolean | type_address | type_integer } // Declared in types/array_type.rs -type_array = { "[" ~ array_element ~ ";" ~ array_dimensions ~ "]" } - -// Declared in types/array_element.rs -array_element = { - type_tuple - | type_data -} +type_array = { "[" ~ type_ ~ ";" ~ array_dimensions ~ "]" } // Declared in types/array_dimensions.rs array_dimensions = { diff --git a/input/src/types/array_dimensions.rs b/input/src/types/array_dimensions.rs index 3cb19adc1e..58d9e14703 100644 --- a/input/src/types/array_dimensions.rs +++ b/input/src/types/array_dimensions.rs @@ -53,12 +53,19 @@ impl<'ast> ArrayDimensions<'ast> { let old_dimension = multiple.numbers.clone(); ArrayDimensions::Multiple(Multiple { - numbers: old_dimension[..old_dimension.len() - 1].to_vec(), + numbers: old_dimension[1..].to_vec(), span: multiple.span.clone(), }) } } } + + pub fn is_empty(&self) -> bool { + match self { + ArrayDimensions::Single(_) => false, + ArrayDimensions::Multiple(multiple) => multiple.numbers.is_empty(), + } + } } impl<'ast> std::fmt::Display for ArrayDimensions<'ast> { diff --git a/input/src/types/array_element.rs b/input/src/types/array_element.rs deleted file mode 100644 index 42966b4af3..0000000000 --- a/input/src/types/array_element.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use crate::{ast::Rule, types::*}; - -use pest_ast::FromPest; - -#[derive(Clone, Debug, FromPest, PartialEq, Eq)] -#[pest_ast(rule(Rule::array_element))] -pub enum ArrayElement<'ast> { - Basic(DataType), - Tuple(TupleType<'ast>), -} - -impl<'ast> std::fmt::Display for ArrayElement<'ast> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match *self { - ArrayElement::Basic(ref basic) => write!(f, "{}", basic), - ArrayElement::Tuple(ref tuple) => write!(f, "{}", tuple), - } - } -} diff --git a/input/src/types/array_type.rs b/input/src/types/array_type.rs index 0110d7c030..00a05f4968 100644 --- a/input/src/types/array_type.rs +++ b/input/src/types/array_type.rs @@ -16,7 +16,7 @@ use crate::{ ast::Rule, - types::{ArrayDimensions, ArrayElement}, + types::{ArrayDimensions, Type}, }; use pest::Span; @@ -25,7 +25,7 @@ use pest_ast::FromPest; #[derive(Clone, Debug, FromPest, PartialEq, Eq)] #[pest_ast(rule(Rule::type_array))] pub struct ArrayType<'ast> { - pub type_: ArrayElement<'ast>, + pub type_: Box>, pub dimensions: ArrayDimensions<'ast>, #[pest_ast(outer())] pub span: Span<'ast>, diff --git a/input/src/types/mod.rs b/input/src/types/mod.rs index 45a997e720..b7a6793d7e 100644 --- a/input/src/types/mod.rs +++ b/input/src/types/mod.rs @@ -20,9 +20,6 @@ pub use address_type::*; pub mod array_dimensions; pub use array_dimensions::*; -pub mod array_element; -pub use array_element::*; - pub mod array_type; pub use array_type::*; diff --git a/package/src/inputs/state.rs b/package/src/inputs/state.rs index 594d6e4cb6..f5faad6929 100644 --- a/package/src/inputs/state.rs +++ b/package/src/inputs/state.rs @@ -71,27 +71,27 @@ impl StateFile { [state] leaf_index: u32 = 0; -root: [u8; 32] = [0u8; 32]; +root: [u8; 32] = [0; 32]; [[private]] [record] -serial_number: [u8; 64] = [0u8; 64]; -commitment: [u8; 32] = [0u8; 32]; +serial_number: [u8; 64] = [0; 64]; +commitment: [u8; 32] = [0; 32]; owner: address = aleo1daxej63vwrmn2zhl4dymygagh89k5d2vaw6rjauueme7le6k2q8sjn0ng9; is_dummy: bool = false; -value: u64 = 5; -payload: [u8; 32] = [0u8; 32]; -birth_program_id: [u8; 48] = [0u8; 48]; -death_program_id: [u8; 48] = [0u8; 48]; -serial_number_nonce: [u8; 32] = [0u8; 32]; -commitment_randomness: [u8; 32] = [0u8; 32]; +value: u64 = 0; +payload: [u8; 32] = [0; 32]; +birth_program_id: [u8; 48] = [0; 48]; +death_program_id: [u8; 48] = [0; 48]; +serial_number_nonce: [u8; 32] = [0; 32]; +commitment_randomness: [u8; 32] = [0; 32]; [state_leaf] -path: [u8; 128] = [0u8; 128]; -memo: [u8; 32] = [0u8; 32]; +path: [u8; 128] = [0; 128]; +memo: [u8; 32] = [0; 32]; network_id: u8 = 0; -leaf_randomness: [u8; 32] = [0u8; 32]; +leaf_randomness: [u8; 32] = [0; 32]; "#, self.package_name ) diff --git a/typed/src/input/input_value.rs b/typed/src/input/input_value.rs index 6a1fbb75a8..14fa81209e 100644 --- a/typed/src/input/input_value.rs +++ b/typed/src/input/input_value.rs @@ -18,7 +18,7 @@ use crate::{Expression as TypedExpression, GroupValue}; use leo_input::{ errors::InputParserError, expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, TupleExpression}, - types::{ArrayElement, ArrayType, DataType, IntegerType, TupleType, Type}, + types::{ArrayType, DataType, IntegerType, TupleType, Type}, values::{Address, AddressValue, BooleanValue, FieldValue, GroupValue as InputGroupValue, NumberValue, Value}, }; @@ -106,46 +106,56 @@ impl InputValue { mut array_type: ArrayType, inline: ArrayInlineExpression, ) -> Result { - let mut array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); + let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); // Return an error if the outer array dimension does not equal the number of array elements. - if let Some(outer_dimension) = array_dimensions.pop() { - array_type.dimensions = array_type.dimensions.next_dimension(); + if array_dimensions[0] != inline.expressions.len() { + return Err(InputParserError::array_inline_length(array_dimensions[0], inline)); + } - if outer_dimension != inline.expressions.len() { - return Err(InputParserError::array_inline_length(outer_dimension, inline)); - } - }; + array_type.dimensions = array_type.dimensions.next_dimension(); - let inner_array_type = if array_dimensions.len() == 0 { + let inner_array_type = if array_dimensions.len() == 1 { // This is a single array - match array_type.type_ { - ArrayElement::Basic(basic) => Type::Basic(basic), - ArrayElement::Tuple(tuple) => Type::Tuple(tuple), - } + *array_type.type_ } else { // This is a multi-dimensional array Type::Array(array_type) }; - let mut values = vec![]; + let mut elements = vec![]; for expression in inline.expressions.into_iter() { - let value = InputValue::from_expression(inner_array_type.clone(), expression)?; + let element = InputValue::from_expression(inner_array_type.clone(), expression)?; - values.push(value) + elements.push(element) } - Ok(InputValue::Array(values)) + Ok(InputValue::Array(elements)) } pub(crate) fn from_array_initializer( array_type: ArrayType, initializer: ArrayInitializerExpression, ) -> Result { - let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone()); - // Return an error if the array type does not equal the array expression + if initializer_dimensions.len() > 1 { + // The expression is an array initializer with tuple syntax + Self::from_array_initializer_tuple(array_type, initializer, initializer_dimensions) + } else { + // The expression is an array initializer with nested syntax + Self::from_array_initializer_nested(array_type, initializer, initializer_dimensions) + } + } + + pub(crate) fn from_array_initializer_tuple( + array_type: ArrayType, + initializer: ArrayInitializerExpression, + initializer_dimensions: Vec, + ) -> Result { + let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![]); + + // Return an error if the dimensions of the array are incorrect. if array_dimensions.ne(&initializer_dimensions) { return Err(InputParserError::array_init_length( array_dimensions, @@ -154,14 +164,10 @@ impl InputValue { )); } - let type_ = match array_type.type_ { - ArrayElement::Basic(basic) => Type::Basic(basic), - ArrayElement::Tuple(tuple) => Type::Tuple(tuple), - }; - - let value = InputValue::from_expression(type_, *initializer.expression.clone())?; + let value = InputValue::from_expression(array_element_type, *initializer.expression.clone())?; let mut elements = vec![]; + // Build the elements of the array using the `vec!` macro for (i, dimension) in initializer_dimensions.into_iter().enumerate() { if i == 0 { elements = vec![value.clone(); dimension]; @@ -175,6 +181,42 @@ impl InputValue { Ok(InputValue::Array(elements)) } + pub(crate) fn from_array_initializer_nested( + mut array_type: ArrayType, + initializer: ArrayInitializerExpression, + initializer_dimensions: Vec, + ) -> Result { + let array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone()); + + let current_array_dimension = array_dimensions[0]; + let current_initializer_dimension = initializer_dimensions[0]; + + // Return an error if the outer array dimension does not equal the number of array elements. + if current_array_dimension.ne(¤t_initializer_dimension) { + return Err(InputParserError::array_init_length( + array_dimensions, + initializer_dimensions, + initializer.span, + )); + } + + array_type.dimensions = array_type.dimensions.next_dimension(); + + let inner_array_type = if array_dimensions.len() == 1 { + // This is the innermost dimension + *array_type.type_ + } else { + // This is an outer dimension of a multi-dimensional array + Type::Array(array_type) + }; + + // Evaluate the array initializer + let element = InputValue::from_expression(inner_array_type.clone(), *initializer.expression)?; + let elements = vec![element; current_initializer_dimension]; + + Ok(InputValue::Array(elements)) + } + pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result { let num_types = tuple_type.types_.len(); let num_values = tuple.expressions.len(); @@ -198,6 +240,17 @@ impl InputValue { } } +// Recursively fetch all dimensions from the array type +fn fetch_nested_array_type_dimensions(array_type: ArrayType, mut array_dimensions: Vec) -> (Vec, Type) { + let mut current_dimension = TypedExpression::get_input_array_dimensions(array_type.dimensions); + array_dimensions.append(&mut current_dimension); + + match *array_type.type_ { + Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions), + type_ => (array_dimensions, type_), + } +} + impl fmt::Display for InputValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { diff --git a/typed/src/types/type_.rs b/typed/src/types/type_.rs index 911ebb6153..70a3d107b0 100644 --- a/typed/src/types/type_.rs +++ b/typed/src/types/type_.rs @@ -15,9 +15,8 @@ // along with the Leo library. If not, see . use crate::{Expression, Identifier, IntegerType}; -use leo_ast::types::{ArrayElement, ArrayType, CircuitType, DataType, TupleType, Type as AstType}; +use leo_ast::types::{ArrayType, CircuitType, DataType, TupleType, Type as AstType}; use leo_input::types::{ - ArrayElement as InputArrayElement, ArrayType as InputArrayType, DataType as InputDataType, TupleType as InputTupleType, @@ -102,24 +101,13 @@ impl From for Type { impl<'ast> From> for Type { fn from(array_type: ArrayType<'ast>) -> Self { - let element_type = Box::new(Type::from(array_type.type_)); + let element_type = Box::new(Type::from(*array_type.type_)); let dimensions = Expression::get_array_dimensions(array_type.dimensions); Type::Array(element_type, dimensions) } } -impl<'ast> From> for Type { - fn from(element: ArrayElement<'ast>) -> Self { - match element { - ArrayElement::Basic(type_) => Type::from(type_), - ArrayElement::Tuple(type_) => Type::from(type_), - ArrayElement::Circuit(type_) => Type::from(type_), - ArrayElement::SelfType(_type) => Type::SelfType, - } - } -} - impl<'ast> From> for Type { fn from(tuple_type: TupleType<'ast>) -> Self { let types = tuple_type.types.into_iter().map(|type_| Type::from(type_)).collect(); @@ -162,22 +150,13 @@ impl From for Type { impl<'ast> From> for Type { fn from(array_type: InputArrayType<'ast>) -> Self { - let element_type = Box::new(Type::from(array_type.type_)); + let element_type = Box::new(Type::from(*array_type.type_)); let dimensions = Expression::get_input_array_dimensions(array_type.dimensions); Type::Array(element_type, dimensions) } } -impl<'ast> From> for Type { - fn from(element: InputArrayElement<'ast>) -> Self { - match element { - InputArrayElement::Basic(type_) => Type::from(type_), - InputArrayElement::Tuple(type_) => Type::from(type_), - } - } -} - impl<'ast> From> for Type { fn from(tuple_type: InputTupleType<'ast>) -> Self { let types = tuple_type.types_.into_iter().map(|type_| Type::from(type_)).collect();