Skip to content

Commit

Permalink
Merge pull request #28466 from ProvableHQ/no-futures-in-structs
Browse files Browse the repository at this point in the history
Error on futures in arrays, structs, or mappings.
  • Loading branch information
d0cd authored Nov 27, 2024
2 parents d9fe41a + fec941a commit 0f406a5
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 2 deletions.
12 changes: 10 additions & 2 deletions compiler/passes/src/type_checking/check_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,13 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
if input.is_record { "record" } else { "struct" },
identifier.span,
));
} else if matches!(type_, Type::Future(..)) {
self.emit_err(TypeCheckerError::composite_data_type_cannot_contain_future(
if input.is_record { "record" } else { "struct" },
identifier.span,
));
}

// Ensure that there are no record members.
self.assert_member_is_not_record(identifier.span, input.identifier.name, type_);
// If the member is a struct, add it to the struct dependency graph.
Expand Down Expand Up @@ -194,8 +200,9 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {
fn visit_mapping(&mut self, input: &'a Mapping) {
// Check that a mapping's key type is valid.
self.assert_type_is_valid(&input.key_type, input.span);
// Check that a mapping's key type is not a tuple, record, or mapping.
// Check that a mapping's key type is not a future, tuple, record, or mapping.
match input.key_type.clone() {
Type::Future(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("key", "future", input.span)),
Type::Tuple(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("key", "tuple", input.span)),
Type::Composite(struct_type) => {
if let Some(struct_) = self.lookup_struct(struct_type.program, struct_type.id.name) {
Expand All @@ -211,8 +218,9 @@ impl<'a, N: Network> ProgramVisitor<'a> for TypeChecker<'a, N> {

// Check that a mapping's value type is valid.
self.assert_type_is_valid(&input.value_type, input.span);
// Check that a mapping's value type is not a tuple, record or mapping.
// Check that a mapping's value type is not a future, tuple, record or mapping.
match input.value_type.clone() {
Type::Future(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("value", "future", input.span)),
Type::Tuple(_) => self.emit_err(TypeCheckerError::invalid_mapping_type("value", "tuple", input.span)),
Type::Composite(struct_type) => {
if let Some(struct_) = self.lookup_struct(struct_type.program, struct_type.id.name) {
Expand Down
2 changes: 2 additions & 0 deletions compiler/passes/src/type_checking/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,8 @@ impl<'a, N: Network> TypeChecker<'a, N> {
}
// Check that the array element type is valid.
match array_type.element_type() {
// Array elements cannot be futures.
Type::Future(_) => self.emit_err(TypeCheckerError::array_element_cannot_be_future(span)),
// Array elements cannot be tuples.
Type::Tuple(_) => self.emit_err(TypeCheckerError::array_element_cannot_be_tuple(span)),
// Array elements cannot be records.
Expand Down
14 changes: 14 additions & 0 deletions errors/src/errors/type_checker/type_checker_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,4 +898,18 @@ create_messages!(
msg: format!("Cannot define a function with no parameters."),
help: None,
}

@formatted
composite_data_type_cannot_contain_future {
args: (data_type: impl Display),
msg: format!("A {data_type} cannot contain a future."),
help: None,
}

@formatted
array_element_cannot_be_future {
args: (),
msg: format!("An array cannot have a future as an element type."),
help: None,
}
);
24 changes: 24 additions & 0 deletions tests/expectations/compiler/futures/future_in_composite_fail.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace = "Compile"
expectation = "Fail"
outputs = ["""
Error [ETYC0372114]: A struct cannot contain a future.
--> compiler-test:7:9
|
7 | member: Future,
| ^^^^^^
Error [ETYC0372031]: A mapping's key cannot be a future
--> compiler-test:4:5
|
4 | mapping x: Future => Future;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error [ETYC0372031]: A mapping's value cannot be a future
--> compiler-test:4:5
|
4 | mapping x: Future => Future;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error [ETYC0372115]: An array cannot have a future as an element type.
--> compiler-test:12:9
|
12 | let an_array: [Future; 1] = [future];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"""]
22 changes: 22 additions & 0 deletions tests/tests/compiler/futures/future_in_composite_fail.leo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
namespace = "Compile"
expectation = "Fail"
*/

program test.aleo {
mapping x: Future => Future;

struct S {
member: Future,
}

async transition main() -> Future {
let future: Future = finish();
let an_array: [Future; 1] = [future];
return an_array[0u32];
}

async function finish() {
assert_eq(1u8, 1u8);
}
}

0 comments on commit 0f406a5

Please sign in to comment.