Skip to content

Commit 208560c

Browse files
Check vector type usage (#29247)
* Check vector element types Add missing type check to vector element types similar to array element types Fixes #29227 * Disallow invalid uses of vector types Fix larger issue where the invalidity of uses of vector types outside storage wasn't checked and would also result in panics. * Add test --------- Co-authored-by: Mohammad Fawaz <mohammadfawaz89@gmail.com>
1 parent c9109eb commit 208560c

File tree

8 files changed

+138
-3
lines changed

8 files changed

+138
-3
lines changed

crates/errors/src/errors/type_checker/type_checker_error.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,4 +1516,11 @@ create_messages!(
15161516
msg: format!("Dynamic call returns record type `{record_type}`, but dynamic calls return `dyn record`."),
15171517
help: Some("Dynamic calls cannot return concrete record types. Access fields on the returned `dyn record` with type annotations: `let x: u64 = result.field;`".to_string()),
15181518
}
1519+
1520+
@formatted
1521+
vector_type_only_in_storage {
1522+
args: (),
1523+
msg: format!("Vector types can only be used in storage declarations."),
1524+
help: None,
1525+
}
15191526
);

crates/passes/src/type_checking/visitor.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,11 @@ impl TypeCheckingVisitor<'_> {
17451745
self.assert_type_is_valid(inner, span);
17461746
}
17471747

1748+
// Vector types can only be used in storage declarations.
1749+
Type::Vector(_) => {
1750+
self.emit_err(TypeCheckerError::vector_type_only_in_storage(span));
1751+
}
1752+
17481753
Type::Address
17491754
| Type::Boolean
17501755
| Type::Composite(_)
@@ -1757,7 +1762,6 @@ impl TypeCheckingVisitor<'_> {
17571762
| Type::Integer(_)
17581763
| Type::Scalar
17591764
| Type::Signature
1760-
| Type::Vector(_)
17611765
| Type::Numeric
17621766
| Type::Err => {} // Do nothing.
17631767
}
@@ -1900,8 +1904,17 @@ impl TypeCheckingVisitor<'_> {
19001904
| Type::Integer(_)
19011905
| Type::Scalar
19021906
| Type::Numeric
1903-
| Type::Err
1904-
| Type::Vector(_) => {} // valid
1907+
| Type::Err => {} // valid
1908+
Type::Vector(vector_type) => {
1909+
let element_ty = vector_type.element_type();
1910+
match element_ty {
1911+
Type::Future(_) => self.emit_err(TypeCheckerError::invalid_storage_type("future", span)),
1912+
Type::Tuple(_) => self.emit_err(TypeCheckerError::invalid_storage_type("tuple", span)),
1913+
Type::Optional(_) => self.emit_err(TypeCheckerError::invalid_storage_type("optional", span)),
1914+
_ => {}
1915+
}
1916+
self.assert_storage_type_is_valid(element_ty, span);
1917+
}
19051918
}
19061919
}
19071920

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Error [ETYC0372079]: An array cannot have a record as an element type
2+
--> compiler-test:8:9
3+
|
4+
8 | data: [token; 2],
5+
| ^^^^^^^^^^^^^^^^
6+
Error [ETYC0372079]: An array cannot have a record as an element type
7+
--> compiler-test:13:9
8+
|
9+
13 | let arr: [token; 2] = [t, t];
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
2+
--> compiler-test:3:12
3+
|
4+
3 | fn foo(a: [Nonexistent]) -> bool {
5+
| ^^^^^^^^^^^^^^^^
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
2+
--> compiler-test:14:5
3+
|
4+
14 | data: [u32]
5+
| ^^^^^^^^^^^
6+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
7+
--> compiler-test:26:9
8+
|
9+
26 | data: [u32]
10+
| ^^^^^^^^^^^
11+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
12+
--> compiler-test:30:5
13+
|
14+
30 | mapping my_map: [u32] => u32;
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
17+
--> compiler-test:33:5
18+
|
19+
33 | mapping my_map2: u32 => [u32];
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
22+
--> compiler-test:3:8
23+
|
24+
3 | fn foo(a: [u32]) -> u32 {
25+
| ^^^^^^^^
26+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
27+
--> compiler-test:8:13
28+
|
29+
8 | fn bar() -> [u32] {
30+
| ^^^^^
31+
Error [ETYC0372117]: Expected type `[u32]` but type `u32` was found.
32+
--> compiler-test:9:12
33+
|
34+
9 | return 0u32;
35+
| ^^^^
36+
Error [ETYC0372189]: Vector types can only be used in storage declarations.
37+
--> compiler-test:18:8
38+
|
39+
18 | fn baz(a: [[u32]; 3]) -> u32 {
40+
| ^^^^^^^^^^^^^
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
program test.aleo {
2+
record token {
3+
owner: address,
4+
amount: u64,
5+
}
6+
7+
struct wrapper {
8+
data: [token; 2],
9+
}
10+
11+
fn main(owner: address) -> u8 {
12+
let t: token = token { owner: owner, amount: 1u64 };
13+
let arr: [token; 2] = [t, t];
14+
return 0u8;
15+
}
16+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
program test.aleo {
3+
fn foo(a: [Nonexistent]) -> bool {
4+
return true;
5+
}
6+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
// Vector as function parameter
3+
fn foo(a: [u32]) -> u32 {
4+
return 0u32;
5+
}
6+
7+
// Vector as function return type
8+
fn bar() -> [u32] {
9+
return 0u32;
10+
}
11+
12+
// Vector as struct field
13+
struct MyStruct {
14+
data: [u32]
15+
}
16+
17+
// Vector nested in array
18+
fn baz(a: [[u32]; 3]) -> u32 {
19+
return 0u32;
20+
}
21+
22+
program test.aleo {
23+
// Vector as record field
24+
record MyRecord {
25+
owner: address,
26+
data: [u32]
27+
}
28+
29+
// Vector as mapping key type
30+
mapping my_map: [u32] => u32;
31+
32+
// Vector as mapping value type
33+
mapping my_map2: u32 => [u32];
34+
35+
fn main() -> Final {
36+
return final {};
37+
}
38+
}

0 commit comments

Comments
 (0)