mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 18:21:38 +03:00
Merge pull request #2014 from AleoHQ/fix/error-on-unrecognized-type
Check for Unrecognized Type
This commit is contained in:
commit
4d18031228
@ -149,7 +149,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_circuit(&access.inner, access.inner.span()));
|
||||
self.emit_err(TypeCheckerError::undefined_type(&access.inner, access.inner.span()));
|
||||
}
|
||||
}
|
||||
Some(type_) => {
|
||||
|
@ -43,6 +43,8 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
self.has_return = false;
|
||||
self.parent = Some(input.name());
|
||||
input.input.iter().for_each(|input_var| {
|
||||
// Check that the type of input parameter is valid.
|
||||
self.assert_type_is_valid(input_var.span, &input_var.type_);
|
||||
self.assert_not_tuple(input_var.span, &input_var.type_);
|
||||
|
||||
// If the function is not a program function, then check that the parameters do not have an associated mode.
|
||||
@ -68,6 +70,10 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
if !self.has_return {
|
||||
self.emit_err(TypeCheckerError::function_has_no_return(input.name(), input.span()));
|
||||
} else {
|
||||
// Check that the return type is valid.
|
||||
// TODO: Span should be just for the return type.
|
||||
self.assert_type_is_valid(input.span, &input.output);
|
||||
}
|
||||
|
||||
// Ensure there are no nested tuples in the return type.
|
||||
@ -88,7 +94,16 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
fn visit_circuit(&mut self, input: &'a Circuit) {
|
||||
// Check for conflicting circuit/record member names.
|
||||
let mut used = HashSet::new();
|
||||
if !input.members.iter().all(|member| used.insert(member.name())) {
|
||||
if !input
|
||||
.members
|
||||
.iter()
|
||||
.all(|CircuitMember::CircuitVariable(ident, type_)| {
|
||||
// TODO: Better spans.
|
||||
// Check that the member types are valid.
|
||||
self.assert_type_is_valid(input.span, type_);
|
||||
used.insert(ident.name)
|
||||
})
|
||||
{
|
||||
self.emit_err(if input.is_record {
|
||||
TypeCheckerError::duplicate_record_variable(input.name(), input.span())
|
||||
} else {
|
||||
|
@ -61,6 +61,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
VariableType::Mut
|
||||
};
|
||||
|
||||
// Check that the type of the definition is valid.
|
||||
self.assert_type_is_valid(input.span, &input.type_);
|
||||
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
|
@ -331,6 +331,23 @@ impl<'a> TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::tuple_not_allowed(span))
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error if the type is not valid.
|
||||
pub(crate) fn assert_type_is_valid(&self, span: Span, type_: &Type) {
|
||||
match type_ {
|
||||
// Check that the named composite type has been defined.
|
||||
Type::Identifier(identifier) if self.symbol_table.borrow().lookup_circuit(identifier.name).is_none() => {
|
||||
self.emit_err(TypeCheckerError::undefined_type(identifier.name, span));
|
||||
}
|
||||
// Check that the constituent types are valid.
|
||||
Type::Tuple(tuple_type) => {
|
||||
for type_ in tuple_type.iter() {
|
||||
self.assert_type_is_valid(span, type_)
|
||||
}
|
||||
}
|
||||
_ => {} // Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn types_to_string(types: &[Type]) -> String {
|
||||
|
@ -193,10 +193,10 @@ create_messages!(
|
||||
|
||||
/// Attempted to access an invalid circuit.
|
||||
@formatted
|
||||
invalid_circuit {
|
||||
args: (circuit: impl Display),
|
||||
undefined_type {
|
||||
args: (type_: impl Display),
|
||||
msg: format!(
|
||||
"Circuit {circuit} is not found in the current scope."
|
||||
"The type `{type_}` is not found in the current scope."
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
14
tests/compiler/circuits/unknown_member_type_fail.leo
Normal file
14
tests/compiler/circuits/unknown_member_type_fail.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
a: u8,
|
||||
bar: Bar,
|
||||
}
|
||||
|
||||
@program
|
||||
function main(a: u8) -> u8 {
|
||||
return a + 1u8;
|
||||
}
|
14
tests/compiler/function/unknown_parameter_type_fail.leo
Normal file
14
tests/compiler/function/unknown_parameter_type_fail.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(a: u8, foo: Foo) -> u8 {
|
||||
return a;
|
||||
}
|
||||
|
||||
@program
|
||||
function returns_foo(a: u8) -> Foo {
|
||||
return a;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(k: bool) -> bool {
|
||||
let b: Foo = 1u8;
|
||||
return k == true;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372017]: The type `Bar` is not found in the current scope.\n --> compiler-test:3:1\n |\n 3 | circuit Foo {\n 4 | a: u8,\n 5 | bar: Bar,\n 6 | }\n | ^\n"
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372017]: The type `Foo` is not found in the current scope.\n --> compiler-test:4:22\n |\n 4 | function main(a: u8, foo: Foo) -> u8 {\n | ^^^\nError [ETYC0372003]: Expected type `circuit Foo` but type `u8` was found\n --> compiler-test:9:22\n |\n 9 | function returns_foo(a: u8) -> Foo {\n | ^\nError [ETYC0372017]: The type `Foo` is not found in the current scope.\n --> compiler-test:9:1\n |\n 9 | function returns_foo(a: u8) -> Foo {\n 10 | return a;\n 11 | }\n | ^\n"
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372017]: The type `Foo` is not found in the current scope.\n --> compiler-test:5:2\n |\n 5 | \tlet b: Foo = 1u8;\n | ^^^^^^^^^^^^^^^^\nError [ETYC0372003]: Expected type `circuit Foo` but type `u8` was found\n --> compiler-test:5:15\n |\n 5 | \tlet b: Foo = 1u8;\n | ^^^\n"
|
Loading…
Reference in New Issue
Block a user