Primitive types

See also: List of primitive types in the standard library documentation

Primitive types are types that are built into the language. Most other types are composed of these primitive types. Primitive types have special syntax – for example, numbers can be created with number literals.

Numeric typesEdit

Numeric types are integers (whole numbers) and floating-point numbers. Unsigned integers can never be negative. Signed integers can be negative and are represented as Two's complement.

The floating-point numbers implement the binary32 and binary64 formats specified in IEEE 754. This means that they are represented as a sign bit, an exponent and a fraction. They can be NaN ("not a number") and (–)Infinity. Because NaN is specified to not be equal to itself, floating-point numbers implement the PartialEq  trait, but not Eq .

Type Size Minimum real number Maximum real number Precision
Unsigned integers u8  1 byte 0 28 – 1 = 255 whole numbers
u16  2 bytes 0 216 – 1 = 65,535
u32  4 bytes 0 232 – 1 = 4,294,967,295
u64  8 bytes 0 264 – 1 ≈ 1.845 × 1019
u128  16 bytes 0 2128 – 1 ≈ 3.403 × 1038
usize  Same as a pointer 0 Platform dependent
Signed integers i8  1 byte –27 = –128 27 – 1 = 127
i16  2 bytes –215 = –32,768 215 – 1 = 32,767
i32  4 bytes –231 = –2,147,483,648 231 – 1 = 2,147,483,647
i64  8 bytes –263 ≈ –9.223 × 1018 263 – 1 ≈ 9.223 × 1018
i128  16 bytes –2127 ≈ –1.701 × 1038 2127 – 1 ≈ 1.701 × 1038
isize  Same as a pointer Platform dependent Platform dependent
Floating-point numbers f32  4 bytes –(2 – 2–23) × 2127 ≈ –3.403 × 1038 (2 – 2–23) × 2127 ≈ 3.403 × 1038 6 to 9 significant decimal digits
f64  8 bytes –(2 – 2–52) × 21023 ≈ –1.798 × 10308 (2 – 2–52) × 21023 ≈ 1.798 × 10308 15 to 17 significant decimal digits

Number literalsEdit

There are two types of number literals, {integer} and {float}; the compiler tries to infer one of the integer types for {integer} literals and f32 or f64 for {float} literals. If the type can't be inferred, {integer} defaults to i32 and {float} defaults to f64. It is possible to explicitly specify the type with a suffix, e.g. 4u8, 0_u32.

A number literal can contain any number of underscores (_), as long as it doesn't start with an underscore, and the decimal point isn't immediately followed by an underscore.

Syntactically, the sign is not part of the literal. However, Rust checks if the literal is preceded by a sign, so -(128_i8) compiles, even though 128_i8 * (-1) and -{ 128_u8 } does not.

{float} literals must contain a decimal point (e.g. 1.5 or 1.) or an exponent (e.g. (1e2 or 1.5e-2), or must have a f32 or f64 suffix (e.g. 1f32).

{integer} literals can be specified in different formats. The default format is decimal. Hexadecimal literals start with 0x, octal literals start with 0o, binary literals with 0b. The prefix can't contain underscores.

Number literals with a type suffix can be immediately followed by a dot and a method call. For example, 7u8.count_ones() and 7.5f32.abs() work.

For u8 exists a special kind of literal, the byte literal, which is a char literal prefixed with b, e.g. b'a'. The character must be in the range 0..=255. Even though it looks like a character, its type is u8.

boolThis links to official Rust documentationEdit

A value that can be true or false. true is represented as 1, false is represented as 0. This type is used for boolean logic. For example if and while expressions as well as the &&, || and ! operators operate on bool values.

Truth tablesEdit

NOT (!)
a !a
true false
false true
AND (&&)
a b a && b
true true true
true false false
false true false
false false false
OR (||)
a b a || b
true true true
true false true
false true true
false false false

Note: The red values are not evaluated because of short-circuiting.

charThis links to official Rust documentationEdit

char is a character of text, or more precisely, a Unicode scalar value. This is similar to, but not the same as a Unicode code point, because a char may never contain a high-surrogate or low-surrogate code point. char has a size of 4 bytes.

Note that some chars aren't visible characters, and what looks like a single character, can consist of multiple chars.

char literalsEdit

char literals are chars surrounded by single quotes (''). They may contain the following escape sequences:

  • Quotes: \' and \"
  • ASCII escapes:
    • \0 (null, U+0000)
    • \t (horizontal tab, U+0009)
    • \n (line feed, U+000A)
    • \r (carriage return, U+000D)
    • \\ (backslash, U+005C)
    • \x followed by an octal digit and a hexadecimal digit, e.g '\x41' == 'A'
  • Unicode escapes: \u{ ... }. Between the braces go 1 to 6 hexadecimal digits. Underscore are allowed as well, e.g. '\u{1E_07}' == 'ḇ'

strThis links to official Rust documentationEdit

A chunk of UTF-8 encoded text. Because the text can have any length, this is a dynamically-sized type.

str is not the same as [char]. While a char is always 4 bytes wide, characters in a str have a variable width between 1 and 4 bytes. Lower code points, like ASCII, have a more compact representation than higher code points, such as Chinese characters or emojis.

Because of this, chars in a string can't be indexed in constant time. Furthermore, the str::len()  method returns the length in bytes, not in characters.

String literalsEdit

String literals have the type &'static str. They have the 'static lifetime, because they are included in the .text section of the executable, so they are always alive.

String literals are written in double quotes (""). They can have the same escape sequences as char literals. Furthermore, a backslash (\) at the end of the line can be used to remove the line break as well as all subsequent whitespace characters:

assert_eq!("Hello \
    world", "Hello world");


Raw string literalsEdit

In raw string literals, escape sequences are ignored. Raw string literals are prefixed with an r, and can be enclosed with an arbitrary number of number signs (#). The number of number signs before and after the string must be equal:

r###"This is a "raw" string literal!"###

See alsoEdit

Function pointer (fnThis links to official Rust documentation)Edit

A type that points to a function:

fn foo(a: i32) -> i32 {
    a * 3
}

let f: fn(i32) -> i32 = foo;
println!("{}", f(42));


Unlike closures, function pointers can't access their surrounding context, so it's often better to use Box<dyn Fn()> or a generic impl Fn() instead of fn().

Tuple (tupleThis links to official Rust documentation, unitThis links to official Rust documentation)Edit

Main article: Tuple

A tuple is a fixed length sequence of values, which may or may not be different types.

let tuple: (bool, i32, &str) = (true, 42, "Hello");


A unit type is the empty tuple (). It is the type of statements and the implied type of functions that don't specify a return type. Since it has only one possible value, it is zero-sized:

fn foo() {}

fn bar() -> () {
    let _: () = foo();
}


arrayThis links to official Rust documentation, sliceThis links to official Rust documentationEdit

Main article: Arrays and slices

Arrays ([T; N]) and slices ([T]) are consecutive sequences of values of the same type. While arrays have a fixed size known at compile time, slices are dynamically sized and can only be used behind a reference or pointer-like type:

let array: [i32; 5] = [1, 1, 2, 3, 5];
let slice: &[i32] = &array[..];


Pointer, referenceEdit

See also: Reference

Never (!)Edit

Main article: Never