Does this error message mean I can use pattern matching in for loops?

Yes, you can use patterns in many places, but not all of them allow you to conditionally branch when there are multiple possible patterns.

A for loop is one place where you cannot add conditions. That's what the error is telling you with "refutable pattern": there's a pattern that will not be handled. Instead, you mostly use the pattern to perform destructuring of the loop variable:

struct Thing {
    foo: u8,
}

fn main() {
    let things = vec![Thing { foo: 1 }, Thing { foo: 2 }, Thing { foo: 3 }];
    for Thing { foo } in things {
        println!("{}", foo);
    }
}

Conditional:

  • match
  • if let
  • while let

Unconditional:

  • for
  • let
  • function parameters

You can use patterns as the binding in a for loop, but not refutable patterns. The difference between refutable and irrefutable patterns is described here, but the gist of it is, if a pattern could fail, you can't use it in a let statement, a for loop, the parameter of a function or closure, or other places where the syntax specifically requires an irrefutable pattern.

An example of an irrefutable pattern being used in a for loop might be something like this:

let mut numbers = HashMap::new();
numbers.insert("one", 1);
numbers.insert("two", 2);
numbers.insert("three", 3);

for (name, number) in &numbers {
    println!("{}: {}", name, number);
}

(name, number) is an irrefutable pattern, because any place where it type checks, it will match. It type checks here because the items being iterated over (defined by the implementation of IntoIterator for &HashMap) are tuples. You could also write the above as

for tuple in &numbers {
    let (name, number) = tuple;
    println!("{}: {}", name, number);
}

because let is another place where only irrefutable patterns are allowed.

Tags:

Rust