Description
🚀 Feature Request
Summary
For any non-reference operands of ==
and !=
, the compiler should automatically insert references. This would:
- make generated programs more efficient
- should be backwards-compatible at the source level
- make it consistent with the new comparison operators being added
Details
Note that currently, we can use ==
(or correspondingly !=
) on values or references. When used on a value, that value needs to have drop
ability (enforced by the compiler and the static bytecode verifier).
If the value has copy
ability, and we have x == y
, the compiler could end up making copies of x
and y
(specifically, the compiler inserts copies if x
or y
are alive after). We have a lint rule to detect this case and warn: https://aptos.dev/en/build/smart-contracts/linter#avoid_copy_on_identity_comparison. By implementing this feature, we can get rid of this lint (as the compiler automatically does what this lint was suggesting we do).
I believe it should be generally backwards compatible for the compiler to automatically insert references when using ==
or !=
on non-reference values. We would accept all programs we would previously accept, but also accept some programs that we would previous reject.
Consider the program:
struct W {
x: u64,
}
fun foo(x: W, y: W): u64 {
if (x == y) {
1
} else {
2
}
}
We get compiler errors that W
is not droppable.
By adding reference to the operands of ==
:
fun foo_ref_inserted(x: W, y: W): u64 {
if (&x == &y) {
1
} else {
2
}
}
This also gives compiler errors about non-droppability, but the error messages are slightly different.
On the other hand, consider this program:
struct W has copy {
x: u64,
}
fun foo(x: W, y: W): (W, W) {
if (x == y) {
(x, y)
} else {
(y, x)
}
}
Fails compilation because ==
drops the value.
But by adding references to the operands of ==
, the program compiles okay.
struct W has copy {
x: u64,
}
fun foo(x: W, y: W): (W, W) {
if (&x == &y) {
(x, y)
} else {
(y, x)
}
}
Similarly, this is not accepted by the compiler:
struct W has drop {
x: u64,
}
fun foo(x: W, y: W): (W, W) {
if (x == y) {
(x, y)
} else {
(y, x)
}
}
But the following reference-inserted version is:
struct W has drop {
x: u64,
}
fun foo(x: W, y: W): (W, W) {
if (&x == &y) {
(x, y)
} else {
(y, x)
}
}
Metadata
Metadata
Assignees
Labels
Type
Projects
Status