integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`,
`isize`, or `usize`.
-The type of an _unsuffixed_ integer literal is determined by type inference.
-If an integer type can be _uniquely_ determined from the surrounding program
-context, the unsuffixed integer literal has that type. If the program context
-underconstrains the type, it defaults to the signed 32-bit integer `i32`; if
-the program context overconstrains the type, it is considered a static type
-error.
+The type of an _unsuffixed_ integer literal is determined by type inference:
+
+* If an integer type can be _uniquely_ determined from the surrounding
+ program context, the unsuffixed integer literal has that type.
+
+* If the program context underconstrains the type, it defaults to the
+ signed 32-bit integer `i32`.
+
+* If the program context overconstrains the type, it is considered a
+ static type error.
Examples of integer literals of various forms:
_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point
types), which explicitly determine the type of the literal.
-The type of an _unsuffixed_ floating-point literal is determined by type
-inference. If a floating-point type can be _uniquely_ determined from the
-surrounding program context, the unsuffixed floating-point literal has that type.
-If the program context underconstrains the type, it defaults to double-precision `f64`;
-if the program context overconstrains the type, it is considered a static type
-error.
+The type of an _unsuffixed_ floating-point literal is determined by
+type inference:
+
+* If a floating-point type can be _uniquely_ determined from the
+ surrounding program context, the unsuffixed floating-point literal
+ has that type.
+
+* If the program context underconstrains the type, it defaults to `f64`.
+
+* If the program context overconstrains the type, it is considered a
+ static type error.
Examples of floating-point literals of various forms:
be undesired.
* Deadlocks
-* Reading data from private fields (`std::repr`)
* Leaks of memory and other resources
* Exiting without calling destructors
-* Sending signals
-* Accessing/modifying the file system
* Integer overflow
- Overflow is considered "unexpected" behavior and is always user-error,
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
as a configuration itself, like `unix` or `windows`.
* `target_os = "..."`. Operating system of the target, examples include
`"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
- `"bitrig"` or `"openbsd"`.
+ `"bitrig"` , `"openbsd"` or `"netbsd"`.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
expression's captured environment.
In this example, we define a function `ten_times` that takes a higher-order
-function argument, and call it with a lambda expression as an argument:
+function argument, and we then call it with a lambda expression as an argument:
```
fn ten_times<F>(f: F) where F: Fn(i32) {
- let mut i = 0i32;
- while i < 10 {
- f(i);
- i += 1;
+ for index in 0..10 {
+ f(index);
}
}
```
type Pair<'a> = (i32, &'a str);
-let p: Pair<'static> = (10, "hello");
+let p: Pair<'static> = (10, "ten");
let (a, b) = p;
-assert!(b != "world");
-assert!(p.0 == 10);
+
+assert_eq!(a, 10);
+assert_eq!(b, "ten");
+assert_eq!(p.0, 10);
+assert_eq!(p.1, "ten");
```
For historical reasons and convenience, the tuple type with no elements (`()`)
Rust has two different types for a list of items:
-* `[T; N]`, an 'array'.
-* `&[T]`, a 'slice'.
+* `[T; N]`, an 'array'
+* `&[T]`, a 'slice'
An array has a fixed size, and can be allocated on either the stack or the
heap.
A slice is a 'view' into an array. It doesn't own the data it points
to, it borrows it.
-An example of each kind:
+Examples:
```{rust}
-let vec: Vec<i32> = vec![1, 2, 3];
-let arr: [i32; 3] = [1, 2, 3];
-let s: &[i32] = &vec[..];
+// A stack-allocated array
+let array: [i32; 3] = [1, 2, 3];
+
+// A heap-allocated array
+let vector: Vec<i32> = vec![1, 2, 3];
+
+// A slice into an array
+let slice: &[i32] = &vector[..];
```
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
`vec!` macro is also part of the standard library, rather than the language.
-All in-bounds elements of arrays, and slices are always initialized, and access
+All in-bounds elements of arrays and slices are always initialized, and access
to an array or slice is always bounds-checked.
### Structure types
#### Function types for specific items
-Internally to the compiler, there are also function types that are specific to a particular
+Internal to the compiler, there are also function types that are specific to a particular
function item. In the following snippet, for example, the internal types of the functions
`foo` and `bar` are different, despite the fact that they have the same signature:
* `FnMut`
: The closure can be called multiple times as mutable. A closure called as
- `FnMut` can mutate values from its environment. `FnMut` implies
- `FnOnce`.
+ `FnMut` can mutate values from its environment. `FnMut` inherits from
+ `FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`).
* `Fn`
: The closure can be called multiple times through a shared reference.
A closure called as `Fn` can neither move out from nor mutate values
- from its environment. `Fn` implies `FnMut` and `FnOnce`.
+ from its environment. `Fn` inherits from `FnMut`, which itself
+ inherits from `FnOnce`.
### Trait objects
### Coercion sites
A coercion can only occur at certain coercion sites in a program; these are
-typically places where the desired type is explicit or can be dervied by
+typically places where the desired type is explicit or can be derived by
propagation from explicit types (without type inference). Possible coercion
sites are: