File I/O is an explicit host boundary with Result-returning acquisition and operations, an opaque resource value, and a deliberately small portable contract.
Canonical contract
open(path) returns Result<File,string>. File exposes read() -> Result<string,string>, write(string) -> Result<(),string>, and close() -> (). File is opaque and non-comparable. Cleanup is expressed with lexical defer or the exact File-only using statement; neither spelling creates a general resource protocol.
Public surface
The wider checked host inventory includes input, FS.readText, writeText, readBytes, writeBytes, list, Path construction helpers, and virtual std.fs/std.io exports. Bytes has explicit UTF-8, hexadecimal, Base64, slicing, length, and array conversion operations. Each host effect remains tied to the declared host/profile surface.
Observable behavior
Result values model acquisition/read/write failure. using acquires once, registers close only after success, gives one immutable child-scope File binding, runs later body defers first, and closes on normal lexical control exits. File capture does not extend the using scope; a later closure observes a value that has already crossed its implicit close boundary.
Current support
File, FS, std.fs, and std.io are available in host profiles that provide filesystem access. They do not grant access to unrelated operating-system APIs, environment variables, processes, networks, or databases.
Constraints and exclusions
Append modes, binary File.read/write overloads, buffering, permissions, async I/O, user-defined disposables, multi-resource using, cancellation cleanup, module-lifetime finalization, ordinary-fault finalization, and portable post-close/repeated-close behavior are not specified. Code must propagate or match Result rather than claim exceptions.
Worked example
function append(path: string, text: string) -> Result<(), string> {
let file = open(path)?
defer { file.close() }
file.write(text)?
return Ok(())
}