DaleSchool

Data Types

Beginner15min

Learning Objectives

  • List the four basic scalar types in Rust
  • Explicitly annotate a variable's type
  • Understand the error that occurs when types don't match

Working Code

Try running this code in the Rust Playground!

fn main() {
    let age: i32 = 20;          // Integer
    let height: f64 = 175.5;    // Float
    let is_student: bool = true; // Boolean
    let grade: char = 'A';      // Character

    println!("Age: {age}");
    println!("Height: {height}cm");
    println!("Student? {is_student}");
    println!("Grade: {grade}");
}

Rust has four basic scalar types.

| Type | Example | Description | | --------- | ------- | ------------------------------------------- | | Integer | i32 | Numbers without a decimal point | | Float | f64 | Numbers with a decimal point | | Boolean | bool | true or false | | Character | char | A single character wrapped in single quotes |

You actually don't have to write the types out — Rust can figure them out on its own.

fn main() {
    let age = 20;       // Inferred as i32
    let height = 175.5; // Inferred as f64
    let is_happy = true; // Inferred as bool
    let emoji = '🦀';   // Inferred as char

    println!("{age}, {height}, {is_happy}, {emoji}");
}

Even without explicit type annotations, the Rust compiler looks at the values and determines the types. This is called type inference.

Try It Yourself

Try removing the type annotations (: i32, : f64, etc.) from the code below. Does the output change?

fn main() {
    let x: i32 = 42;
    let y: f64 = 3.14;
    let z: bool = false;

    println!("{x}, {y}, {z}");
}

You'll get the same result even without the types. Rust infers them for you. That said, writing out the types can make your code easier for others to read.

"Why?" — Why Do We Need Types?

Computers store the number 42 and the decimal 3.14 in different ways. Integers use one storage format, and floats use another. The compiler needs to know the type to store values correctly in memory and perform accurate operations.

Rust does not allow operations between different types. This helps catch unintended mistakes early.

fn main() {
    let a: i32 = 10;
    let b: f64 = 3.0;

    // This causes an error!
    // let result = a + b;

    // You need to match the types
    let result = a as f64 + b;
    println!("Result: {result}");
}

You can convert types using the as keyword. For now, just remember: "if the types differ, you need to align them."

Deep Dive

Varieties of integer types

Rust has a variety of integer types.

| Signed | Unsigned | Size | | ------ | -------- | ------ | | i8 | u8 | 8-bit | | i16 | u16 | 16-bit | | i32 | u32 | 32-bit | | i64 | u64 | 64-bit |

i types can hold negative numbers, while u types only hold zero and positive numbers. Larger sizes store a wider range of values.

For now, just remember i32 for integers and f64 for floats. You can learn the rest when you need them!

Adding an integer and a float directly causes an error.

fn main() {
    let x = 5;
    let y = 2.0;
    let sum = x + y;

    println!("{sum}");
}

Error message:

error[E0277]: cannot add `{float}` to `{integer}`
 --> src/main.rs:4:19
  |
4 |     let sum = x + y;
  |                   ^ no implementation for `{integer} + {float}`

Translation: "You can't directly add an integer and a float." Fix it with let sum = x as f64 + y; to align the types.

Some languages convert types automatically, but Rust requires you to be explicit — "convert to this type, please." This prevents bugs caused by unexpected conversions.

  1. Store the first letter of your name in a char variable and your age in an i32 variable, then print both values on one line.
  2. Create two i32 variables and print the results of addition, subtraction, multiplication, and division. (/ is division, % is the remainder operator.)

Q1. What is the default type for a number with a decimal point in Rust?

  • A) float
  • B) f32
  • C) f64
  • D) double

Q2. Will the following code run successfully?

fn main() {
    let x: i32 = 10;
    let y: f64 = 3.0;
    let z = x + y;
    println!("{z}");
}
  • A) 13.0 is printed
  • B) 13 is printed
  • C) A compile error occurs
  • D) 10 is printed

Q3. What is the type of flag in let flag = true;?

  • A) i32
  • B) string
  • C) char
  • D) bool