Data Types

A practical tour of integers, floats, booleans, characters, tuples, and arrays — and how Rust quietly figures out most of this for you.

12 min read4 learning objectives

What You'll Learn

  • Tell the difference between scalar and compound types
  • Pick the right integer and float types without overthinking it
  • Use tuples and arrays, and know when each one fits
  • Understand why Rust asks for type annotations sometimes but not others

Rust is statically typed — every value has a known type, and that type can't change. That might sound restrictive coming from JavaScript or Python, but in practice it mostly stays out of your way: Rust can usually figure out the type from how you use a value, a trick called type inference.

You only have to spell out a type when Rust genuinely can't tell — we'll hit one of those cases in a moment. Let's go through the types you'll actually use.

Integers

An integer is a number with no fractional part. Rust has several integer types, named by how many bits they use and whether they can be negative:

SizeSigned (can be negative)Unsigned (zero or positive)
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
pointer-sizedisizeusize

That looks like a lot to memorize. Here's the shortcut: when you're not sure, use i32. It's Rust's default integer type and it's fast on basically every modern machine. You'll reach for the others in specific situations — for example, usize shows up naturally when you're indexing into collections, because that's the type Rust uses to represent "a length or a position in memory."

What about overflow? Each integer type has a maximum value — u8 tops out at 255, for instance. In a debug build, Rust panics (crashes loudly) if your math overflows one of these. In a release build, it quietly wraps around instead. Neither is usually what you want in a real calculation — it's a sign you picked a type that's too small for the job.

Floating-point numbers

For numbers with a decimal point, Rust gives you f32 and f64. Use f64 unless you have a specific reason not to — it's the default, and on modern CPUs it's just as fast as f32 while being noticeably more precise.

Notice discount as f64 — Rust won't silently convert between numeric types for you, even ones that seem obviously compatible. You have to ask for the conversion explicitly with as. It feels picky at first; it's actually Rust refusing to let a subtle bug sneak past you.

Booleans

Exactly what you'd expect: true or false, written as bool, one byte in size.

Characters

Rust's char type represents a single Unicode character — written with single quotes, which is how Rust tells a char apart from a string (double quotes). And "Unicode" is doing real work here: a Rust char is four bytes and can represent way more than ASCII letters.

🦀, by the way, is basically Rust's mascot — you'll see "Ferris the crab" all over the community. Now you know why people drop crab emojis in Rust code samples.

Tuples — group different types together

A tuple bundles multiple values, possibly of different types, into a single compound value. Once created, a tuple's length is fixed — you can't grow or shrink it.

Tuples are great for quickly grouping a handful of related values — especially for returning more than one thing from a function, which we'll do in the very next lesson.

Arrays — same type, fixed length

An array holds multiple values of the same type, and — like a tuple — its length is fixed once created. Reach for an array when you know exactly how many elements you need and that number won't change, like the months of the year.

Try changing primes[0] to primes[10] and running it — Rust will panic with an "index out of bounds" error rather than silently handing you garbage memory. That's the safety net working exactly as designed: a class of bugs that plagues C and C++ simply can't happen here.

Most of the time, though, you'll want a list that can grow — and for that, Rust has Vec<T>, which gets its own lesson later in this course.

Quick exercise

Declare a tuple representing a product: a name (&str), a price (f64), and a quantity in stock (u32). Destructure it into three variables and print a sentence describing the product using all three. Bonus: what happens if you try to print product.3?

You now know how Rust represents the basic shapes of data. Next, let's wrap logic around that data with functions.