Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Compiler-v2][Feature] Index notation #13695

Merged
merged 4 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Diagnostics:
error: value of type `test::Y<test::X<bool>>` does not have the `copy` ability
┌─ tests/ability-check/index_ability_err.move:12:17
12 │ let _ = Y<X<bool>>[addr];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that we support the dref here now!

│ ^^^^^^^^^^^^^^^^ reference content copied here
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module 0x42::test {

struct X<M> has copy, drop, store {
value: M
}
struct Y<T> has key, drop {
field: T
}

fun test_resource_no_copy() acquires Y {
let addr = @0x1;
let _ = Y<X<bool>>[addr];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Diagnostics:
error: resource indexing can only applied to a resource type (a struct type which has key ability)
┌─ tests/ability-check/index_ability_err_2.move:9:17
9 │ let _ = X<bool>[addr];
│ ^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module 0x42::test {

struct X<M> has copy, drop, store {
value: M
}

fun test_struct_no_resource() acquires X {
let addr = @0x1;
let _ = X<bool>[addr];
}

}
91 changes: 91 additions & 0 deletions third_party/move/move-compiler-v2/tests/checking-lang-v1/index.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@

Diagnostics:
error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:11:17
11 │ assert!((test::R[@0x1]).value == true, 0);
│ ^^^^^^^^^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:15:9
15 │ 0x42::test::R[@0x1].value = false;
│ ^^^^^^^^^^^^^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:16:17
16 │ assert!(R[@0x1].value == false, 1);
│ ^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:38:17
38 │ assert!(test::Y<X<bool>>[@0x1].field.value == true, 0);
│ ^^^^^^^^^^^^^^^^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:43:22
43 │ let y = &mut 0x42::test ::Y<X<bool>> [addr];
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:45:17
45 │ assert!(Y<X<bool>>[addr].field.value == false, 1);
│ ^^^^^^^^^^^^^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:53:17
53 │ assert!(v[0].value == 2, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:70:17
70 │ assert!(v[0].field.value == true, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:71:17
71 │ assert!(v[1].field.value == false, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:88:17
88 │ assert!(v[0].field.value == true, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:89:17
89 │ assert!(v[1].field.value == false, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:90:9
90 │ v[0].field.value = false;
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:91:9
91 │ v[1].field.value = true;
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:92:17
92 │ assert!(v[0].field.value == false, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond

error: unsupported language construct
┌─ tests/checking-lang-v1/index.move:93:17
93 │ assert!(v[1].field.value == true, 0);
│ ^^^^ `_[_]` index operator in non-specification code only allowed in Move 2 and beyond
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
module 0x42::test {

struct R has key, drop { value: bool }

fun init(s: &signer) {
move_to(s, R{value: true});
}

fun test_resource_1() acquires R {
use 0x42::test;
assert!((test::R[@0x1]).value == true, 0);
}

fun test_resource_2() acquires R {
0x42::test::R[@0x1].value = false;
assert!(R[@0x1].value == false, 1);
}

struct X<M> has copy, drop, store {
value: M
}
struct Y<T> has key, drop {
field: T
}

fun init_2(s: &signer) {
let x = X {
value: true
};
let y = Y {
field: x
};
move_to(s, y);
}

fun test_resource_3() {
use 0x42::test;
assert!(test::Y<X<bool>>[@0x1].field.value == true, 0);
}

fun test_resource_4() {
let addr = @0x1;
let y = &mut 0x42::test ::Y<X<bool>> [addr];
y.field.value = false;
assert!(Y<X<bool>>[addr].field.value == false, 1);
}

fun test_vector() {
let x = X {
value: 2
};
let v = vector[x, x];
assert!(v[0].value == 2, 0);
}

fun test_vector_borrow() {
let x1 = X {
value: true
};
let x2 = X {
value: false
};
let y1 = Y {
field: x1
};
let y2 = Y {
field: x2
};
let v = vector[y1, y2];
assert!(v[0].field.value == true, 0);
assert!(v[1].field.value == false, 0);
}

fun test_vector_borrow_mut() {
let x1 = X {
value: true
};
let x2 = X {
value: false
};
let y1 = Y {
field: x1
};
let y2 = Y {
field: x2
};
let v = vector[y1, y2];
assert!(v[0].field.value == true, 0);
assert!(v[1].field.value == false, 0);
v[0].field.value = false;
v[1].field.value = true;
assert!(v[0].field.value == false, 0);
assert!(v[1].field.value == true, 0);
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

Diagnostics:
error: indexing can only be applied to a vector or a resource type (a struct type which has key ability)
┌─ tests/checking/typing/index_err.move:14:9
14 │ UNUSED_Test[@0x1];
│ ^^^^^^^^^^^^^^^^^

error: indexing can only be applied to a vector or a resource type (a struct type which has key ability)
┌─ tests/checking/typing/index_err.move:19:9
19 │ &test::UNUSED_Test[@0x1];
│ ^^^^^^^^^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module 0x42::test {

struct R has key, drop { value: bool }

spec schema UNUSED_Test {
}

fun test_no_ref_for_resource() acquires R {
use 0x42::test;
assert!((test::R[@0x1]).value == true, 0);
}

fun test_no_schema() {
UNUSED_Test[@0x1];
}

fun test_no_schema_ref() {
use 0x42::test;
&test::UNUSED_Test[@0x1];
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Diagnostics:
error: expected `vector<struct{value}>` but found a value of type `X<integer>`
┌─ tests/checking/typing/index_err_2.move:11:17
11 │ assert!(x[0].value == 2, 0);
│ ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module 0x42::test {

struct X<M> has copy, drop, store {
value: M
}

fun test_vector() {
let x = X {
value: 2
};
assert!(x[0].value == 2, 0);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Diagnostics:
error: Invalid operation: storage operation on type `test::Y` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------- called here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to be specific about the operation here. global resource test::Y<..> at addr borrowed here. Or even borrow_global<0x42::test::Y<0x42::test::X<bool>>(addr) called here. With the use of [] it's really unclear what could be "called" here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently we don't distinguish different storage operations: https://github.com/aptos-labs/aptos-core/blob/main/third_party/move/move-compiler-v2/src/function_checker.rs#L106. We want to revisit this later but I don't think we need to address it in this PR.


error: Invalid operation: access of the field `field` on type `test::Y` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------------- accessed here

error: Invalid operation: access of the field `value` on type `test::X` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------------------- accessed here
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module 0x42::test {

struct X<M> has copy, drop, store {
value: M
}
struct Y<T> has key, drop {
field: T
}

}

module 0x42::test2 {

fun test_resource_other_module() acquires 0x42::test::Y {
let addr = @0x1;
assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
spec {
// This is OK
assert 0x42::test::Y<0x42::test::X<bool>>[addr].field.value == true;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Diagnostics:
error: Invalid operation: storage operation on type `test::Y` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------- called here

error: Invalid operation: access of the field `field` on type `test::Y` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------------- accessed here

error: Invalid operation: access of the field `value` on type `test::X` can only be done within the defining module `0x42::test`
┌─ tests/file-format-generator/index_acquires_err.move:14:9
14 │ fun test_resource_other_module() acquires 0x42::test::Y {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
15 │ let addr = @0x1;
16 │ assert!((&0x42::test::Y<0x42::test::X<bool>>[addr]).field.value == true, 1);
│ ------------------------------------------------------- accessed here
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
processed 21 tasks
Loading
Loading