]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | # Operator expressions |
2 | ||
3 | Operators are defined for built in types by the Rust language. Many of the | |
4 | following operators can also be overloaded using traits in `std::ops` or | |
5 | `std::cmp`. | |
6 | ||
7 | ## Overflow | |
8 | ||
9 | Integer operators will panic when they overflow when compiled in debug mode. | |
10 | The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used | |
11 | to control this more directly. The following things are considered to be | |
12 | overflow: | |
13 | ||
14 | * When `+`, `*` or `-` create a value greater than the maximum value, or less | |
15 | than the minimum value that can be stored. This includes unary `-` on the | |
16 | smallest value of any signed integer type. | |
17 | * Using `/` or `%`, where the left-hand argument is the smallest integer of a | |
18 | signed integer type and the right-hand argument is `-1`. | |
19 | * Using `<<` or `>>` where the right-hand argument is greater than or equal to | |
20 | the number of bits in the type of the left-hand argument, or is negative. | |
21 | ||
22 | ## Grouped expressions | |
23 | ||
24 | An expression enclosed in parentheses evaluates to the result of the enclosed | |
25 | expression. Parentheses can be used to explicitly specify evaluation order | |
26 | within an expression. | |
27 | ||
28 | An example of a parenthesized expression: | |
29 | ||
30 | ```rust | |
31 | let x: i32 = 2 + 3 * 4; | |
32 | let y: i32 = (2 + 3) * 4; | |
33 | assert_eq!(x, 14); | |
34 | assert_eq!(y, 20); | |
35 | ``` | |
36 | ||
37 | ## Borrow operators | |
38 | ||
39 | The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix | |
40 | operators. When applied to an lvalue produce a reference (pointer) to the | |
41 | location that the value refers to. The lvalue is also placed into a borrowed | |
42 | state for the duration of the reference. For a shared borrow (`&`), this | |
43 | implies that the lvalue may not be mutated, but it may be read or shared again. | |
44 | For a mutable borrow (`&mut`), the lvalue may not be accessed in any way until | |
45 | the borrow expires. `&mut` evaluates its operand in a mutable lvalue context. | |
46 | If the `&` or `&mut` operators are applied to an rvalue, a temporary value is | |
47 | created; the lifetime of this temporary value is defined by [syntactic | |
48 | rules](expressions.html#temporary-lifetimes). These operators cannot be overloaded. | |
49 | ||
50 | ```rust | |
51 | { | |
52 | // a temporary with value 7 is created that lasts for this scope. | |
53 | let shared_reference = &7; | |
54 | } | |
55 | let mut array = [-2, 3, 9]; | |
56 | { | |
57 | // Mutably borrows `array` for this scope. | |
58 | // `array` may only be used through `mutable_reference`. | |
59 | let mutable_reference = &mut array; | |
60 | } | |
61 | ``` | |
62 | ||
63 | ## The dereference operator | |
64 | ||
65 | The `*` (dereference) operator is also a unary prefix operator. When applied to | |
66 | a [pointer](types.html#pointer-types) it denotes the pointed-to location. If | |
67 | the expression is of type `&mut T` and `*mut T`, and is either a local | |
68 | variable, a (nested) field of a local variance or is a mutable lvalue, then the | |
69 | resulting [lvalue](expressions.html#lvalues-and-rvalues) can be | |
70 | assigned to. Dereferencing a raw pointer requires `unsafe`. | |
71 | ||
72 | On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an | |
73 | [immutable lvalue context](expressions.html#mutability) and | |
74 | `*std::ops::Deref::deref_mut(&mut x)` in a mutable lvalue context. | |
75 | ||
76 | ```rust | |
77 | let x = &7; | |
78 | assert_eq!(*x, 7); | |
79 | let y = &mut 9; | |
80 | *y = 11; | |
81 | assert_eq!(*y, 11); | |
82 | ``` | |
83 | ||
84 | ## The `?` operator. | |
85 | ||
86 | The `?` ("question mark") operator can be applied to values of the `Result<T, | |
87 | E>` type to propagate errors. If applied to `Err(e)` it will return | |
88 | `Err(From::from(e))` from the enclosing function or closure. If applied to | |
89 | `Ok(x)` it will unwrap the value to return `x`. Unlike other unary operators | |
90 | `?` is written in postfix notation. `?` cannot be overloaded. | |
91 | ||
92 | ```rust | |
93 | # use std::num::ParseIntError; | |
94 | fn try_to_parse() -> Result<i32, ParseIntError> { | |
95 | let x: i32 = "123".parse()?; // x = 123 | |
96 | let y: i32 = "24a".parse()?; // returns an Err() immediately | |
97 | Ok(x + y) // Doesn't run. | |
98 | } | |
99 | ||
100 | let res = try_to_parse(); | |
101 | println!("{:?}", res); | |
102 | # assert!(res.is_err()) | |
103 | ``` | |
104 | ||
105 | ## Negation operators | |
106 | ||
107 | These are the last two unary operators. This table summarizes the behavior of | |
108 | them on primitive types and which traits are used to overload these operators | |
109 | for other types. Remember that signed integers are always represented using | |
110 | two's complement. The operands of all of these operators are evaluated in | |
111 | rvalue context so are moved or copied. | |
112 | ||
113 | | Symbol | Integer | `bool` | Floating Point | Overloading Trait | | |
114 | |--------|-------------|-------------|----------------|--------------------| | |
115 | | `-` | Negation* | | Negation | `std::ops::Neg` | | |
116 | | `!` | Bitwise NOT | Logical NOT | | `std::ops::Not` | | |
117 | ||
118 | \* Only for signed integer types. | |
119 | ||
120 | Here are some example of these operators | |
121 | ||
122 | ```rust | |
123 | let x = 6; | |
124 | assert_eq!(-x, -6); | |
125 | assert_eq!(!x, -7); | |
126 | assert_eq!(true, !false); | |
127 | ``` | |
128 | ||
129 | ## Arithmetic and Logical Binary Operators | |
130 | ||
131 | Binary operators expressions are all written with infix notation. This table | |
132 | summarizes the behavior of arithmetic and logical binary operators on | |
133 | primitive types and which traits are used to overload these operators for other | |
134 | types. Remember that signed integers are always represented using two's | |
135 | complement. The operands of all of these operators are evaluated in rvalue | |
136 | context so are moved or copied. | |
137 | ||
138 | | Symbol | Integer | `bool` | Floating Point | Overloading Trait | | |
139 | |--------|-------------------------|-------------|----------------|--------------------| | |
140 | | `+` | Addition | | Addition | `std::ops::Add` | | |
141 | | `-` | Subtraction | | Subtraction | `std::ops::Sub` | | |
142 | | `*` | Multiplication | | Multiplication | `std::ops::Mul` | | |
143 | | `/` | Division | | Division | `std::ops::Div` | | |
144 | | `%` | Remainder | | Remainder | `std::ops::Rem` | | |
145 | | `&` | Bitwise AND | Logical AND | | `std::ops::BitAnd` | | |
146 | | <code>|</code> | Bitwise OR | Logical OR | | `std::ops::BitOr` | | |
147 | | `^` | Bitwise XOR | Logical XOR | | `std::ops::BitXor` | | |
148 | | `<<` | Left Shift | | | `std::ops::Shl` | | |
149 | | `>>` | Right Shift* | | | `std::ops::Shr` | | |
150 | ||
151 | \* Arithmetic right shift on signed integer types, logical right shift on | |
152 | unsigned integer types. | |
153 | ||
154 | Here are examples of these operators being used. | |
155 | ||
156 | ```rust | |
157 | assert_eq!(3 + 6, 9); | |
158 | assert_eq!(5.5 - 1.25, 4.25); | |
159 | assert_eq!(-5 * 14, -70); | |
160 | assert_eq!(14 / 3, 4); | |
161 | assert_eq!(100 % 7, 2); | |
162 | assert_eq!(0b1010 & 0b1100, 0b1000); | |
163 | assert_eq!(0b1010 | 0b1100, 0b1110); | |
164 | assert_eq!(0b1010 ^ 0b1100, 0b110); | |
165 | assert_eq!(13 << 3, 104); | |
166 | assert_eq!(-10 >> 2, -3); | |
167 | ``` | |
168 | ||
169 | ## Comparison Operators | |
170 | ||
171 | Comparison operators are also defined both for primitive types and many type in | |
172 | the standard library. Parentheses are required when chaining comparison | |
173 | operators. For example, the expression `a == b == c` is invalid and may be | |
174 | written as `(a == b) == c`. | |
175 | ||
176 | Unlike arithmetic and logical operators, the traits for | |
177 | overloading the operators the traits for these operators are used more | |
178 | generally to show how a type may be compared and will likely be assumed to | |
179 | define actual comparisons by functions that use these traits as bounds. Many | |
180 | functions and macros in the standard library can then use that assumption | |
181 | (although not to ensure safety). Unlike the arithmetic and logical operators | |
182 | above, these operators implicitly take shared borrows of their operands, | |
183 | evaluating them in lvalue context: | |
184 | ||
185 | ```rust,ignore | |
186 | a == b; | |
187 | // is equivalent to | |
188 | ::std::cmp::PartialEq::eq(&a, &b); | |
189 | ``` | |
190 | ||
191 | This means that the operands don't have to be moved out of. | |
192 | ||
193 | | Symbol | Meaning | Overloading method | | |
194 | |--------|--------------------------|----------------------------| | |
195 | | `==` | Equal | `std::cmp::PartialEq::eq` | | |
196 | | `!=` | Not equal | `std::cmp::PartialEq::ne` | | |
197 | | `>` | Greater than | `std::cmp::PartialOrd::gt` | | |
198 | | `<` | Less than | `std::cmp::PartialOrd::lt` | | |
199 | | `>=` | Greater than or equal to | `std::cmp::PartialOrd::ge` | | |
200 | | `<=` | Less than or equal to | `std::cmp::PartialOrd::le` | | |
201 | ||
202 | Here are examples of the comparison operators being used. | |
203 | ||
204 | ```rust | |
205 | assert!(123 == 123); | |
206 | assert!(23 != -12); | |
207 | assert!(12.5 > 12.2); | |
208 | assert!([1, 2, 3] < [1, 3, 4]); | |
209 | assert!('A' <= 'B'); | |
210 | assert!("World" >= "Hello"); | |
211 | ``` | |
212 | ||
213 | ## Lazy boolean operators | |
214 | ||
215 | The operators `||` and `&&` may be applied to operands of boolean type. The | |
216 | `||` operator denotes logical 'or', and the `&&` operator denotes logical | |
217 | 'and'. They differ from `|` and `&` in that the right-hand operand is only | |
218 | evaluated when the left-hand operand does not already determine the result of | |
219 | the expression. That is, `||` only evaluates its right-hand operand when the | |
220 | left-hand operand evaluates to `false`, and `&&` only when it evaluates to | |
221 | `true`. | |
222 | ||
223 | ```rust | |
224 | let x = false || true; // true | |
225 | let y = false && panic!(); // false, doesn't evaluate `panic!()` | |
226 | ``` | |
227 | ||
228 | ## Type cast expressions | |
229 | ||
230 | A type cast expression is denoted with the binary operator `as`. | |
231 | ||
232 | Executing an `as` expression casts the value on the left-hand side to the type | |
233 | on the right-hand side. | |
234 | ||
235 | An example of an `as` expression: | |
236 | ||
237 | ```rust | |
238 | # fn sum(values: &[f64]) -> f64 { 0.0 } | |
239 | # fn len(values: &[f64]) -> i32 { 0 } | |
240 | fn average(values: &[f64]) -> f64 { | |
241 | let sum: f64 = sum(values); | |
242 | let size: f64 = len(values) as f64; | |
243 | sum / size | |
244 | } | |
245 | ``` | |
246 | ||
247 | `as` can be used to explicitly perform [coercions](type-coercions.html), as | |
248 | well as the following additional casts. Here `*T` means either `*const T` or | |
249 | `*mut T`. | |
250 | ||
251 | | Type of `e` | `U` | Cast performed by `e as U` | | |
252 | |-----------------------|-----------------------|----------------------------------| | |
253 | | Integer or Float type | Integer or Float type | Numeric cast | | |
254 | | C-like enum | Integer type | Enum cast | | |
255 | | `bool` or `char` | Integer type | Primitive to integer cast | | |
256 | | `u8` | `char` | `u8` to `char` cast | | |
257 | | `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | | |
258 | | `*T` where `T: Sized` | Numeric type | Pointer to address cast | | |
259 | | Integer type | `*V` where `V: Sized` | Address to pointer cast | | |
260 | | `&[T; n]` | `*const T` | Array to pointer cast | | |
261 | | [Function pointer](types.html#function-pointer-types) | `*V` where `V: Sized` | Function pointer to pointer cast | | |
262 | | Function pointer | Integer | Function pointer to address cast | | |
263 | ||
264 | \* or `T` and `V` are compatible unsized types, e.g., both slices, both the | |
265 | same trait object. | |
266 | ||
267 | ### Semantics | |
268 | ||
269 | * Numeric cast | |
270 | * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op | |
271 | * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will | |
272 | truncate | |
273 | * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will | |
274 | * zero-extend if the source is unsigned | |
275 | * sign-extend if the source is signed | |
276 | * Casting from a float to an integer will round the float towards zero | |
277 | * **[NOTE: currently this will cause Undefined Behavior if the rounded | |
278 | value cannot be represented by the target integer type][float-int]**. | |
279 | This includes Inf and NaN. This is a bug and will be fixed. | |
280 | * Casting from an integer to float will produce the floating point | |
281 | representation of the integer, rounded if necessary (rounding strategy | |
282 | unspecified) | |
283 | * Casting from an f32 to an f64 is perfect and lossless | |
284 | * Casting from an f64 to an f32 will produce the closest possible value | |
285 | (rounding strategy unspecified) | |
286 | * **[NOTE: currently this will cause Undefined Behavior if the value | |
287 | is finite but larger or smaller than the largest or smallest finite | |
288 | value representable by f32][float-float]**. This is a bug and will | |
289 | be fixed. | |
290 | * Enum cast | |
291 | * Casts an enum to its discriminant, then uses a numeric cast if needed. | |
292 | * Primitive to integer cast | |
293 | * `false` casts to `0`, `true` casts to `1` | |
294 | * `char` casts to the value of the code point, then uses a numeric cast if needed. | |
295 | * `u8` to `char` cast | |
296 | * Casts to the `char` with the corresponding code point. | |
297 | ||
298 | [float-int]: https://github.com/rust-lang/rust/issues/10184 | |
299 | [float-float]: https://github.com/rust-lang/rust/issues/15536 | |
300 | ||
301 | ## Assignment expressions | |
302 | ||
303 | An _assignment expression_ consists of an | |
abe05a73 XL |
304 | [lvalue](expressions.html#lvalues-and-rvalues) expression followed by an equals |
305 | sign (`=`) and an [rvalue](expressions.html#lvalues-and-rvalues) expression. | |
ea8adc8c | 306 | |
abe05a73 XL |
307 | Evaluating an assignment expression [drops](destructors.html) the left-hand |
308 | operand, unless it's an unitialized local variable or field of a local variable, | |
309 | and [either copies or moves](expressions.html#moved-and-copied-types) its | |
310 | right-hand operand to its left-hand operand. The left-hand operand must be an | |
311 | lvalue: using an rvalue results in a compiler error, rather than promoting it | |
312 | to a temporary. | |
ea8adc8c XL |
313 | |
314 | ```rust | |
315 | # let mut x = 0; | |
316 | # let y = 0; | |
317 | x = y; | |
318 | ``` | |
319 | ||
320 | ## Compound assignment expressions | |
321 | ||
322 | The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be | |
323 | composed with the `=` operator. The expression `lval OP= val` is equivalent to | |
324 | `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. | |
325 | Any such expression always has the [`unit`](types.html#tuple-types) type. | |
326 | These operators can all be overloaded using the trait with the same name as for | |
327 | the normal operation followed by 'Assign', for example, `std::ops::AddAssign` | |
328 | is used to overload `+=`. As with `=`, `lval` must be an lvalue. | |
329 | ||
330 | ```rust | |
331 | let mut x = 10; | |
332 | x += 4; | |
333 | assert_eq!(x, 14); | |
334 | ``` |