From f636bed59bad9df49a6e62b8f3ff8dd933a6259a Mon Sep 17 00:00:00 2001 From: Michael Benfield Date: Mon, 6 Jan 2025 09:36:02 -0800 Subject: [PATCH] Remove () expressions and () type except returns. () serves no purpose beyond indicating the absence of return values, at least until/unless we have some kind of type polymorphism. --- compiler/ast/src/statement/return_.rs | 6 +- compiler/parser/src/parser/expression.rs | 24 ++--- .../src/code_generation/visit_statements.rs | 91 +++++++++---------- .../src/type_checking/check_expressions.rs | 9 +- .../src/type_checking/check_statements.rs | 22 ++--- compiler/passes/src/type_checking/checker.rs | 38 ++++---- .../passes/src/type_checking/scope_state.rs | 3 - .../errors/type_checker/type_checker_error.rs | 11 ++- .../compiler/array/array_with_units_fail.out | 21 ----- .../constants/const_type_error_fail.out | 21 +---- .../finalize/set_in_an_assignment_fail.out | 2 +- .../compiler/function/unit_parameter_fail.out | 29 ++++++ .../statements/expr_statement_fail.out | 4 +- .../compiler/tuple/assign_unit_fail.out | 29 ------ .../compiler/tuple/function_return_unit.out | 9 -- .../tuple/function_unit_input_fail.out | 9 -- .../compiler/tuple/tuple_in_return_type.out | 5 - .../compiler/tuple/tuple_not_allowed_fail.out | 5 - tests/expectations/compiler/tuple/unit.out | 14 +-- .../parser/expression/literal/group_fail.out | 7 +- .../parser/expression/literal/tuple_fail.out | 22 +++++ .../compiler/array/array_with_units_fail.leo | 10 -- .../constants/const_type_error_fail.leo | 3 +- .../compiler/function/unit_parameter_fail.leo | 18 ++++ .../statements/expr_statement_fail.leo | 2 +- .../tests/compiler/tuple/assign_unit_fail.leo | 20 ---- .../compiler/tuple/function_return_unit.leo | 10 -- .../tuple/function_unit_input_fail.leo | 17 ---- tests/tests/compiler/tuple/unit.leo | 13 --- .../parser/expression/literal/tuple_fail.leo | 10 ++ 30 files changed, 192 insertions(+), 292 deletions(-) delete mode 100644 tests/expectations/compiler/array/array_with_units_fail.out create mode 100644 tests/expectations/compiler/function/unit_parameter_fail.out delete mode 100644 tests/expectations/compiler/tuple/assign_unit_fail.out delete mode 100644 tests/expectations/compiler/tuple/function_return_unit.out delete mode 100644 tests/expectations/compiler/tuple/function_unit_input_fail.out create mode 100644 tests/expectations/parser/expression/literal/tuple_fail.out delete mode 100644 tests/tests/compiler/array/array_with_units_fail.leo create mode 100644 tests/tests/compiler/function/unit_parameter_fail.leo delete mode 100644 tests/tests/compiler/tuple/assign_unit_fail.leo delete mode 100644 tests/tests/compiler/tuple/function_return_unit.leo delete mode 100644 tests/tests/compiler/tuple/function_unit_input_fail.leo create mode 100644 tests/tests/parser/expression/literal/tuple_fail.leo diff --git a/compiler/ast/src/statement/return_.rs b/compiler/ast/src/statement/return_.rs index 11dfe3f6ff..61fc70618d 100644 --- a/compiler/ast/src/statement/return_.rs +++ b/compiler/ast/src/statement/return_.rs @@ -33,7 +33,11 @@ pub struct ReturnStatement { impl fmt::Display for ReturnStatement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "return {}", self.expression) + if let Expression::Unit(..) = self.expression { + write!(f, "return") + } else { + write!(f, "return {}", self.expression) + } } } diff --git a/compiler/parser/src/parser/expression.rs b/compiler/parser/src/parser/expression.rs index 68091bfdb2..0e98f896ea 100644 --- a/compiler/parser/src/parser/expression.rs +++ b/compiler/parser/src/parser/expression.rs @@ -608,18 +608,20 @@ impl ParserContext<'_, N> { let (mut elements, trailing, span) = self.parse_expr_tuple()?; - match elements.len() { - // If the tuple expression is empty, return a `UnitExpression`. - 0 => Ok(Expression::Unit(UnitExpression { span, id: self.node_builder.next_id() })), - 1 => match trailing { + match (elements.len(), trailing) { + (0, _) | (1, true) => { + // A tuple with 0 or 1 elements - emit an error since tuples must have at least two elements. + Err(ParserError::tuple_must_have_at_least_two_elements("expression", span).into()) + } + (1, false) => { // If there is one element in the tuple but no trailing comma, e.g `(foo)`, return the element. - false => Ok(elements.swap_remove(0)), - // If there is one element in the tuple and a trailing comma, e.g `(foo,)`, emit an error since tuples must have at least two elements. - true => Err(ParserError::tuple_must_have_at_least_two_elements("expression", span).into()), - }, - // Otherwise, return a tuple expression. - // Note: This is the only place where `TupleExpression` is constructed in the parser. - _ => Ok(Expression::Tuple(TupleExpression { elements, span, id: self.node_builder.next_id() })), + Ok(elements.remove(0)) + } + _ => { + // Otherwise, return a tuple expression. + // Note: This is the only place where `TupleExpression` is constructed in the parser. + Ok(Expression::Tuple(TupleExpression { elements, span, id: self.node_builder.next_id() })) + } } } diff --git a/compiler/passes/src/code_generation/visit_statements.rs b/compiler/passes/src/code_generation/visit_statements.rs index 0771dc3454..c69bcc1666 100644 --- a/compiler/passes/src/code_generation/visit_statements.rs +++ b/compiler/passes/src/code_generation/visit_statements.rs @@ -80,59 +80,56 @@ impl<'a> CodeGenerator<'a> { } fn visit_return(&mut self, input: &'a ReturnStatement) -> String { - let outputs = match input.expression { + if let Expression::Unit(..) = input.expression { // Skip empty return statements. - Expression::Unit(_) => String::new(), - _ => { - let (operand, mut expression_instructions) = self.visit_expression(&input.expression); - // Get the output type of the function. - let output = self.current_function.unwrap().output.iter(); - // If the operand string is empty, initialize an empty vector. - let operand_strings = match operand.is_empty() { - true => vec![], - false => operand.split(' ').collect_vec(), - }; + return String::new(); + } - let mut future_output = String::new(); - let mut instructions = operand_strings - .iter() - .zip_eq(output) - .map(|(operand, output)| { - // Transitions outputs with no mode are private. - // Note that this unwrap is safe because we set the variant before traversing the function. - let visibility = match (self.variant.unwrap().is_transition(), output.mode) { - (true, Mode::None) => Mode::Private, - (_, mode) => mode, - }; - - if let Type::Future(_) = output.type_ { - future_output = format!( - " output {} as {}.aleo/{}.future;\n", - operand, - self.program_id.unwrap().name, - self.current_function.unwrap().identifier, - ); - String::new() - } else { - format!( - " output {} as {};\n", - operand, - self.visit_type_with_visibility(&output.type_, visibility) - ) - } - }) - .join(""); + let (operand, mut expression_instructions) = self.visit_expression(&input.expression); + // Get the output type of the function. + let output = self.current_function.unwrap().output.iter(); + // If the operand string is empty, initialize an empty vector. + let operand_strings = match operand.is_empty() { + true => vec![], + false => operand.split(' ').collect_vec(), + }; + + let mut future_output = String::new(); + let mut instructions = operand_strings + .iter() + .zip_eq(output) + .map(|(operand, output)| { + // Transitions outputs with no mode are private. + // Note that this unwrap is safe because we set the variant before traversing the function. + let visibility = match (self.variant.unwrap().is_transition(), output.mode) { + (true, Mode::None) => Mode::Private, + (_, mode) => mode, + }; - // Insert future output at the end. - instructions.push_str(&future_output); + if let Type::Future(_) = output.type_ { + future_output = format!( + " output {} as {}.aleo/{}.future;\n", + operand, + self.program_id.unwrap().name, + self.current_function.unwrap().identifier, + ); + String::new() + } else { + format!( + " output {} as {};\n", + operand, + self.visit_type_with_visibility(&output.type_, visibility) + ) + } + }) + .join(""); - expression_instructions.push_str(&instructions); + // Insert future output at the end. + instructions.push_str(&future_output); - expression_instructions - } - }; + expression_instructions.push_str(&instructions); - outputs + expression_instructions } fn visit_definition(&mut self, _input: &'a DefinitionStatement) -> String { diff --git a/compiler/passes/src/type_checking/check_expressions.rs b/compiler/passes/src/type_checking/check_expressions.rs index adddaa0534..8aef40fd38 100644 --- a/compiler/passes/src/type_checking/check_expressions.rs +++ b/compiler/passes/src/type_checking/check_expressions.rs @@ -996,12 +996,7 @@ impl<'a, N: Network> ExpressionVisitor<'a> for TypeChecker<'a, N> { ty } - fn visit_unit(&mut self, input: &'a UnitExpression, additional: &Self::AdditionalInput) -> Self::Output { - // Unit expression are only allowed inside a return statement. - if !self.scope_state.is_return { - self.emit_err(TypeCheckerError::unit_expression_only_in_return_statements(input.span())); - } - self.maybe_assert_type(&Type::Unit, additional, input.span()); - Type::Unit + fn visit_unit(&mut self, _input: &'a UnitExpression, _additional: &Self::AdditionalInput) -> Self::Output { + unreachable!("Unit expressions should not exist in normal code"); } } diff --git a/compiler/passes/src/type_checking/check_statements.rs b/compiler/passes/src/type_checking/check_statements.rs index 5c36215ba5..789a74bfb1 100644 --- a/compiler/passes/src/type_checking/check_statements.rs +++ b/compiler/passes/src/type_checking/check_statements.rs @@ -222,8 +222,6 @@ impl<'a, N: Network> StatementVisitor<'a> for TypeChecker<'a, N> { // Check that the type of the definition is not a unit type, singleton tuple type, or nested tuple type. match &input.type_ { - // If the type is an empty tuple, return an error. - Type::Unit => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.span)), // If the type is a singleton tuple, return an error. Type::Tuple(tuple) => match tuple.length() { 0 | 1 => unreachable!("Parsing guarantees that tuple types have at least two elements."), @@ -421,20 +419,12 @@ impl<'a, N: Network> StatementVisitor<'a> for TypeChecker<'a, N> { // Set the `has_return` flag. self.scope_state.has_return = true; - // Check that the return expression is not a nested tuple. - if let Expression::Tuple(TupleExpression { elements, .. }) = &input.expression { - for element in elements { - if matches!(element, Expression::Tuple(_)) { - self.emit_err(TypeCheckerError::nested_tuple_expression(element.span())); - } - } - } - - // Set the `is_return` flag. This is necessary to allow unit expressions in the return statement. - self.scope_state.is_return = true; // Type check the associated expression. - self.visit_expression(&input.expression, &return_type); - // Unset the `is_return` flag. - self.scope_state.is_return = false; + if let Expression::Unit(..) = input.expression { + // TODO - do will this error message be appropriate? + self.maybe_assert_type(&Type::Unit, &return_type, input.expression.span()); + } else { + self.visit_expression(&input.expression, &return_type); + } } } diff --git a/compiler/passes/src/type_checking/checker.rs b/compiler/passes/src/type_checking/checker.rs index b3abf3b267..1541f3ca80 100644 --- a/compiler/passes/src/type_checking/checker.rs +++ b/compiler/passes/src/type_checking/checker.rs @@ -856,29 +856,30 @@ impl<'a, N: Network> TypeChecker<'a, N> { } /// Emits an error if the type or its constituent types is not valid. - pub(crate) fn assert_type_is_valid(&mut self, type_: &Type, span: Span) -> bool { - let mut is_valid = true; + pub(crate) fn assert_type_is_valid(&mut self, type_: &Type, span: Span) { match type_ { + // Unit types may only appear as the return type of a function. + Type::Unit => { + self.emit_err(TypeCheckerError::unit_type_only_return(span)); + } // String types are temporarily disabled. Type::String => { - is_valid = false; self.emit_err(TypeCheckerError::strings_are_not_supported(span)); } // Check that the named composite type has been defined. Type::Composite(struct_) if self.lookup_struct(struct_.program, struct_.id.name).is_none() => { - is_valid = false; self.emit_err(TypeCheckerError::undefined_type(struct_.id.name, span)); } // Check that the constituent types of the tuple are valid. Type::Tuple(tuple_type) => { for type_ in tuple_type.elements().iter() { - is_valid &= self.assert_type_is_valid(type_, span) + self.assert_type_is_valid(type_, span); } } // Check that the constituent types of mapping are valid. Type::Mapping(mapping_type) => { - is_valid &= self.assert_type_is_valid(&mapping_type.key, span); - is_valid &= self.assert_type_is_valid(&mapping_type.value, span); + self.assert_type_is_valid(&mapping_type.key, span); + self.assert_type_is_valid(&mapping_type.value, span); } // Check that the array element types are valid. Type::Array(array_type) => { @@ -909,11 +910,10 @@ impl<'a, N: Network> TypeChecker<'a, N> { } _ => {} // Do nothing. } - is_valid &= self.assert_type_is_valid(array_type.element_type(), span) + self.assert_type_is_valid(array_type.element_type(), span); } _ => {} // Do nothing. } - is_valid } /// Emits an error if the type is not a mapping. @@ -1067,17 +1067,19 @@ impl<'a, N: Network> TypeChecker<'a, N> { } } } - // Check that the type of output is defined. - if self.assert_type_is_valid(&function_output.type_, function_output.span) { - // If the function is not a transition function, then it cannot output a record. - if let Type::Composite(struct_) = function_output.type_.clone() { - if !function.variant.is_transition() - && self.lookup_struct(struct_.program, struct_.id.name).unwrap().is_record - { - self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(function_output.span)); - } + + // Check that the output type is valid. + self.assert_type_is_valid(&function_output.type_, function_output.span); + + // If the function is not a transition function, then it cannot output a record. + if let Type::Composite(struct_) = function_output.type_.clone() { + if !function.variant.is_transition() + && self.lookup_struct(struct_.program, struct_.id.name).map_or(false, |s| s.is_record) + { + self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(function_output.span)); } } + // Check that the type of the output is not a tuple. This is necessary to forbid nested tuples. if matches!(&function_output.type_, Type::Tuple(_)) { self.emit_err(TypeCheckerError::nested_tuple_type(function_output.span)) diff --git a/compiler/passes/src/type_checking/scope_state.rs b/compiler/passes/src/type_checking/scope_state.rs index 725ba9786a..a213188af2 100644 --- a/compiler/passes/src/type_checking/scope_state.rs +++ b/compiler/passes/src/type_checking/scope_state.rs @@ -25,8 +25,6 @@ pub struct ScopeState { pub(crate) variant: Option, /// Whether or not the function that we are currently traversing has a return statement. pub(crate) has_return: bool, - /// Whether or not we are currently traversing a return statement. - pub(crate) is_return: bool, /// Current program name. pub(crate) program_name: Option, /// Whether or not we are currently traversing a stub. @@ -50,7 +48,6 @@ impl ScopeState { function: None, variant: None, has_return: false, - is_return: false, program_name: None, is_stub: true, futures: IndexMap::new(), diff --git a/errors/src/errors/type_checker/type_checker_error.rs b/errors/src/errors/type_checker/type_checker_error.rs index 3a44cd2d22..1260e041cc 100644 --- a/errors/src/errors/type_checker/type_checker_error.rs +++ b/errors/src/errors/type_checker/type_checker_error.rs @@ -418,8 +418,7 @@ create_messages!( help: None, } - // TODO: Consider changing this to a warning. - + // TODO This error is unused. Remove it in a future version. @formatted assign_unit_expression_to_variable { args: (), @@ -476,6 +475,7 @@ create_messages!( help: None, } + // TODO This error is unused. Remove it in a future version. @formatted unit_expression_only_in_return_statements { args: (), @@ -976,4 +976,11 @@ create_messages!( ), help: Some("Valid second operands are `u8`, `u16`, or `u32`".into()), } + + @formatted + unit_type_only_return { + args: (), + msg: "The unit type () may appear only as the return type of a function.".to_string(), + help: None, + } ); diff --git a/tests/expectations/compiler/array/array_with_units_fail.out b/tests/expectations/compiler/array/array_with_units_fail.out deleted file mode 100644 index b7f0e9bf22..0000000000 --- a/tests/expectations/compiler/array/array_with_units_fail.out +++ /dev/null @@ -1,21 +0,0 @@ -namespace = "Compile" -expectation = "Fail" -outputs = [""" -Error [ETYC0372056]: Unit expressions can only be used in return statements. - --> compiler-test:5:29 - | - 5 | let bar: [(); 2] = [(), ()]; - | ^^ -Error [ETYC0372056]: Unit expressions can only be used in return statements. - --> compiler-test:5:33 - | - 5 | let bar: [(); 2] = [(), ()]; - | ^^ -Error [ETYC0372036]: Function must return a value. - --> compiler-test:4:5 - | - 4 | transition foo() -> bool { - 5 | let bar: [(); 2] = [(), ()]; - 6 | } - | ^ -"""] diff --git a/tests/expectations/compiler/constants/const_type_error_fail.out b/tests/expectations/compiler/constants/const_type_error_fail.out index 8d5c6581ed..c4d9b01598 100644 --- a/tests/expectations/compiler/constants/const_type_error_fail.out +++ b/tests/expectations/compiler/constants/const_type_error_fail.out @@ -1,30 +1,15 @@ namespace = "Compile" expectation = "Fail" outputs = [""" -Error [ETYC0372055]: The left-hand side of a `DefinitionStatement` can only be an identifier or tuple. Note that a tuple must contain at least two elements. - --> compiler-test:7:9 - | - 7 | const A: () = (); - | ^^^^^^^^^^^^^^^^ Error [ETYC0372070]: The value of a const declaration must be a literal --> compiler-test:7:9 | - 7 | const A: () = (); - | ^^^^^^^^^^^^^^^^ -Error [ETYC0372056]: Unit expressions can only be used in return statements. - --> compiler-test:7:23 - | - 7 | const A: () = (); - | ^^ -Error [ETYC0372070]: The value of a const declaration must be a literal - --> compiler-test:8:9 - | - 8 | const B: u8 = ((1u8,1u8),1u8); + 7 | const B: u8 = ((1u8,1u8),1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error [ETYC0372023]: Tuples must be explicitly typed in Leo - --> compiler-test:8:23 + --> compiler-test:7:23 | - 8 | const B: u8 = ((1u8,1u8),1u8); + 7 | const B: u8 = ((1u8,1u8),1u8); | ^^^^^^^^^^^^^^^ | = The function definition must match the function return statement diff --git a/tests/expectations/compiler/finalize/set_in_an_assignment_fail.out b/tests/expectations/compiler/finalize/set_in_an_assignment_fail.out index f5dfba8c78..5e4ef293fe 100644 --- a/tests/expectations/compiler/finalize/set_in_an_assignment_fail.out +++ b/tests/expectations/compiler/finalize/set_in_an_assignment_fail.out @@ -1,7 +1,7 @@ namespace = "Compile" expectation = "Fail" outputs = [""" -Error [ETYC0372055]: The left-hand side of a `DefinitionStatement` can only be an identifier or tuple. Note that a tuple must contain at least two elements. +Error [ETYC0372123]: The unit type () may appear only as the return type of a function. --> compiler-test:11:9 | 11 | let result: () = Mapping::set(amounts, addr, amount); diff --git a/tests/expectations/compiler/function/unit_parameter_fail.out b/tests/expectations/compiler/function/unit_parameter_fail.out new file mode 100644 index 0000000000..7b14a227bc --- /dev/null +++ b/tests/expectations/compiler/function/unit_parameter_fail.out @@ -0,0 +1,29 @@ +namespace = "Compile" +expectation = "Fail" +outputs = [""" +Error [ETYC0372123]: The unit type () may appear only as the return type of a function. + --> compiler-test:5:9 + | + 5 | x: (), + | ^^^^^ +Error [ETYC0372123]: The unit type () may appear only as the return type of a function. + --> compiler-test:9:21 + | + 9 | transition main(x: ()) {} + | ^^^^^ +Error [ETYC0372123]: The unit type () may appear only as the return type of a function. + --> compiler-test:11:22 + | + 11 | transition other(x: [(); 2]) {} + | ^^^^^^^^^^ +Error [ETYC0372123]: The unit type () may appear only as the return type of a function. + --> compiler-test:13:39 + | + 13 | transition yet_another() -> [(); 2] {} + | ^ +Error [ETYC0372036]: Function must return a value. + --> compiler-test:13:5 + | + 13 | transition yet_another() -> [(); 2] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +"""] diff --git a/tests/expectations/compiler/statements/expr_statement_fail.out b/tests/expectations/compiler/statements/expr_statement_fail.out index 7a5aac14fe..d72cf72448 100644 --- a/tests/expectations/compiler/statements/expr_statement_fail.out +++ b/tests/expectations/compiler/statements/expr_statement_fail.out @@ -41,6 +41,6 @@ Error [ETYC0372053]: An expression statement must be a function call. Error [ETYC0372053]: An expression statement must be a function call. --> compiler-test:19:9 | - 19 | (); - | ^^^ + 19 | 1field; + | ^^^^^^^ """] diff --git a/tests/expectations/compiler/tuple/assign_unit_fail.out b/tests/expectations/compiler/tuple/assign_unit_fail.out deleted file mode 100644 index 6847fcb592..0000000000 --- a/tests/expectations/compiler/tuple/assign_unit_fail.out +++ /dev/null @@ -1,29 +0,0 @@ -namespace = "Compile" -expectation = "Fail" -outputs = [""" -Error [ETYC0372055]: The left-hand side of a `DefinitionStatement` can only be an identifier or tuple. Note that a tuple must contain at least two elements. - --> compiler-test:6:9 - | - 6 | let b: () = (); - | ^^^^^^^^^^^^^^ -Error [ETYC0372056]: Unit expressions can only be used in return statements. - --> compiler-test:6:21 - | - 6 | let b: () = (); - | ^^ -Error [ETYC0372055]: The left-hand side of a `DefinitionStatement` can only be an identifier or tuple. Note that a tuple must contain at least two elements. - --> compiler-test:11:9 - | - 11 | let b: () = bar(); - | ^^^^^^^^^^^^^^^^^ -Error [ETYC0372043]: Cannot call a local transition function from a transition function. - --> compiler-test:11:21 - | - 11 | let b: () = bar(); - | ^^^^^ -Error [ETYC0372006]: Call expected `1` args, but got `0` - --> compiler-test:11:21 - | - 11 | let b: () = bar(); - | ^^^^^ -"""] diff --git a/tests/expectations/compiler/tuple/function_return_unit.out b/tests/expectations/compiler/tuple/function_return_unit.out deleted file mode 100644 index 6864bbf90f..0000000000 --- a/tests/expectations/compiler/tuple/function_return_unit.out +++ /dev/null @@ -1,9 +0,0 @@ -namespace = "Compile" -expectation = "Pass" -outputs = [[{ compile = [{ initial_symbol_table = "462cd81513e909c609e0576e90c7597534b5344a5ed8e34dba5d31aff90a0bc4", type_checked_symbol_table = "623e5ab19827aca9f7189760af4e2126bbc139361d4686a3fc9f0c17ae068a90", unrolled_symbol_table = "623e5ab19827aca9f7189760af4e2126bbc139361d4686a3fc9f0c17ae068a90", initial_ast = "a076b480260c5ea0ea36da0405e311ce0dd8bff6400243213a1c8e71296e54b2", unrolled_ast = "a076b480260c5ea0ea36da0405e311ce0dd8bff6400243213a1c8e71296e54b2", ssa_ast = "a076b480260c5ea0ea36da0405e311ce0dd8bff6400243213a1c8e71296e54b2", flattened_ast = "fd15fe07e96f61c9936872758776ecf8efe6bd1a6eab93b9bddf4df0bc4ed47b", destructured_ast = "841ba7ea96bcdbceca1dd9d6d53676fb7a6aab7f9f46f8195d8725ab6927d149", inlined_ast = "841ba7ea96bcdbceca1dd9d6d53676fb7a6aab7f9f46f8195d8725ab6927d149", dce_ast = "841ba7ea96bcdbceca1dd9d6d53676fb7a6aab7f9f46f8195d8725ab6927d149", bytecode = """ -program test.aleo; - -function main: - input r0 as boolean.private; - input r1 as boolean.private; -""", errors = "", warnings = "" }] }]] diff --git a/tests/expectations/compiler/tuple/function_unit_input_fail.out b/tests/expectations/compiler/tuple/function_unit_input_fail.out deleted file mode 100644 index 01fad4c217..0000000000 --- a/tests/expectations/compiler/tuple/function_unit_input_fail.out +++ /dev/null @@ -1,9 +0,0 @@ -namespace = "Compile" -expectation = "Fail" -outputs = [""" -Error [ETYC0372056]: Unit expressions can only be used in return statements. - --> compiler-test:10:13 - | - 10 | foo(()); - | ^^ -"""] diff --git a/tests/expectations/compiler/tuple/tuple_in_return_type.out b/tests/expectations/compiler/tuple/tuple_in_return_type.out index 659ead1eda..9d3c3879f4 100644 --- a/tests/expectations/compiler/tuple/tuple_in_return_type.out +++ b/tests/expectations/compiler/tuple/tuple_in_return_type.out @@ -11,9 +11,4 @@ Error [ETYC0372052]: A tuple expression cannot contain another tuple expression. | 5 | return (a, (a + a, a * a)); | ^^^^^^^^^^^^^^ -Error [ETYC0372052]: A tuple expression cannot contain another tuple expression. - --> compiler-test:5:20 - | - 5 | return (a, (a + a, a * a)); - | ^^^^^^^^^^^^^^ """] diff --git a/tests/expectations/compiler/tuple/tuple_not_allowed_fail.out b/tests/expectations/compiler/tuple/tuple_not_allowed_fail.out index cd2d78c7b0..7c712032e7 100644 --- a/tests/expectations/compiler/tuple/tuple_not_allowed_fail.out +++ b/tests/expectations/compiler/tuple/tuple_not_allowed_fail.out @@ -21,11 +21,6 @@ Error [ETYC0372052]: A tuple expression cannot contain another tuple expression. | 13 | return (1u8, (2u16, 3u32)); | ^^^^^^^^^^^^ -Error [ETYC0372052]: A tuple expression cannot contain another tuple expression. - --> compiler-test:13:22 - | - 13 | return (1u8, (2u16, 3u32)); - | ^^^^^^^^^^^^ Error [ETYC0372117]: Expected an integer but type `(u8, u16)` was found. --> compiler-test:17:13 | diff --git a/tests/expectations/compiler/tuple/unit.out b/tests/expectations/compiler/tuple/unit.out index e43faf3774..ed6277a215 100644 --- a/tests/expectations/compiler/tuple/unit.out +++ b/tests/expectations/compiler/tuple/unit.out @@ -1,14 +1,8 @@ namespace = "Compile" expectation = "Pass" -outputs = [[{ compile = [{ initial_symbol_table = "5931e9e8bf3df8ca226d00a479f35404edcc010093d1eb360dc67d82391b1538", type_checked_symbol_table = "bac9de371b7871ec03c288aa6f1f932d59509e79fbecdda79dca5f1944e347d6", unrolled_symbol_table = "bac9de371b7871ec03c288aa6f1f932d59509e79fbecdda79dca5f1944e347d6", initial_ast = "5656071e540418bee7f1d24156ca443a68904977039c84ca8b060ead7d0195f3", unrolled_ast = "5656071e540418bee7f1d24156ca443a68904977039c84ca8b060ead7d0195f3", ssa_ast = "5656071e540418bee7f1d24156ca443a68904977039c84ca8b060ead7d0195f3", flattened_ast = "63bfc28e505ec93892a04a9c61e20040aba6af50526c30b19847ea0a02a26d23", destructured_ast = "c963649c5ab9a1fd4f8883e674465a2c4b331b9e0fa9cc8ea5b938dc65ca8e30", inlined_ast = "c963649c5ab9a1fd4f8883e674465a2c4b331b9e0fa9cc8ea5b938dc65ca8e30", dce_ast = "c963649c5ab9a1fd4f8883e674465a2c4b331b9e0fa9cc8ea5b938dc65ca8e30", bytecode = """ +outputs = [[{ compile = [{ initial_symbol_table = "5f63fbb0866219290b9c25ae6150dcf7df23b35fc63dcd13c6e085fa507d546b", type_checked_symbol_table = "2fbc99ea074d672d430fcb5c2e4db60d732bff120cb77c25997e1efdb4168493", unrolled_symbol_table = "2fbc99ea074d672d430fcb5c2e4db60d732bff120cb77c25997e1efdb4168493", initial_ast = "2744442271ec20dc37bf0b9bf73e39079da06b8c5cdd134e3f5d931a955c8edf", unrolled_ast = "2744442271ec20dc37bf0b9bf73e39079da06b8c5cdd134e3f5d931a955c8edf", ssa_ast = "2744442271ec20dc37bf0b9bf73e39079da06b8c5cdd134e3f5d931a955c8edf", flattened_ast = "b7f1c450d79cd7a78d9e174e20b5b8a4feb687eb3782a031f50d0bddb2639863", destructured_ast = "4cdc7012d694d9c2b854780bdee40ae4eceaa809a0d05cd40285efd37aac90ce", inlined_ast = "4cdc7012d694d9c2b854780bdee40ae4eceaa809a0d05cd40285efd37aac90ce", dce_ast = "4cdc7012d694d9c2b854780bdee40ae4eceaa809a0d05cd40285efd37aac90ce", bytecode = """ program test.aleo; -function foo: - input r0 as u8.private; - input r1 as u8.private; - assert.eq r0 r1; - assert.eq r1 r0; - function bar: input r0 as u8.private; input r1 as u8.private; @@ -21,12 +15,6 @@ function baz: assert.eq r0 r1; assert.eq r1 r0; -function floo: - input r0 as u8.private; - input r1 as u8.private; - assert.eq r0 r1; - assert.eq r1 r0; - function blar: input r0 as u8.private; input r1 as u8.private; diff --git a/tests/expectations/parser/expression/literal/group_fail.out b/tests/expectations/parser/expression/literal/group_fail.out index 452237171d..b1f0d58fb4 100644 --- a/tests/expectations/parser/expression/literal/group_fail.out +++ b/tests/expectations/parser/expression/literal/group_fail.out @@ -2,8 +2,11 @@ namespace = "ParseExpression" expectation = "Fail" outputs = [ """ -did not consume all input: 'group' @ 1:3-8 -""", +Error [EPAR0370029]: A tuple expression must have at least two elements. + --> test:1:1 + | + 1 | ()group + | ^^""", """ Error [EPAR0370017]: Could not parse the implicit value: 123. --> test:1:2 diff --git a/tests/expectations/parser/expression/literal/tuple_fail.out b/tests/expectations/parser/expression/literal/tuple_fail.out new file mode 100644 index 0000000000..7136458121 --- /dev/null +++ b/tests/expectations/parser/expression/literal/tuple_fail.out @@ -0,0 +1,22 @@ +namespace = "ParseExpression" +expectation = "Fail" +outputs = [ + """ +Error [EPAR0370029]: A tuple expression must have at least two elements. + --> test:1:1 + | + 1 | () + | ^^""", + """ +Error [EPAR0370029]: A tuple expression must have at least two elements. + --> test:1:1 + | + 1 | (1u32,) + | ^^^^^^^""", + """ +Error [EPAR0370029]: A tuple expression must have at least two elements. + --> test:1:1 + | + 1 | (1field,) + | ^^^^^^^^^""", +] diff --git a/tests/tests/compiler/array/array_with_units_fail.leo b/tests/tests/compiler/array/array_with_units_fail.leo deleted file mode 100644 index a6a18d5e10..0000000000 --- a/tests/tests/compiler/array/array_with_units_fail.leo +++ /dev/null @@ -1,10 +0,0 @@ -/* -namespace = "Compile" -expectation = "Fail" -*/ - -program test.aleo { - transition foo() -> bool { - let bar: [(); 2] = [(), ()]; - } -} diff --git a/tests/tests/compiler/constants/const_type_error_fail.leo b/tests/tests/compiler/constants/const_type_error_fail.leo index 82ef7ed7ff..9a837db8f6 100644 --- a/tests/tests/compiler/constants/const_type_error_fail.leo +++ b/tests/tests/compiler/constants/const_type_error_fail.leo @@ -7,8 +7,7 @@ program test.aleo { const START: u32 = 0u32; transition foo(a: u32, b: u32, flag: bool) -> u32 { const STOP: u32 = 10u32; - const A: () = (); const B: u8 = ((1u8,1u8),1u8); return 1u32; } -} \ No newline at end of file +} diff --git a/tests/tests/compiler/function/unit_parameter_fail.leo b/tests/tests/compiler/function/unit_parameter_fail.leo new file mode 100644 index 0000000000..be645d3cf3 --- /dev/null +++ b/tests/tests/compiler/function/unit_parameter_fail.leo @@ -0,0 +1,18 @@ +/* +namespace = "Compile" +expectation = "Fail" +*/ + +program test.aleo { + struct S { + x: (), + y: u8, + } + + transition main(x: ()) {} + + transition other(x: [(); 2]) {} + + transition yet_another() -> [(); 2] {} + +} diff --git a/tests/tests/compiler/statements/expr_statement_fail.leo b/tests/tests/compiler/statements/expr_statement_fail.leo index 68266dfea9..0b16d2062a 100644 --- a/tests/tests/compiler/statements/expr_statement_fail.leo +++ b/tests/tests/compiler/statements/expr_statement_fail.leo @@ -19,7 +19,7 @@ program test.aleo { a; 1u8; -i8; - (); + 1field; return a + b; } diff --git a/tests/tests/compiler/tuple/assign_unit_fail.leo b/tests/tests/compiler/tuple/assign_unit_fail.leo deleted file mode 100644 index 3a3c388588..0000000000 --- a/tests/tests/compiler/tuple/assign_unit_fail.leo +++ /dev/null @@ -1,20 +0,0 @@ -/* -namespace = "Compile" -expectation = "Fail" -*/ - -program test.aleo { - - transition foo(a: u8) -> u8 { - let b: () = (); - return a + a; - } - - transition baz(a: u8) -> u8 { - let b: () = bar(); - return a + a; - } - - transition bar(a: u8) -> () {} -} - diff --git a/tests/tests/compiler/tuple/function_return_unit.leo b/tests/tests/compiler/tuple/function_return_unit.leo deleted file mode 100644 index 159397025a..0000000000 --- a/tests/tests/compiler/tuple/function_return_unit.leo +++ /dev/null @@ -1,10 +0,0 @@ -/* -namespace = "Compile" -expectation = "Pass" -*/ - -program test.aleo { - transition main(a: bool, b: bool) -> () { - return (); - } -} diff --git a/tests/tests/compiler/tuple/function_unit_input_fail.leo b/tests/tests/compiler/tuple/function_unit_input_fail.leo deleted file mode 100644 index 5e7fb3c14a..0000000000 --- a/tests/tests/compiler/tuple/function_unit_input_fail.leo +++ /dev/null @@ -1,17 +0,0 @@ -/* -namespace = "Compile" -expectation = "Fail" -*/ - -program test.aleo { - function foo(a: ()) -> u8 { - assert_eq(1u8, 2u8); - return 3u8; - } - - transition bar(a: u8, b: u8) -> u8 { - foo(()); - return a + b; - } - -} diff --git a/tests/tests/compiler/tuple/unit.leo b/tests/tests/compiler/tuple/unit.leo index 978b636fee..73e3c7ed85 100644 --- a/tests/tests/compiler/tuple/unit.leo +++ b/tests/tests/compiler/tuple/unit.leo @@ -4,13 +4,6 @@ expectation = "Pass" */ program test.aleo { - - transition foo(a: u8, b: u8) -> () { - assert_eq(a, b); - assert_eq(b, a); - return (); - } - transition bar(a: u8, b: u8) -> () { assert_eq(a, b); assert_eq(b, a); @@ -22,12 +15,6 @@ program test.aleo { assert_eq(b, a); } - transition floo(a: u8, b: u8) { - assert_eq(a, b); - assert_eq(b, a); - return (); - } - transition blar(a: u8, b: u8) { assert_eq(a, b); assert_eq(b, a); diff --git a/tests/tests/parser/expression/literal/tuple_fail.leo b/tests/tests/parser/expression/literal/tuple_fail.leo new file mode 100644 index 0000000000..658490452e --- /dev/null +++ b/tests/tests/parser/expression/literal/tuple_fail.leo @@ -0,0 +1,10 @@ +/* +namespace = "ParseExpression" +expectation = "Fail" +*/ + +() + +(1u32,) + +(1field,)