A function can only do what its signature admits to.
Not a lint, not a convention. Deed reads the body, and a function that reaches for something its signature did not mention is not a program.
This function saves a file.
fn keep(files: Dir, name: String, text: String) -> Result<(), String>
uses
Io.read,
{
match Io.read(files, name) {
ok(_) => ok(()),
err(_) => Io.save(files, name, text),
}
}
Its signature only admits to reading one.
error[DEED5001]: `keep` performs `Io.save` without declaring it
--> main.deed:3:4
|
3 | fn keep(files: Dir, name: String, text: String) -> Result<(), String>
| ^^^^ add `Io.save` to the `uses` clause
|
= note: a function can only do what its signature admits to
That list has a name, an effect row, and it is part of the type. It is checked in both directions, so a row that claims authority the body never uses is an error too: a signature is only worth reading if it is tight. Nothing is ambient. If a function can touch the filesystem, it was handed the filesystem, and you can see that from the call.