3 The Rust language has a number of types that are considered ‘primitive’. This
4 means that they’re built-in to the language. Rust is structured in such a way
5 that the standard library also provides a number of useful types built on top
6 of these ones, as well, but these are the most primitive.
10 Rust has a built-in boolean type, named `bool`. It has two values, `true` and `false`:
18 A common use of booleans is in [`if` conditionals][if].
22 You can find more documentation for `bool`s [in the standard library
25 [bool]: ../std/primitive.bool.html
29 The `char` type represents a single Unicode scalar value. You can create `char`s
30 with a single tick: (`'`)
37 Unlike some other languages, this means that Rust’s `char` is not a single byte,
40 You can find more documentation for `char`s [in the standard library
43 [char]: ../std/primitive.char.html
47 Rust has a variety of numeric types in a few categories: signed and unsigned,
48 fixed and variable, floating-point and integer.
50 These types consist of two parts: the category, and the size. For example,
51 `u16` is an unsigned type with sixteen bits of size. More bits lets you have
54 If a number literal has nothing to cause its type to be inferred, it defaults:
57 let x = 42; // `x` has type `i32`.
59 let y = 1.0; // `y` has type `f64`.
62 Here’s a list of the different numeric types, with links to their documentation
63 in the standard library:
65 * [i8](../std/primitive.i8.html)
66 * [i16](../std/primitive.i16.html)
67 * [i32](../std/primitive.i32.html)
68 * [i64](../std/primitive.i64.html)
69 * [u8](../std/primitive.u8.html)
70 * [u16](../std/primitive.u16.html)
71 * [u32](../std/primitive.u32.html)
72 * [u64](../std/primitive.u64.html)
73 * [isize](../std/primitive.isize.html)
74 * [usize](../std/primitive.usize.html)
75 * [f32](../std/primitive.f32.html)
76 * [f64](../std/primitive.f64.html)
78 Let’s go over them by category:
80 ## Signed and Unsigned
82 Integer types come in two varieties: signed and unsigned. To understand the
83 difference, let’s consider a number with four bits of size. A signed, four-bit
84 number would let you store numbers from `-8` to `+7`. Signed numbers use
85 “two’s complement representation”. An unsigned four bit number, since it does
86 not need to store negatives, can store values from `0` to `+15`.
88 Unsigned types use a `u` for their category, and signed types use `i`. The `i`
89 is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an
90 eight-bit signed number.
94 Fixed-size types have a specific number of bits in their representation. Valid
95 bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer,
96 and `i64` is a signed, 64-bit integer.
98 ## Variable-size types
100 Rust also provides types whose particular size depends on the underlying machine
101 architecture. Their range is sufficient to express the size of any collection, so
102 these types have ‘size’ as the category. They come in signed and unsigned varieties
103 which account for two types: `isize` and `usize`.
105 ## Floating-point types
107 Rust also has two floating point types: `f32` and `f64`. These correspond to
108 IEEE-754 single and double precision numbers.
112 Like many programming languages, Rust has list types to represent a sequence of
113 things. The most basic is the *array*, a fixed-size list of elements of the
114 same type. By default, arrays are immutable.
117 let a = [1, 2, 3]; // a: [i32; 3]
118 let mut m = [1, 2, 3]; // m: [i32; 3]
121 Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics
122 section][generics]. The `N` is a compile-time constant, for the length of the
125 There’s a shorthand for initializing each element of an array to the same
126 value. In this example, each element of `a` will be initialized to `0`:
129 let a = [0; 20]; // a: [i32; 20]
132 You can get the number of elements in an array `a` with `a.len()`:
137 println!("a has {} elements", a.len());
140 You can access a particular element of an array with *subscript notation*:
143 let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
145 println!("The second name is: {}", names[1]);
148 Subscripts start at zero, like in most programming languages, so the first name
149 is `names[0]` and the second name is `names[1]`. The above example prints
150 `The second name is: Brian`. If you try to use a subscript that is not in the
151 array, you will get an error: array access is bounds-checked at run-time. Such
152 errant access is the source of many bugs in other systems programming
155 You can find more documentation for `array`s [in the standard library
156 documentation][array].
158 [array]: ../std/primitive.array.html
162 A ‘slice’ is a reference to (or “view” into) another data structure. They are
163 useful for allowing safe, efficient access to a portion of an array without
164 copying. For example, you might want to reference only one line of a file read
165 into memory. By nature, a slice is not created directly, but from an existing
166 variable binding. Slices have a defined length, and can be mutable or immutable.
168 Internally, slices are represented as a pointer to the beginning of the data
173 You can use a combo of `&` and `[]` to create a slice from various things. The
174 `&` indicates that slices are similar to [references], which we will cover in
175 detail later in this section. The `[]`s, with a range, let you define the
179 let a = [0, 1, 2, 3, 4];
180 let complete = &a[..]; // A slice containing all of the elements in `a`.
181 let middle = &a[1..4]; // A slice of `a`: only the elements `1`, `2`, and `3`.
184 Slices have type `&[T]`. We’ll talk about that `T` when we cover
185 [generics][generics].
187 [generics]: generics.html
189 You can find more documentation for slices [in the standard library
190 documentation][slice].
192 [slice]: ../std/primitive.slice.html
196 Rust’s `str` type is the most primitive string type. As an [unsized type][dst],
197 it’s not very useful by itself, but becomes useful when placed behind a
198 reference, like `&str`. We'll elaborate further when we cover
199 [Strings][strings] and [references].
201 [dst]: unsized-types.html
202 [strings]: strings.html
203 [references]: references-and-borrowing.html
205 You can find more documentation for `str` [in the standard library
208 [str]: ../std/primitive.str.html
212 A tuple is an ordered list of fixed size. Like this:
215 let x = (1, "hello");
218 The parentheses and commas form this two-length tuple. Here’s the same code, but
219 with the type annotated:
222 let x: (i32, &str) = (1, "hello");
225 As you can see, the type of a tuple looks like the tuple, but with each
226 position having a type name rather than the value. Careful readers will also
227 note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
228 In systems programming languages, strings are a bit more complex than in other
229 languages. For now, read `&str` as a *string slice*, and we’ll learn more
232 You can assign one tuple into another, if they have the same contained types
233 and [arity]. Tuples have the same arity when they have the same length.
235 [arity]: glossary.html#arity
238 let mut x = (1, 2); // x: (i32, i32)
239 let y = (2, 3); // y: (i32, i32)
244 You can access the fields in a tuple through a *destructuring let*. Here’s
248 let (x, y, z) = (1, 2, 3);
250 println!("x is {}", x);
253 Remember [before][let] when I said the left-hand side of a `let` statement was more
254 powerful than assigning a binding? Here we are. We can put a pattern on
255 the left-hand side of the `let`, and if it matches up to the right-hand side,
256 we can assign multiple bindings at once. In this case, `let` “destructures”
257 or “breaks up” the tuple, and assigns the bits to three bindings.
259 [let]: variable-bindings.html
261 This pattern is very powerful, and we’ll see it repeated more later.
263 You can disambiguate a single-element tuple from a value in parentheses with a
267 (0,); // A single-element tuple.
268 (0); // A zero in parentheses.
273 You can also access fields of a tuple with indexing syntax:
277 let tuple = (1, 2, 3);
283 println!("x is {}", x);
286 Like array indexing, it starts at zero, but unlike array indexing, it uses a
287 `.`, rather than `[]`s.
289 You can find more documentation for tuples [in the standard library
290 documentation][tuple].
292 [tuple]: ../std/primitive.tuple.html
296 Functions also have a type! They look like this:
299 fn foo(x: i32) -> i32 { x }
301 let x: fn(i32) -> i32 = foo;
304 In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and