Skip to content

Patterns

Bind, ignore, destructure, qualify, combine, and constrain value shapes.

Updated View as Markdown

A pattern describes a value shape and the names to bind from it. The same pattern language appears in bindings, loops, conditional patterns, and match arms.

Wildcards

_ matches any value without creating a binding.

for _ in 0..3 {
    retry()
}

Use a wildcard when a value is intentionally ignored or when it completes an otherwise open-ended match.

Bindings

A fresh identifier matches any value and binds that value to the name.

match result {
    Some(value) => consume(value)
    None => use_default()
}

Whether an identifier is a new binding or a visible constant is resolved by the compiler. Constants in pattern position match their folded value.

Literals

Boolean, numeric, character, and string literals match equal values.

match command {
    "start" => start()
    "stop" => stop()
    _ => unknown()
}

Floating-point patterns should be avoided where rounding makes exact equality an unstable domain rule.

Tuples

Tuple patterns match arity and destructure positions.

(host, port) := endpoint

The outer parentheses may be omitted in binding and iteration positions where the comma is unambiguous.

for key, value in entries {
    store(key, value)
}

Structs

Struct patterns name the fields to inspect.

Point { x, y } := point

Rename a field by supplying a subpattern.

User { id: user_id, name } := user

.. ignores fields that are not explicitly listed.

Request { method, path, .. } := request

Anonymous record patterns are structural; nominal struct patterns also check the owning type.

Variants

Enum, Option, Result, and declared error variants use constructor-shaped patterns.

match result {
    Ok(value) => consume(value)
    Err(error) => report(error)
}

Tuple-style variants bind positional payloads. Struct-style variants bind named fields. Unit variants have no payload.

Qualify a variant when a bare name is ambiguous.

match state {
    NetworkState.Ready => connect()
    StorageState.Ready => load()
}

The checker uses the subject’s expected type to resolve unambiguous bare variants.

Slices

Slice patterns match sequence elements.

match values {
    [] => empty()
    [only] => one(only)
    [head, ..tail] => many(head, tail)
}

A rest pattern absorbs the remaining elements. The current parser supports a bare .. and a named rest binding.

Ranges

Inclusive and exclusive range patterns match values inside their endpoints.

match digit {
    0..=9 => decimal()
    _ => invalid()
}

Range endpoints must be valid compile-time pattern values of a compatible ordered type.

Bound patterns

name @ subpattern binds the whole matched value while also requiring the subpattern.

match value {
    digit @ 0..=9 => use_digit(digit)
    _ => reject()
}

This avoids reconstructing a value from its parts merely to retain the original.

Alternatives

left | right matches either alternative.

match event {
    Created(id) | Updated(id) => refresh(id)
    Deleted(id) => remove(id)
}

Every alternative must bind the same names with compatible types. Otherwise the arm body would not have a consistent environment.

Refutability

An irrefutable pattern is guaranteed to match its input type, such as a plain binding or complete tuple destructure. A refutable pattern can fail, such as a variant, literal, range, or constrained slice.

Use refutable patterns only where failure has defined control flow:

  • an if pattern condition;
  • a for pattern := expression loop;
  • a match arm;
  • a binding followed by a diverging else.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close