Course contentsShow
← Rust
Lesson 494 of 1,9105. Type System and TraitsFree lesson

The Unit Type and Empty Tuples

Understand the role of the unit type in expressions and return values.

In this lesson, you will learn how the unit type () acts as the invisible "do-nothing" value that satisfies Rust’s strict requirements for expressions and return types.

The Role of ()

In Rust, every expression must have a value. Even if a function doesn't seem to return anything meaningful—like a function that prints to the console or modifies a piece of state—it still has to return something.

This is where the unit type, written as (), comes in. It is a special type that has exactly one possible value: (). Because it only has one possible state, the compiler treats it as essentially "empty." It carries no information and takes up zero bytes in memory.

When do you see it?

You see the unit type most often as the implicit return value of a function. If you omit a return type in a function definition, Rust assumes you mean -> ().

fn say_hello() {
    println!("Hello!");
    // Implicitly returns ()
}

You can think of () as Rust’s way of saying, "This expression completes successfully, but there is no meaningful data to return."

The Empty Tuple

Syntactically, the unit type is the empty tuple. A tuple with one element is (T,), and a tuple with two is (T, U). Following that logic, a tuple with zero elements is (). While it acts like a type that holds no data, it satisfies the type system's need for a concrete result.

This is extremely useful when using generics or trait implementations. For instance, if you have a HashMap<String, ()>, you are effectively building a HashSet. You don't care about the value associated with the key, but the HashMap requires a value type to exist, so you provide () to act as a placeholder.

By using the unit type, Rust keeps its type system consistent: every expression evaluates to a type, and () allows functions to finish without needing to invent "dummy" data.

Key Takeaway: The unit type () is the canonical way to represent the absence of a value, ensuring every expression evaluates to something while occupying zero memory at runtime.