← Table of contents

1.2 The Names of Things

Every thing has a nature - and nature does not ask permission. A number stays a number, a string stays a string, and trying to add them together leads nowhere good, however convincing it looks on paper. The compiler knows this in advance. That, in fact, is its job.

What You Need

The Task struct has three fields with three types. In the previous chapter they were accepted without explanation. That was the right call then - and it would be a poor one to leave it that way forever.

The Material

u64 - an unsigned integer.

u means unsigned: zero and positive numbers only. 64 is the bit width: up to eighteen quintillion and change. A negative task ID makes no sense - u64 makes it impossible. Exhausting the range is not a concern either.

bool - a boolean value.

true or false. A task’s status has exactly two states - bool expresses them precisely, with nothing left over. In chapter 1.4, status will get a richer representation; for now, bool is enough.

String - a string.

A string the program creates at runtime, rather than one taken ready-made from the source code. String::from("Buy coffee") creates it from a text literal.

Type inference.

In a struct definition, types must be written explicitly: without them, the compiler does not know what shape to build. But elsewhere it can often work things out on its own. This is already happening in main.rs:

let task = Task {
    id: 1,
    title: String::from("Buy coffee"),
    status: false,
};

Nowhere is there let task: Task = .... The compiler sees the right-hand side and determines the type itself. Writing it out where it is obvious is extra work that Rust does not require.

The Result

The task has not changed. But now the apprentice knows what it is made of. The compiler knew from the start.

The complete tq code for this chapter is in 1-a-task/02-the-names-of-things/.


Lore: Integer Types

Rust has several integer types. The pattern is consistent: i means signed (can be negative), u means unsigned, the number is the bit width.

TypeRange
i32−2,147,483,648 … 2,147,483,647
u320 … 4,294,967,295
i64−9.2 × 10¹⁸ … 9.2 × 10¹⁸
u640 … 1.8 × 10¹⁹

When no type is specified and context does not help, Rust defaults to i32 - large enough for most purposes and fast on any modern platform.