Errors that go unhandled
- The problem
- When something fails, the program needs a way to deal with it.
- An example
- A program reads its configuration file. The file is missing, but the calling code assumes the read succeeded.
- What Nikaia checks
- Functions declare when they can fail, and what they can fail with is worked out from their bodies. A function that calls something that can fail, and neither declares it nor handles it, is rejected when the program is built. Tasks are held to the same rule. A task’s error is thrown where the program waits for the task, at
h.join()or at the end of anoverlap, and the compiler asks for it to be handled there as for any call that can fail. A task handle that is never joined, cancelled or detached is refused (NK2109), so the error has a place to arrive. - The limit
- For functions from outside Nikaia that nothing describes, Nikaia cannot know every way they fail. A description of the library closes that gap. The check shows where failures are not accounted for; it does not make the handling itself correct.
Show the program and what Nikaia says
use std::fs
fn load() -> String {
return fs::read_to_string("config.txt", fs::Root::Anywhere)
}
fn main() {
println(load())
}
$ nikaia check main.nika
error[NK2605]: This function can fail, because `fs::read_to_string` can fail.
--> main.nika:4:5
|
4 | return fs::read_to_string("config.txt", fs::Root::Anywhere)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `fs::read_to_string` can fail with `io::IoError`.
= note: A call that can fail looks like any other call, so its failure passes straight through this function unless you handle it.
= help: Add `throws` to `load`, or handle it at the call: `… catch { … }`.
Go deeper
More under Very safe: Conflicting actionsTasks that get stuckA memory budget for every taskBroken promises