Skip to Content

Match

match tests one value against a sequence of patterns and runs whichever arm matches. It is both an expression and a statement, and the two forms share the same matching machinery and exhaustiveness checking. Every pattern form is on the Pattern page.

Basic Form

An arm has the shape pattern => body; arms are separated by commas, and a trailing comma on the last arm is optional. The body can be an expression, a block, or control flow starting with return / fail:

enum Shape { Circle(radius: float), Rect(w: float, h: float), Point, } func Area(s: Shape) -> float { return match s { Shape.Circle(r) => 3.14159 * r * r, Shape.Rect(w, h) => w * h, Shape.Point => 0.0, }; } print(Area(Shape.Circle(2.0)), Area(Shape.Rect(3.0, 4.0)), Area(Shape.Point));
12.56636 12 0

Shape.Circle(r) both tests the variant and deconstructs the payload into r.

when Guards

An arm can be followed by when condition for a second filter; the condition must produce a bool. Guards do not count toward exhaustive coverage:

func Describe(n: int) -> string { return match n { 0 => "zero", x when x < 0 => "negative", x when x < 10 => "single digit", _ => "two digits or more", }; } print(Describe(-5), Describe(0), Describe(7), Describe(42));
negative zero single digit two digits or more

When a guarded arm matches, bindings from the arm-head pattern (here x) are available in the arm body.

Exhaustiveness Checking

match enforces exhaustiveness: every possible value must be handled by some arm, and a missing one raises MS4001, listing the uncovered cases. Guards and list patterns do not count as coverage; fall back to _:

error MS4001: match is not exhaustive: uncovered case(s) Point.

A match statement gets the same exhaustiveness check; nobody consuming the result does not wave it through.

Arm Types Must Unify

In a match expression, all arm types must unify into one; mixing them raises MS3254:

error MS3254: match arm body types do not unify: 'string' vs 'int32'.

When you need differently shaped results, make every arm produce the same type, such as string or tuple.

match as a Statement

Use the statement form when nobody consumes the result; arm bodies are usually side effects. The comma rules between arms are unchanged:

val n = 2; match n { 1 => print("one"), 2 => print("two"), _ => print("many"), }
two

Notes

  • Matching on error values shares one exhaustiveness accounting with recover consumption; see Failure and Crash;
  • When the branch logic is flat (just comparing sizes), an if expression is lighter; reach for match when structure needs to be taken apart.
Last updated on October 11, 2026