Merge pull request #2328 from AleoHQ/fix/issue-2324

[Fix] Fixes unwrapping panic when unwrapping `lookup_struct` in `ProgramVisitor::visit_function`
This commit is contained in:
d0cd 2023-03-31 16:06:51 -07:00 committed by GitHub
commit c74772cfac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 12 deletions

View File

@ -243,13 +243,14 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
}
Output::Internal(function_output) => {
// Check that the type of output is defined.
self.assert_type_is_defined(&function_output.type_, function_output.span);
// If the function is not a transition function, then it cannot output a record.
if let Type::Identifier(identifier) = function_output.type_ {
if !matches!(function.variant, Variant::Transition)
&& self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record
{
self.emit_err(TypeCheckerError::function_cannot_output_record(function_output.span));
if self.assert_type_is_defined(&function_output.type_, function_output.span) {
// If the function is not a transition function, then it cannot output a record.
if let Type::Identifier(identifier) = function_output.type_ {
if !matches!(function.variant, Variant::Transition)
&& self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record
{
self.emit_err(TypeCheckerError::function_cannot_output_record(function_output.span));
}
}
}
// Check that the type of the output is not a tuple. This is necessary to forbid nested tuples.

View File

@ -201,7 +201,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
}
}
},
Type::Mapping(_) | Type::Err => unreachable!(),
Type::Mapping(_) | Type::Err => unreachable!(
"Parsing guarantees that `mapping` and `err` types are not present at this location in the AST."
),
// Otherwise, the type is valid.
_ => (), // Do nothing
}

View File

@ -352,29 +352,33 @@ impl<'a> TypeChecker<'a> {
}
/// Emits an error if the type or its constituent types are not defined.
pub(crate) fn assert_type_is_defined(&self, type_: &Type, span: Span) {
pub(crate) fn assert_type_is_defined(&self, type_: &Type, span: Span) -> bool {
let mut is_defined = true;
match type_ {
// String types are temporarily disabled.
Type::String => {
is_defined = false;
self.emit_err(TypeCheckerError::strings_are_not_supported(span));
}
// Check that the named composite type has been defined.
Type::Identifier(identifier) if self.symbol_table.borrow().lookup_struct(identifier.name).is_none() => {
is_defined = false;
self.emit_err(TypeCheckerError::undefined_type(identifier.name, span));
}
// Check that the constituent types of the tuple are valid.
Type::Tuple(tuple_type) => {
for type_ in tuple_type.iter() {
self.assert_type_is_defined(type_, span)
is_defined &= self.assert_type_is_defined(type_, span)
}
}
// Check that the constituent types of mapping are valid.
Type::Mapping(mapping_type) => {
self.assert_type_is_defined(&mapping_type.key, span);
self.assert_type_is_defined(&mapping_type.value, span);
is_defined &= self.assert_type_is_defined(&mapping_type.key, span);
is_defined &= self.assert_type_is_defined(&mapping_type.value, span);
}
_ => {} // Do nothing.
}
is_defined
}
/// Emits an error if the type is not a mapping.

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372017]: The type `Board` is not found in the current scope.\n --> compiler-test:4:35\n |\n 4 | function aria192check_for_win(b: Board, p: u8) -> u128bool {\n | ^\nError [ETYC0372017]: The type `u128bool` is not found in the current scope.\n --> compiler-test:4:55\n |\n 4 | function aria192check_for_win(b: Board, p: u8) -> u128bool {\n | ^^^^^^^^\nError [ETYC0372005]: Unknown variable `test`\n --> compiler-test:5:16\n |\n 5 | return test;\n | ^^^^\n"

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Fail
*/
program test.aleo {
function aria192check_for_win(b: Board, p: u8) -> u128bool {
return test;
}
}