Question

How to Iterate Through Enum Values in Rust

rustenumsiteration

Question

I am coming from a Java background, where I might define an enum like this:

enum Direction {
    NORTH, SOUTH, EAST, WEST
}

for (Direction dir : Direction.values()) {
    // do something with dir
}

In Java, Direction.values() gives me all enum variants, and I can loop over them easily.

How can I do something similar with Rust enums? Is there a built-in way to iterate through all values of an enum, or is there a common Rust pattern for this?

Short Answer

By the end of this page, you will understand why Rust enums do not automatically provide a values() method like Java enums, and how to iterate over enum variants using common Rust patterns. You will also see practical examples, trade-offs, and how this is handled in real Rust codebases.

Concept

Rust enums and Java enums look similar at first, but they are designed differently.

In Java, enums are a special kind of class with built-in runtime support for listing all values using methods like values(). In Rust, an enum is a type that can represent one of several variants, but Rust does not automatically generate a list of all variants.

For example:

enum Direction {
    North,
    South,
    East,
    West,
}

This tells Rust that a Direction can be one of four variants. However, Rust does not keep a built-in array or registry of those variants for iteration.

Why? Because Rust enums are more general than Java enums:

  • Variants can hold data
  • Enums are often used for pattern matching, not just named constants
  • Rust prefers explicitness over hidden runtime features

That means if you want to iterate over every variant, you usually choose one of these approaches:

  • Define a constant array containing all variants
  • Implement a helper method that returns all variants
  • Use a crate such as strum to derive iteration support

This matters in real programming when you need to:

  • render all possible options in a UI
  • validate user input against allowed values
  • loop through states or directions in a game
  • test all enum variants

So the core idea is: Rust does not provide enum iteration automatically, but it is easy to add using explicit patterns.

Mental Model

Think of a Rust enum like a set of labeled cards in a box.

  • The enum definition tells you which cards are allowed.
  • But Rust does not automatically hand you a stack containing one of each card.
  • If you want to loop over them, you must prepare that stack yourself.

In Java, the language gives you the stack automatically with values(). In Rust, you usually create that stack explicitly, such as:

const ALL_DIRECTIONS: [Direction; 4] = [
    Direction::North,
    Direction::South,
    Direction::East,
    Direction::West,
];

Now you have a concrete collection to iterate over.

So the mental model is:

  • enum defines the possible choices
  • an array or helper provides the iterable list of choices
Take Quiz

Syntax and Examples

Basic pattern: define all variants in an array

A common beginner-friendly Rust approach is to store all enum variants in a constant array.

#[derive(Debug, Clone, Copy)]
enum Direction {
    North,
    South,
    East,
    West,
}

const ALL_DIRECTIONS: [Direction; 4] = [
    Direction::North,
    Direction::South,
    Direction::East,
    Direction::West,
];

fn main() {
    for dir in ALL_DIRECTIONS {
        println!("{:?}", dir);
    }
}

Why Clone and Copy?

For small enums without attached data, deriving Copy is convenient. It lets each value be copied cheaply when iterating.

Alternative: return a slice from an associated function

#[derive(Debug, Clone, Copy)]
enum Direction {
    North,
    South,
    East,
    West,
}

impl Direction {
    fn all() -> &'static [Direction] {
        &[
            Direction::North,
            Direction::South,
            Direction::East,
            Direction::West,
        ]
    }
}

fn main() {
    for dir in Direction::all() {
        println!("{:?}", dir);
    }
}

This feels a bit more like Java's Direction.values() because the list is attached to the enum type.

Using strum for automatic iteration

In real projects, many Rust developers use the strum crate.

use strum::IntoEnumIterator;
use strum_macros::EnumIter;

#[derive(Debug, EnumIter)]
enum Direction {
    North,
    South,
    East,
    West,
}

fn main() {
    for dir in Direction::iter() {
        println!("{:?}", dir);
    }
}

This is very convenient, especially when the enum has many variants.

When to use each approach

  • Array or slice: simple, no dependencies, great for small projects
  • Associated function: clearer API, keeps the list near the enum
  • strum: best when you want less manual maintenance and do not mind adding a crate

Step by Step Execution

Consider this example:

#[derive(Debug, Clone, Copy)]
enum Direction {
    North,
    South,
    East,
    West,
}

const ALL_DIRECTIONS: [Direction; 4] = [
    Direction::North,
    Direction::South,
    Direction::East,
    Direction::West,
];

fn main() {
    for dir in ALL_DIRECTIONS {
        println!("Moving {:?}", dir);
    }
}

Here is what happens step by step:

  1. enum Direction defines four possible values.
  2. ALL_DIRECTIONS creates an array containing one of each variant.
  3. main() starts running.
  4. The for loop takes each item from ALL_DIRECTIONS one at a time.
  5. On the first iteration, dir is Direction::North.
  6. println! prints Moving North.
  7. The loop repeats for South, East, and West.
  8. After the last element, the loop ends.

Expected output:

Moving North
Moving South
Moving East
Moving West

The important point is that the loop is not reading the enum definition directly. It is iterating over the array you created.

Real World Use Cases

Iterating through enum variants is useful in many practical situations.

Building menu options

If your app has a list of available modes:

enum Theme {
    Light,
    Dark,
    System,
}

You might loop through all themes to render a settings menu.

Game movement or state logic

A game may use directions such as North, South, East, and West to test possible moves.

Validation and parsing

You may want to compare user input against all allowed enum values and display valid options.

Testing all variants

When writing tests, iterating over all enum variants helps verify that every option behaves correctly.

Data export or reporting

If an enum represents categories, statuses, or roles, iterating over all variants can help generate reports or summaries.

Take Quiz

Real Codebase Usage

In real Rust projects, developers usually use enum iteration in a few common patterns.

Configuration and option lists

An enum may represent a fixed set of supported values, such as log levels, themes, regions, or output formats. A helper like all() is often used to populate dropdowns, CLI help text, or config validation.

Validation

A request parser may convert strings into enum variants. If parsing fails, code can iterate through all valid values to build a useful error message.

Tests

Developers often iterate through every variant in tests to avoid missing edge cases.

#[test]
fn all_directions_have_labels() {
    for dir in Direction::all() {
        let label = match dir {
            Direction::North => "North",
            Direction::South => "South",
            Direction::East => "East",
            Direction::West => "West",
        };
        assert!(!label.is_empty());
    }
}

Guarded APIs

Sometimes a public API exposes Direction::all() so other parts of the codebase have one consistent source of truth.

Crate-based derive patterns

In larger codebases, using strum is common because it reduces the risk of forgetting to update a manual array when a new enum variant is added.

Common Mistakes

Mistake 1: expecting a built-in values() method

This does not exist in Rust:

for dir in Direction::values() {
    println!("{:?}", dir);
}

Fix

Create your own list of variants or use a crate like strum.

Mistake 2: forgetting to keep the manual list updated

Broken design:

#[derive(Debug, Clone, Copy)]
enum Direction {
    North,
    South,
    East,
    West,
    Up,
}

const ALL_DIRECTIONS: [Direction; 4] = [
    Direction::North,
    Direction::South,
    Direction::East,
    Direction::West,
];

Here, Up exists in the enum but is missing from the array.

Fix

Whenever you add a variant, update the array or use strum to avoid manual duplication.

Mistake 3: trying to iterate enums with data as if they were simple fixed values

enum Message {
    Quit,
    Move(i32, i32),
    Write(String),
}

This enum cannot be meaningfully auto-iterated because some variants require values.

Fix

Only use iteration patterns when the enum represents a finite list of concrete variants, or define a custom list of representative values.

Mistake 4: borrowing confusion in loops

If you return a slice:

for dir in Direction::all() {
    println!("{:?}", dir);
}

Then dir is usually a reference like &Direction.

Fix

Match the type you are iterating over. If needed:

for &dir in Direction::all() {
    println!("{:?}", dir);
}

Or derive Copy and use methods that copy values where appropriate.

Mistake 5: using integers to fake enum iteration

Some beginners try to cast integers to enum variants. That is unsafe design unless carefully controlled.

Fix

Prefer explicit arrays, helper methods, or derive macros.

Comparisons

ApproachHow it worksProsCons
Manual array constantStore all variants in a constant arraySimple, no dependencies, easy to understandMust be updated manually
all() associated functionReturn a slice or array from the enum implClean API, keeps logic near enumStill manual
strum with EnumIterDerive iteration support using a crateConvenient, less repetitionAdds dependency

Rust enums vs Java enums

FeatureJava enumRust enum
Built-in list of valuesYes, values()No built-in values()
Variants with attached dataLimited compared to RustYes, very common
Typical useNamed constants with class-like featuresAlgebraic data types and pattern matching
Iteration supportAutomaticManual or crate-based

Array vs slice return

PatternExampleGood when
Constant arrayconst ALL: [Direction; 4]You want simple direct iteration
Slice from functionfn all() -> &'static [Direction]You want a nicer API attached to the enum
Take Quiz

Cheat Sheet

#[derive(Debug, Clone, Copy)]
enum Direction {
    North,
    South,
    East,
    West,
}

const ALL_DIRECTIONS: [Direction; 4] = [
    Direction::North,
    Direction::South,
    Direction::East,
    Direction::West,
];

for dir in ALL_DIRECTIONS {
    println!("{:?}", dir);
}

Quick rules

  • Rust enums do not have a built-in values() method.
  • To iterate variants, define a manual list or use a crate.
  • Copy is useful for small enums without data.
  • If variants contain data, full iteration may not make sense.
  • strum is a popular crate for EnumIter.

Handy pattern

impl Direction {
    fn all() -> &'static [Direction] {
        &[
            Direction::North,
            Direction::South,
            Direction::East,
            Direction::West,
        ]
    }
}

With strum

use strum::IntoEnumIterator;
use strum_macros::EnumIter;

#[derive(EnumIter)]
enum Direction {
    North,
    South,
    East,
    West,
}

for dir in Direction::iter() {
    // use dir
}

Edge case

This enum is not naturally iterable over all possible values:

enum Message {
    Quit,
    Move(i32, i32),
}

Because Move(i32, i32) can have many possible values.

FAQ

Is there a built-in values() function for Rust enums?

No. Rust does not automatically generate a values() method for enums.

What is the simplest way to iterate over enum variants in Rust?

Create a constant array containing all variants and loop over it.

Can I make Rust enums behave more like Java enums?

Yes. A common pattern is to add an all() method that returns a slice of all variants.

What crate is commonly used for enum iteration in Rust?

strum is a popular crate. It can derive iteration support with EnumIter.

Does enum iteration work for enums with data fields?

Not automatically in a general way. Variants with fields can represent many possible values.

Should I use a manual array or a crate?

Use a manual array for small, simple projects. Use a crate if you want less boilerplate or have many enums.

Why does Rust not provide this automatically?

Because Rust enums are more flexible than simple named constants, and Rust generally prefers explicit patterns over hidden runtime behavior.

Take Quiz

Mini Project

Description

Build a small command-line helper that lists all possible movement directions and prints a short instruction for each one. This demonstrates how to define an enum, create a manual iterable list of variants, and process each variant in a loop.

Goal

Create a Rust program that iterates through every Direction variant and prints a human-readable message for each one.

Requirements

  • Define a Direction enum with North, South, East, and West.
  • Create a reusable way to access all enum variants.
  • Loop through every direction and print a message.
  • Use match to generate a different message for each direction.
Take Quiz

Keep learning

Related questions

View more