Skip to content

Operators

Operators work on values of one type at a time: both operands of a binary operator have the same type, with literals taking the type of the other side. They follow Rust and C, with a few exceptions noted below.

From the tightest to the loosest. All binary operators are left-associative: a - b - c is (a - b) - c.

precedence operators kind
1 f(x) a[i] s.x call, index, field
2 -x !x *p &x ref x comptime x prefix
3 x as T conversion
4 * / % multiplicative
5 + - additive
6 << >> shift
7 & bitwise and
8 ^ bitwise xor
9 | bitwise or
10 < <= > >= ordering
11 == != equality
12 && logical and
13 || logical or

As in Rust and unlike C, comparisons bind looser than the bitwise operators, so x & 1 == 0 is (x & 1) == 0. Unlike Rust, ordering binds tighter than equality, so a < b == c < d compares two bools.

A prefix operator applies to everything after it at its level: comptime a * b is (comptime a) * b, so write comptime (a * b) for a whole product.

operator operands result
+ - * integers, floats the same type; integers wrap around
/ % integers, floats integers truncate; floats per IEEE (% is fmod)
-x signed integers, floats negation
+ str, str concatenation (hosted)
+ [T], [T] a new list of both lists’ elements (hosted)
+ - *T and i64 a pointer moved by whole elements (Pointers)

See Types for overflow and division by zero.

operator operands result
== != any type made of comparable parts bool (Equality)
< <= > >= integers, floats, pointers of the same type; str; two values of a type with an Ord bool

Integers compare signed or unsigned according to their type, and pointers by address; strings compare byte by byte, a prefix first. Other types are ordered by their Ord: a < b is a.compare(b) < 0, so structs, enums, tuples, lists and options order once they or their parts have one. Arrays have no ordering.

operator operands result
& | ^ integers bitwise and, or, xor
& | ^ bools and, or, xor — both sides are always evaluated
!x integers every bit flipped (Rust’s !, C’s ~)
<< >> integers of one type shift

>> is arithmetic (sign-filling) for signed types and logical for unsigned ones. The shift amount is taken modulo the bit width, so x << 64 on an i64 is x, on the VM and natively alike.

operator operands result
&& || bools and, or — the right side is only evaluated if needed
!x bool not
operator meaning page
&place the address of a variable, field or element Pointers
*p what a pointer, ref or cell holds Pointers, References, Cells
ref e a new reference to a copy of e References

Assignment is a statement, not an operator: = and the compound assignments +=, -=, *=, /=, %=, &=, |=, ^=, <<= and >>= (Variables and control flow) cannot be used inside expressions.

There is no increment (++), no ternary ?: (use a match expression), and no operator overloading.