Skip to content

Comparison

Move supports four comparison operations <, >, <=, and >=.

SyntaxOperation
<less than
>greater than
<=less than or equal to
>=greater than or equal to

Comparison operations only work if both operands have the same type.

script {
fun example() {
0 >= 0; // `true`
1u128 > 2u128; // `false`
}
}

If the operands have different types, there is a type checking error.

script {
fun example() {
1u8 >= 1u128; // ERROR!
// ^^^^^ expected an argument of type `u8`
}
}

Prior to language version 2.2, comparison operations only work with integer types. Since language version 2.2, comparison operations work with all types.

TypeSemantics
integercompare by the numerical value
booltrue being larger than false
addresscompare as 256-bit unsigned integers
signercompare by the address wrapped by the signer
structcompare by field values first, and then by the number of fields.
vectorcompare by element values first, and then by the number of elements
function valuecompare in order by module address, module name, function name, argument type list, and captured value list
referencecompare by the value being referenced
module 0x42::example {
struct S has copy, drop { f: u64, s: vector<u8> }
fun true_example(): bool {
let s1 = S { f: 0, s: b"" };
let s2 = S { f: 1, s: b"" };
// return true
s1 < s2
}
fun false_example(): bool {
let s1 = S { f: 0, s: b"abc" };
let s2 = S { f: 0, s: b"" };
// return false
s1 < s2
}
}

When comparing references, the values being referenced are compared. The type of the reference (immutable or mutable) does not matter. This means that you can compare an immutable & reference with a mutable one &mut of the same underlying type.

script {
fun example() {
let i = &0u64;
let m = &mut 1u64;
i > m; // `false`
m < i; // `false`
m >= m; // `true`
i <= i; // `true`
}
}

The above is equivalent to applying an explicit freeze to each mutable reference where needed

script {
fun example() {
let i = &0u64;
let m = &mut 1u64;
i > freeze(m); // `false`
freeze(m) < i; // `false`
m >= m; // `true`
i <= i; // `true`
}
}

But again, the underlying type must be the same.

script {
fun example() {
let i = &0u64;
let s = &b"";
i > s; // ERROR!
// ^ expected an argument of type '&u64'
}
}

Comparison operations consume operands for integers but automatically borrow them for non-integer types. This differs from the equality == and inequality != operations, which always consume their operands and mandate the drop ability.

module 0x42::example {
struct Coin has store { value: u64 }
fun invalid(c1: Coin, c2: Coin) {
c1 <= c2 // OK!
c1 == c2 // ERROR!
// ^^ ^^ These resources would be destroyed!
}
}