# Primitive types

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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 types

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 literals

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`.

## `bool`

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 tables

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

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

## `char`

`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 `char`s aren't visible characters, and what looks like a single character, can consist of multiple `char`s.

### `char` literals

`char` literals are `char`s 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}' == 'ḇ'`

## `str`

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, `char`s in a string can't be indexed in constant time. Furthermore, the `str::len()` method returns the length in bytes, not in characters.

### String literals

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 literals

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!"###
```

## Function pointer (`fn`)

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 (`tuple`, `unit`)

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();
}
```

## `array`, `slice`

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[..];
```