V6003 resource_escape
A @resource value (v0: File) escapes the callback of the operation that introduced it: the callback returns a type containing it (directly, or inside a record, list or closure), or the value is stored in handler var state (design §8.4, §17.70).
An error from the capability phase. sakura explain V6003 prints this explanation offline.
A @resource value (v0: File) escapes the callback of the operation that introduced it: the
callback returns a type containing it (directly, or inside a record, list or closure), or the
value is stored in handler var state (design §8.4, §17.70). The runtime closes the file when
the callback returns, so an escaped File cannot be used. Read or write inside the callback and
return ordinary data. Use-at-most-once is not checked statically in v0.
Wrong:
import std/fs.{Fs, File, Mode, FsError}
import std/path.{Path}
fn keep_open(p: Path) -> File ! {Fs, Fail<FsError>} {
Fs.with_file(p, Mode.Read, fn(file) { file })
}Fixed:
fn first_kb(p: Path) -> Bytes ! {Fs, Fail<FsError>} {
Fs.with_file(p, Mode.Read, fn(file) { Fs.read_chunk(file, 1024) })
}Wrong program
compiler/tests/ui/V6003_resource_escape.sakura, which the compiler's ui suite runs through sakura check:
import std/fs.{File, Fs, FsError, Mode}
import std/path.{Path}
fn keep_open(p: Path) -> File ! {Fs, Fail<FsError>} {
Fs.with_file(p, Mode.Read, fn(file) { file })
}sakura check --json reports this record (pretty-printed; $DIR is the fixture's directory):
{
"schema_version": "1.0",
"kind": "diagnostic",
"id": "d:9a99a69a967c1b07",
"code": "V6003",
"severity": "error",
"phase": "capability",
"message": "this `File` escapes the callback of `with_file`: it holds a resource, which is closed when the callback returns (design §8.4)",
"snapshot": "sha256:$SNAPSHOT",
"symbol_id": "main::V6003_resource_escape::keep_open",
"spans": [
{
"uri": "file://$DIR/V6003_resource_escape.sakura",
"content_hash": "sha256:579bb06c8d05fa88c34b60f174de613fd71825550c967a76fdccb4e0dd20580f",
"start_byte": 216,
"end_byte": 220,
"role": "primary"
}
],
"related_ids": [],
"expected": null,
"actual": null,
"obligation": null,
"counterexample": null,
"explanation_uri": "sakura://explain/V6003",
"fixes": []
}More fixtures for this code: compiler/tests/ui/V6003_route_handler_returns_file.sakura.
Fixed program
compiler/tests/ui/V6003_resource_escape.fixed.sakura, which sakura check accepts with no diagnostics:
import std/fs.{Fs, FsError, Mode}
import std/path.{Path}
fn first_kb(p: Path) -> Bytes ! {Fs, Fail<FsError>} {
Fs.with_file(p, Mode.Read, fn(file) { Fs.read_chunk(file, 1024) })
}