diff --git a/compiler/passes/src/flattening/flatten_program.rs b/compiler/passes/src/flattening/flatten_program.rs index cbe0165fe0..ca7aa035d9 100644 --- a/compiler/passes/src/flattening/flatten_program.rs +++ b/compiler/passes/src/flattening/flatten_program.rs @@ -31,8 +31,6 @@ impl ProgramReconstructor for Flattener<'_> { self.structs.insert(input.identifier().name, struct_name.name); } } - // TODO: Flatten the function arguments. - // Flatten the finalize block. let mut block = self.reconstruct_block(finalize.block).0; diff --git a/compiler/passes/src/type_checking/check_program.rs b/compiler/passes/src/type_checking/check_program.rs index 7488d6c39d..9087af2f89 100644 --- a/compiler/passes/src/type_checking/check_program.rs +++ b/compiler/passes/src/type_checking/check_program.rs @@ -31,10 +31,8 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { // Check for conflicting struct/record member names. let mut used = HashSet::new(); if !input.members.iter().all(|Member { identifier, type_ }| { - // TODO: Better spans. - // Check that the member types are valid. + // Check that the member types are defined. self.assert_type_is_defined(type_, identifier.span); - self.assert_valid_declaration_or_parameter_type(type_, identifier.span); used.insert(identifier.name) }) { self.emit_err(if input.is_record { @@ -72,8 +70,14 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> { } for Member { identifier, type_ } in input.members.iter() { - // Ensure there are no tuple typed members. - self.assert_not_tuple(identifier.span, type_); + // Check that the member type is not a tuple. + if matches!(type_, Type::Tuple(_)) { + self.emit_err(if input.is_record { + TypeCheckerError::record_cannot_contain_tuple(identifier.span) + } else { + TypeCheckerError::struct_cannot_contain_tuple(identifier.span) + }); + } // Ensure that there are no record members. self.assert_member_is_not_record(identifier.span, input.identifier.name, type_); } diff --git a/compiler/passes/src/type_checking/checker.rs b/compiler/passes/src/type_checking/checker.rs index aec2f67b4b..82b4e4406b 100644 --- a/compiler/passes/src/type_checking/checker.rs +++ b/compiler/passes/src/type_checking/checker.rs @@ -355,13 +355,6 @@ impl<'a> TypeChecker<'a> { Type::Identifier(struct_) } - /// Emits an error if the type is a tuple. - pub(crate) fn assert_not_tuple(&self, span: Span, type_: &Type) { - if matches!(type_, Type::Tuple(_)) { - self.emit_err(TypeCheckerError::tuple_not_allowed(span)) - } - } - /// Emits an error if the struct member is a record type. pub(crate) fn assert_member_is_not_record(&self, span: Span, parent: Symbol, type_: &Type) { match type_ { diff --git a/errors/src/errors/type_checker/type_checker_error.rs b/errors/src/errors/type_checker/type_checker_error.rs index 887cf96857..313c32f134 100644 --- a/errors/src/errors/type_checker/type_checker_error.rs +++ b/errors/src/errors/type_checker/type_checker_error.rs @@ -253,13 +253,6 @@ create_messages!( help: None, } - @formatted - tuple_not_allowed { - args: (), - msg: format!("Tuples are only allowed as function return types."), - help: None, - } - @formatted unreachable_code_after_return { args: (), @@ -468,4 +461,25 @@ create_messages!( msg: format!("Empty tuple expressions and tuple types are not allowed."), help: None, } + + @formatted + nested_tuple { + args: (), + msg: format!("Nested tuples are not supported."), + help: None, + } + + @formatted + struct_cannot_contain_tuple { + args: (), + msg: format!("A struct cannot contain a tuple."), + help: None, + } + + @formatted + record_cannot_contain_tuple { + args: (), + msg: format!("A record cannot contain a tuple."), + help: None, + } );