W# 0.1.1

Errors

What an error set is, how it is inferred, and what panics instead.

An error value

error.Name makes one. The name is not declared anywhere: writing return error.NotFound; is what brings NotFound into existence, and the set it belongs to is worked out from where it is raised.

The type carries the set

!T is a T or an error, and which errors it may be is part of the type:

fn risky(n: i64) !i64 {            // fn(i64) !{Negative, Zero}i64
    if (n < 0) { return error.Negative; }
    if (n == 0) { return error.Zero; }
    return n;
}

The set is the union of what the function raises directly and what it propagates with try. Nothing caps how many errors a set may name.

Written down, it is checked:

fn risky(n: i64) !{Negative, Zero}i64 { ... }   // exactly these
fn risky(n: i64) !{Negative}i64 { ... }         // error: Zero escapes

Raising an error outside a declared set is a compile error, which is what makes the declaration worth writing.

Because the set is in the type, the e bound by catch |e| is worth testing:

const v = risky(n) catch |e| if (e == error.Negative) 0 else -1;

Handling

try f()the payload, or return this error from the current function
f() catch vthe payload, or v
f() catch |e| exprthe payload, or expr with the error bound
f() catch return falsecatch takes any expression, including return
f() catch { log(); 0 }including a block, whose last expression is its value

try propagates, so a function using it has to be fallible itself.

Coercion

A plain value coerces into an error union when the context wants one, so return n; is legal in a function declared !i64. There is no constructor to write.

What panics instead

W# separates errors, which the type system makes you handle, from failures the type system permits but the program must not perform. The second kind prints W# panic: <reason> to stderr and exits 101:

Arithmetic overflow is not one of them. +, - and * wrap.

A container written in W# can raise the same out-of-bounds panic that a[i] does, by calling the prelude’s panic_index(i, len), so a bad index into a list.List[T] reports exactly as a bad index into an array.

Two other compile-time checks in the same family

A function that can reach the end of its body without returning a value is a compile error, not a function returning something unspecified.

An ambiguous pair of overloads is a compile error at the call site. See dispatch.

Last changed 8 September 2026. Improve this page

On this page