Errors
A function that can fail returns a union T | E1 | E2. Error types are declared with @error: such a value cannot be ignored
silently. fail e returns an error, expr? passes it to the caller, match takes it apart by type.
@error data NotFound { id: i64 }
@error data Invalid { why: str }
fn find(id: i64) -> str | NotFound {
if id == 1 { return "ann" }
fail NotFound{ id }
}
fn parse(s: str) -> i64 | Invalid {
match s.parseInt() {
i64 n => n
ParseError => fail Invalid{ why: "not a number: {s}" }
}
}
fn lookup(s: str) -> str | NotFound | Invalid {
let id = parse(s)?
find(id)?
}
fn main() io {
for s in ["1", "2", "x"] {
match lookup(s) {
str name => print("found {name}")
NotFound e => print("no user {e.id}")
Invalid e => print("bad input: {e.why}")
}
}
let r = await find(2)
-> it.len()
!> NotFound => 0
print("{r}")
}Output
found ann no user 2 bad input: not a number: x 0
- If a
matchdoes not list a possible error, the compiler reports it (unhandled-error). - Network calls add
NetErrorto the result (§6.5):Timeout,Unavailableand others. - Panics (
panic, overflow, out-of-range index) are not errors: they mean a bug and end the task (§6.6). mainmay return errors:fn main() -> () | Usage | IoError io; an unhandled error ends the process with a non-zero exit code.