Rust Data Types
Every value in Rust has a type — a label that tells the compiler what kind of data it is (a whole number, a decimal, text, true/false, and so on). Knowing the type lets Rust check your code for mistakes before it runs.
As you saw with variables, Rust can usually infer the type for you. But it helps to know the main types by name, because you’ll see them in error messages and function signatures.
Integers (whole numbers)
Section titled “Integers (whole numbers)”Integers are numbers without a decimal point, like 42 or -7. Rust has several integer types that differ by size and whether they allow negative numbers:
| Type | Signed? | Typical use |
|---|---|---|
i32 |
Yes (can be negative) | The default — use this unless you have a reason not to |
u32 |
No (0 and up) | Counts, sizes, things that can’t be negative |
i64 / u64 |
Yes / No | Very large numbers |
usize |
No | Indexing into collections |
fn main() { let temperature = -5; // i32 by default let count: u32 = 100; // explicitly unsigned println!("{temperature} degrees, count is {count}");}Output:
-5 degrees, count is 100Floating-point numbers (decimals)
Section titled “Floating-point numbers (decimals)”For numbers with a decimal point, use floating-point types. There are two: f64 (the default, double precision) and f32.
fn main() { let pi = 3.14159; // f64 by default let price: f32 = 9.99; println!("Pi is {pi}, price is {price}");}Output:
Pi is 3.14159, price is 9.99Stick with f64 unless you specifically need the smaller f32 — it’s more precise and just as fast on modern hardware.
Booleans
Section titled “Booleans”A boolean (bool) is the simplest type: it’s either true or false. You’ll use these constantly in if statements and conditions.
fn main() { let is_logged_in = true; let has_permission: bool = false; println!("logged in: {is_logged_in}, permission: {has_permission}");}Output:
logged in: true, permission: falseCharacters
Section titled “Characters”A char holds a single character, written with single quotes ' '. A Rust char can be any single Unicode scalar value — which covers most emoji, though a few complex ones (like flags or emoji built from multiple joined characters) don’t fit in just one.
fn main() { let letter = 'R'; let symbol = '$'; let crab = '🦀'; println!("{letter} {symbol} {crab}");}Output:
R $ 🦀Strings (text)
Section titled “Strings (text)”Text in Rust is written with double quotes. There are two string types you’ll meet:
&str— a string slice, usually text you write directly in your code (a “string literal”).String— a growable, owned piece of text you can change and build up.
fn main() { let greeting = "Hello"; // &str let mut name = String::from("Ferris"); // String name.push_str(" the crab"); // Strings can grow println!("{greeting}, {name}!");}Output:
Hello, Ferris the crab!Don’t worry about the difference between &str and String yet — it connects to ownership, which you’ll learn soon. For now: use "..." for text and reach for String when you need to build or modify it.
Type annotations
Section titled “Type annotations”Most of the time Rust infers the type. But sometimes it needs a hint — for example, when parsing text into a number (you’ll see that on the Type Casting page). You add a type with a colon:
let x: i32 = 42;let y: f64 = 3.5;let active: bool = true;Quick reference
Section titled “Quick reference”| Type | What it holds | Example |
|---|---|---|
i32 |
Whole number (default) | let n = 42; |
u32 |
Non-negative whole number | let n: u32 = 42; |
f64 |
Decimal number (default) | let pi = 3.14; |
bool |
true or false |
let ok = true; |
char |
One character | let c = 'A'; |
&str |
Text literal | let s = "hi"; |
String |
Growable text | let s = String::from("hi"); |
Practice
Section titled “Practice”1. A player profile
Section titled “1. A player profile”Describe a game character with one variable of each type: a name (&str), a level (i32), a health percentage (f64), an is_online flag (bool) and a rank letter (char). Print them all on one line. Hint: a char uses single quotes, text uses double quotes.
Show solution
fn main() { let name = "Ferris"; // &str let level = 7; // i32 let health = 82.5; // f64 let is_online = true; // bool let rank = 'A'; // char
println!("{name} | level {level} | {health}% | online: {is_online} | rank {rank}");}Output:
Ferris | level 7 | 82.5% | online: true | rank A2. Build a sentence
Section titled “2. Build a sentence”Start with String::from("Rust"), then add " is fast" and " and safe" to it, and print the result. Hint: the String must be declared with mut before push_str can change it.
Show solution
fn main() { let mut sentence = String::from("Rust"); sentence.push_str(" is fast"); sentence.push_str(" and safe"); println!("{sentence}");}Output:
Rust is fast and safe- Every value has a type; Rust usually infers it.
- Whole numbers →
i32(default). Decimals →f64(default). boolistrue/false;charis a single character in single quotes.- Text is written in double quotes:
&strfor literals,Stringfor growable text.
Quick check
Section titled “Quick check”Quick check
1. What is the default integer type in Rust if you don't specify one?
2. How does Rust distinguish a char literal from a string literal?
3. Which type is a growable, owned piece of text you can modify?
4. What is the default floating-point type in Rust?
5. Which type would let greeting = "Hello"; infer to?
Score: 0 / 5
Read more
Section titled “Read more”- Data Types — The Rust Book: every scalar type with its size and range, plus integer overflow and the compound types (tuples and arrays).
- Primitives — Rust by Example: runnable examples of each basic type, with a follow-up on literals like
1_000and0x80. i32— standard library docs: the smallest and largest values (i32::MIN,i32::MAX) and the many methods numbers have.char— standard library docs: what a Unicode scalar value is, and why acharis always 4 bytes.String— standard library docs: howStringrelates to&str, and every method for building and changing text.