Skip to content

Control Flow And Patterns

Chris Michael edited this page Sep 2, 2026 · 3 revisions

Pudu

Control Flow And Patterns

if let Some(value) = current {
  value
} else {
  0
}

Status: all forms on this page are parsed, checked, formatted, and interpreted.

if and if let

if requires Bool. Reachable branch values unify.

if let PATTERN = EXPRESSION evaluates its subject once. Successful bindings exist only in the then block. An irrefutable pattern is E1056, because ordinary let states an unconditional binding directly.

let … else

let Some(name) = selected else { return Err("missing name") }
use(name)

The fallback must diverge—it must return, break, continue, panic, or otherwise not reach the code after the binding. Successful bindings remain in scope for the rest of the containing block.

match

match result {
  case Ok(value) => value
  case Err(reason) => { return Err(reason) }
}

The scrutinee is evaluated once. Arms are tested top-to-bottom. Guards run only after structural pattern success. Closed sums and booleans are checked for exhaustiveness; unreachable arms produce warnings. A guarded arm does not prove coverage.

Patterns include wildcards, bindings, literals, ranges, tuples, records, variants, and alternatives. Match arms may also carry guards. Binder-carrying alternatives are not usable correctly: repeated binders fail in resolution, while different binders violate the language rule and may pass checking. Pattern Language records the defect.

Loops

for item in items { consume(item) }

while condition { step() }

while let Some(item) = next() { consume(item) }

let answer = loop {
  if ready() { break 42 }
}

for binds the element type of its iterable. while let re-evaluates the subject before every iteration and stops at the first failed match. Its bindings exist only inside the body.

while and for produce unit. loop can produce the common type carried by break; a loop no break leaves has type Never. Labels select an outer loop for break or continue.

Divergence

return, break, and continue have type Never at a valid boundary. A block ending directly in one preserves Never, so an arm that returns can join an arm that produces an ordinary value.

Related

Clone this wiki locally