pub enum Builtin {
Show 86 variants
Println,
Print,
EPrint,
EPrintln,
Panic,
StrCmp,
StrHash,
CharToInt,
StrLenChars,
StrChars,
StrFromChars,
StrJoin,
StrIndexOf,
JsonQuote,
StrToUpper,
StrToLower,
FloatFixed,
StrToFloat,
TestSelector,
TaskSpawn,
TaskIsDone,
TaskRelease,
TaskDrive,
TaskOutput,
TaskYieldFuture,
TaskSleepFutureNanos,
TaskJoinFuture,
TaskTimeoutFuture,
FsReadToString,
FsWriteString,
FsTakeString,
FsLastErrorMessage,
FsTempDir,
FsExists,
FsCreateDir,
FsCreateDirAll,
FsRemoveFile,
FsRemoveDirAll,
FsReadDir,
FsTakeStringArray,
FsKind,
FsRead,
FsTakeBytes,
FsWrite,
FileOpen,
FileClose,
FileRead,
FileWrite,
FileFlush,
IoStdinRead,
IoStdoutWrite,
IoStderrWrite,
IoStdoutFlush,
IoStderrFlush,
NetConnect,
NetClose,
NetRead,
NetWrite,
NetReadTimeout,
NetListen,
NetLocalPort,
NetAccept,
BytesLen,
BytesFromString,
BytesIsUtf8,
BytesToStringUnchecked,
BytesAt,
BytesSlice,
BytesConcat,
BytesToInts,
BytesFromInts,
BytesEq,
IntHashSeed,
HttpParseRequest,
CryptoHash,
CryptoRandomBytes,
CryptoRandomInt,
TimeNowNanos,
TimeNowEpochNanos,
LogConfigLevel,
LogConfigToStderr,
LogSetConfig,
ShutdownRequested,
ProcessArgCount,
ProcessArg,
ProcessExit,
}Expand description
A compiler-provided builtin function.
Variants§
Println
println(s: String) — write a line to stdout.
print(s: String) — write to stdout without a trailing newline.
EPrint
eprint(s: String) — write to stderr without a trailing newline.
EPrintln
eprintln(s: String) — write a line to stderr.
Panic
panic(msg: String) — abort the program with a message.
StrCmp
str_cmp(a: String, b: String) -> Int — byte-lexicographic compare,
returning -1, 0, or 1. Backs std/core‘s impl Ord for String:
< is not defined for String (E0013) and String is not FFI-safe
(require_ffi_safe in nova-typeck only accepts scalars), so a
user-visible extern is not an option. Reached the same way
println/print/panic are — a Res::Builtin checked specially by
nova-typeck and lowered straight to a CallRuntime in nova-mir —
not the way == on String reaches nova_rt_str_eq: that is a
pure operator lowering (binary_result_ty permits Eq/Ne for
Ty::String, then MIR’s lower_binary intercepts it) that introduces
no name in any namespace, whereas str_cmp is a named function.
Unlike println/print/panic, str_cmp is not part of the
user-visible language surface: it is seeded only into std modules’ own
scopes (see Builtin::STD_ONLY), so it never becomes a
reserved word in user code.
StrHash
str_hash(s: String) -> Int — seeded FNV-1a over the string’s bytes,
then splitmix64’s finalizer. The seed is per-process, so the same
string hashes differently in two runs; why the finalizer is needed and
what the pair does and does not buy are documented at
nova_rt_str_hash and splitmix64_finalize in nova-runtime rather
than restated here. Backs
std/core’s impl Hash for String, and exists for the same reason
Builtin::StrCmp does: no primitive walks a String, so a NAMED
operation over its bytes needs a builtin like this one, and an
extern cannot stand in because String is not FFI-safe. Named is
the operative word – == reaches nova_rt_str_eq as a pure operator
lowering introducing no name at all, as Builtin::StrCmp’s own doc
comment sets out just above. That is a statement
about the primitive layer, not about what Nova code can reach –
std/bytes and std/strings build byte and char access on builtins
of this kind, and ADR 0005’s 2026-08-27 amendment records where an
earlier wording read as the wider claim. Std-only, so str_hash is
not a reserved word in user code.
CharToInt
char_to_int(c: Char) -> Int — a Char’s Unicode scalar value. The
only way any std module can compare or classify a Char numerically:
Nova has no other Char → Int conversion (as casts are
unsupported, E0900; Char has no methods beyond its trait impls;
no arithmetic operator accepts a Char). Backs std/core‘s
impl Hash for Char, and std/strings’ non-ASCII whitespace check
(char_is_whitespace), and any future std module with the same need.
Unlike every other builtin this is not a runtime call — Char and
Int are both MirTy::I64, so nova-mir lowers it to a register
move (see lower_call) rather than adding a runtime ABI symbol whose
body would be the identity function. Std-only, so char_to_int is
not a reserved word in user code.
StrLenChars
str_len_chars(s: String) -> Int — the number of Unicode scalar
values in s. Backs std/strings’ String::len. No primitive walks
a String, so a length query has to be a builtin, and an extern
cannot stand in because String is not FFI-safe. Note this builtin is
part of what supplies the capability it names as absent, so read the
absence as one about primitives and not about String as user code
sees it. Separate from str_chars so a length query allocates
nothing. Std-only, so it is not a reserved word in user code.
StrChars
str_chars(s: String) -> [Char] — the string’s Unicode scalar values
in order. Backs std/strings’ String::chars, and every operation in
that module that inspects a string. Also backs std/core’s
impl Debug for String, which needs to escape the contents. Std-only.
StrFromChars
str_from_chars(cs: [Char]) -> String — encode codepoints as UTF-8.
The inverse of Builtin::StrChars, and how every std/strings
operation that produces a string produces it: Nova has no + for
String (E0013), so building a result any other way would mean
quadratic interpolation. Std-only.
StrJoin
str_join(sep: String, parts: [String]) -> String — parts with
sep between each pair, copied byte for byte into one result. Backs
std/strings’ String.join, which otherwise has to walk every part
character by character through Builtin::StrChars and
Builtin::StrFromChars. Std-only.
StrIndexOf
str_index_of(haystack: String, needle: String) -> Int — the
character index of the first occurrence of needle, or -1, found by
a byte search. Backs std/strings’ String.index_of and
String.contains, which used to build a Builtin::StrChars array
for each string first. Std-only.
JsonQuote
json_quote(s: String) -> String — s as a JSON string literal,
quotation marks included: the escaped length counted, then the result
written once. Backs std/json’s quote, which used to scan a
Builtin::StrChars array and rebuild any string that needed escaping
character by character. Std-only.
StrToUpper
str_to_upper(s: String) -> String — full Unicode uppercase. Backs
std/strings’ String::to_upper. Whole-string rather than
Char → Char because ß → SS is not 1:1. Std-only.
StrToLower
str_to_lower(s: String) -> String — full Unicode lowercase, for the
same reason as Builtin::StrToUpper. Std-only.
FloatFixed
float_fixed(v: Float, places: Int) -> String — render v to a fixed
number of decimal places. Two callers, not one. It was introduced
for std/fmt’s Float::fixed (std/fmt/lib.nova), and std/json’s
impl FromJson for Int (std/json/lib.nova) is now the second: it
takes an integral Float’s digits from float_fixed(n, 0) because
Float’s Display is a shortest-round-trip rendering rather than an
exact one. So a change to its rounding or its clamping reaches the JSON
decode path as well as std/fmt. Nova cannot implement this itself:
decimal rendering of a binary float is a solved problem with sharp
edges, and Nova has no Float to Int conversion at all to begin one
with. Std-only.
StrToFloat
str_to_float(s: String) -> Float — parse decimal text as a Float.
Two callers, not one. It was introduced for std/json’s number
scanner, and impl ToJson for Int is now the second, which does not go
through the scanner at all. The exact mirror of Builtin::FloatFixed,
and a builtin for the same reason: correctly rounded decimal-to-binary
conversion is a solved problem with sharp edges, and the obvious
digits × 10^exp accumulation double-rounds — once into the
significand, once into the scaling — so a Nova reimplementation would
not round-trip its own output. That is the whole of the refusal. The
language also has no Int → Float conversion (no such builtin, and
as casts are unsupported, E0900), but that is a cost rather than a
wall: an if/else chain from Int to a Float literal spans any fixed
digit range, the same construction std/json’s hex_digit used over
sixteen arms to reach String literals, until Builtin::JsonQuote
replaced it on 2026-10-03. Std-only, so
str_to_float is not a reserved word in user code.
TestSelector
test_selector() -> Int — which @test to run in this process, or a
negative value meaning “print the inventory instead”.
Reads NOVA_TEST_INDEX. A negative value is the sentinel rather than
“index >= count”, because producing a negative needs no knowledge of the
count — and “greater than or equal” would require the runner to already
know the number it is asking for. An absent or unparseable variable
reads as negative, so running the test binary by hand with no variable
set prints its inventory rather than silently doing nothing.
STD_ONLY, like str_cmp: seeded into std modules’ scopes only, so it
never becomes a name a user program could call or collide with.
TaskSpawn
task_spawn(fut: Future<T>) -> Int — register a future with this
thread’s executor and return its task id. Backs std/task’s spawn.
A builtin because its parameter is a Future<T>, which no extern can
mention (Future is not FFI-safe, require_ffi_safe in nova-typeck)
and no Nova expression can construct. Like every Future-taking builtin
below it is typed with Ty::Param(0), so it unifies only against a
generic parameter of index zero — which is why every std/task
function that calls one declares exactly one type parameter, and why a
second one declared before it is a compile error at the call site
(E0010) rather than anything quieter. Std-only, so task_spawn is not
a reserved word in user code.
TaskIsDone
task_is_done(fut: Future<T>) -> Bool — whether the task named by
fut’s state has completed.
Backed JoinHandle::join’s spin loop before Task 3 replaced it with a
real park on completion (Builtin::TaskJoinFuture); no call site in
std/task remains, but the query is still part of the executor’s
Nova-facing surface. Std-only.
TaskRelease
task_release(fut: Future<T>) — end the executor’s claim on the task
named by fut’s state, so a joined task’s state is not rooted for the
rest of the process. Idempotent, which is what lets join be called
twice on one handle. Std-only.
TaskDrive
task_drive(fut: Future<T>) — run this thread’s executor until every
queued task has finished. Backs std/task’s block_on, paired with
Builtin::TaskOutput to read the value: the runtime returns the
output as an i64, which is not the machine class of a Float.
Std-only.
TaskOutput
task_output(fut: Future<T>) -> T — the value a finished future wrote
to its state object’s output slot.
Unlike every other builtin here this is not a runtime call: it is two
typed field loads (nova-mir’s lower_call), which is the only way the
value can arrive in T’s own machine class — a Float output crosses
register banks, so routing it through the executor’s i64 return would
reinterpret its bits. Safe to read at any point after the future has
completed, and any number of times, because the value stays in the state
object and the future keeps that object alive. Std-only.
TaskYieldFuture
task_yield_future() -> Future<unit> — a fresh future that reports
pending once and then completes.
The whole of what std/task’s yield_now awaits, and it has to be a
builtin because a Nova async fn body suspends only at an .await:
there is nothing in the language to await that is not already ready.
Its future is built by nova_rt_task_yield_future, the one poll
function nova-mir’s async transform did not generate. Std-only.
TaskSleepFutureNanos
task_sleep_future_nanos(nanos: Int) -> Future<unit> — a fresh future
that parks for nanos nanoseconds, then completes.
The first builtin that actually parks: unlike
Builtin::TaskYieldFuture, which always resumes on the next turn,
this future registers a deadline with the executor’s park set (Task
1’s Wait::Deadline) and is not polled again until that deadline
passes. Backs std/time’s sleep. A builtin for the same reason
task_yield_future is: an async fn body suspends only at an
.await, and nothing expressible in Nova produces a future that
starts out pending. Std-only.
TaskJoinFuture
task_join_future(fut: Future<T>) -> Future<unit> — a fresh future
that parks until the task named by fut’s state completes, then
completes itself.
Resolves fut to a task id up front, through the same state-address
lookup Builtin::TaskIsDone/Builtin::TaskRelease use, so a
future no task was spawned for aborts immediately rather than
becoming a park nothing can wake. Backs std/task’s join, which
used to spin on Builtin::TaskIsDone instead: joining a task that
is parked with nothing left in the program that could ever wake it —
for example, two tasks joining each other in a cycle — now reports a
deadlock rather than costing one poll per turn forever. Joining a
task parked on a deadline (one that is sleeping) is not, by itself,
this. Joining a task that never finishes because it keeps
re-queueing itself (a yield_now loop) is a livelock, not a
deadlock, and is not reported: nothing there is parked, so it still
costs one poll per turn forever, undiagnosed
(docs/adr/0009-async-execution-model.md §1’s 2026-08-10 amendment).
A builtin for the same reason task_sleep_future_nanos
is: an async fn body suspends only at an .await, and nothing
expressible in Nova produces a future that starts out pending.
Std-only.
TaskTimeoutFuture
task_timeout_future(nanos: Int, fut: Future<T>) -> Future<Int> — a
fresh future that polls fut until it completes or nanos nanoseconds
pass, producing 0 if the inner future completed and 1 if the
deadline elapsed.
Carries a status rather than the value, which is what keeps it
expressible: a builtin’s signature is a fixed list of types, and the
value is read separately with Builtin::TaskOutput on the inner
future, from the slot the inner future itself wrote. Backs std/time’s
timeout. Std-only.
FsReadToString
fs_read_to_string(path: String) -> Int — read path as UTF-8.
Returns a status code (0 on success, an IoErrorKind code otherwise
— see crates/nova-runtime/src/fs.rs), not the string itself: an
intrinsic returns exactly one word, and this call must convey both a
String and enough information to build an IoError. On success the
contents are waiting in Builtin::FsTakeString. Backs std/fs’s
read_to_string. Std-only.
FsWriteString
fs_write_string(path: String, content: String) -> Int — write
content to path, truncating any existing contents. A status code,
for the same reason as Builtin::FsReadToString. Backs std/fs’s
write_string. Std-only.
FsTakeString
fs_take_string() -> String — take the payload staged by a successful
Builtin::FsReadToString. Backs std/fs’s read_to_string.
Std-only.
FsLastErrorMessage
fs_last_error_message() -> String — take the OS-provided message
staged by a failed filesystem operation. Backs std/fs’s
read_to_string and write_string. Std-only.
FsTempDir
fs_temp_dir() -> String — the OS temporary-directory path
(std::env::temp_dir(), lossily reencoded from UTF-16 on Windows —
see crates/nova-runtime/src/fs.rs). Backs std/fs’s temp_dir.
Not a runtime-call-only concern: this is what lets a fixture build a
writable path without hardcoding one. Std-only.
FsExists
fs_exists(path: String) -> Bool — whether path exists on disk.
Not a status code like its siblings: nova-spec/20-STDLIB.md §5
gives exists a plain Bool, so a path that exists but cannot be
examined is indistinguishable from one that is absent. Backs
std/fs’s exists. Std-only.
FsCreateDir
fs_create_dir(path: String) -> Int — create the directory path.
Its parent must exist; an existing path is AlreadyExists. A
status code, for the same reason as Builtin::FsReadToString.
Backs std/fs’s create_dir. Std-only.
FsCreateDirAll
fs_create_dir_all(path: String) -> Int — create the directory
path, and any missing parent directories along the way. Unlike
Builtin::FsCreateDir, an already-existing directory at path is
success, not AlreadyExists. Backs std/fs’s create_dir_all.
Std-only.
FsRemoveFile
fs_remove_file(path: String) -> Int — remove the file path. A
status code, for the same reason as Builtin::FsReadToString.
Backs std/fs’s remove_file. Std-only.
FsRemoveDirAll
fs_remove_dir_all(path: String) -> Int — remove the directory
path and everything beneath it. A status code, for the same reason
as Builtin::FsReadToString. Backs std/fs’s remove_dir_all.
Std-only.
FsReadDir
fs_read_dir(path: String) -> Int — list path’s entry names,
sorted. A status code, for the same reason as
Builtin::FsReadToString; on success the names are waiting in
Builtin::FsTakeStringArray. Sorted in the runtime because
directory order is unspecified by every OS. Backs std/fs’s
read_dir. Std-only.
FsTakeStringArray
fs_take_string_array() -> [String] — take the array staged by a
successful Builtin::FsReadDir. Backs std/fs’s read_dir.
Std-only.
FsKind
fs_kind(path: String) -> Int — what path is: 0 metadata
unavailable (absent, or unreadable), 1 file, 2 directory. One call
rather than separate is_file/is_dir intrinsics, so a DirEntry
costs one syscall instead of two and the two answers cannot disagree.
Backs std/fs’s read_dir. Std-only.
FsRead
fs_read(path: String) -> Int — read the path’s raw bytes. 0 on
success, with the contents waiting in Builtin::FsTakeBytes;
otherwise an IoErrorKind status code (crates/nova-runtime/src/fs.rs).
Unlike Builtin::FsReadToString this cannot report InvalidData:
there is no encoding to violate. Backs std/fs’s read. Std-only.
FsTakeBytes
fs_take_bytes() -> Bytes — take the payload staged by a successful
Builtin::FsRead. Backs std/fs’s read. Std-only.
FsWrite
fs_write(path: String, content: Bytes) -> Int — write the bytes to
the path, truncating an existing file. Status code, as
Builtin::FsReadToString. Backs std/fs’s write. Std-only.
FileOpen
file_open(path: String, read: Bool, write: Bool, append: Bool, truncate: Bool, create: Bool, create_new: Bool) -> Int — open path
through std::fs::OpenOptions, forwarding all six flags one for one.
0 on success, with the new fd waiting in Builtin::FsTakeBytes as
an 8-byte little-endian payload — the fd cannot travel in the status
word because the status word already carries the IoErrorKind, the
same reason Builtin::IoStdoutWrite’s byte count does not either;
otherwise an IoErrorKind status code, as Builtin::FsReadToString.
The widest builtin in this table, one parameter per OpenOptions
method rather than a packed bitmask, so the Nova surface matches
std::fs::OpenOptions field for field. Runtime symbol
nova_rt_file_open (crates/nova-runtime/src/file.rs). Std-only.
FileClose
file_close(fd: Int) -> Int — close fd, dropping the underlying
file and releasing its OS handle. Idempotent: closing an
already-closed, stale, or forged fd finds nothing in the runtime’s
handle table and still reports success, so a caller may close the
same value more than once. No payload, mirroring
Builtin::IoStdoutFlush. Runtime symbol nova_rt_file_close
(crates/nova-runtime/src/file.rs). Std-only.
FileRead
file_read(fd: Int, max: Int) -> Int — read up to max bytes from
fd, the same status/payload shape as Builtin::IoStdinRead. 0
on success, with the bytes read waiting in Builtin::FsTakeBytes;
otherwise an IoErrorKind status code, as Builtin::FsReadToString
— including a closed, stale, or forged fd, which the runtime’s handle
table reports as an ordinary IoError rather than a panic. An
empty payload means end of stream; a short read does not. Runtime
symbol nova_rt_file_read (crates/nova-runtime/src/file.rs).
Std-only.
FileWrite
file_write(fd: Int, buf: Bytes) -> Int — write buf to fd with
one Write::write call, not a write_all loop, the same shape as
Builtin::IoStdoutWrite. 0 on success, with the number of bytes
actually written waiting in Builtin::FsTakeBytes, encoded as an
8-byte little-endian count; otherwise an IoErrorKind status code, as
Builtin::FsReadToString — including a closed, stale, or forged
fd, as Builtin::FileRead. Runtime symbol nova_rt_file_write
(crates/nova-runtime/src/file.rs). Std-only.
FileFlush
file_flush(fd: Int) -> Int — flush fd. A status code, as
Builtin::FsReadToString, including a closed, stale, or forged fd,
as Builtin::FileRead; unlike Builtin::FileWrite, a successful
flush stashes no payload of its own for Builtin::FsTakeBytes to
collect, mirroring Builtin::IoStdoutFlush. Runtime symbol
nova_rt_file_flush (crates/nova-runtime/src/file.rs). Std-only.
IoStdinRead
io_stdin_read(max: Int) -> Int — read up to max bytes from stdin,
the same status/payload shape as Builtin::FsRead. 0 on success,
with the bytes read waiting in Builtin::FsTakeBytes; otherwise an
IoErrorKind status code, as Builtin::FsReadToString. An
empty payload means end of stream; a short read does not. Runtime
symbol nova_rt_io_stdin_read (crates/nova-runtime/src/io.rs).
Std-only.
IoStdoutWrite
io_stdout_write(buf: Bytes) -> Int — write buf to stdout with one
Write::write call, not a write_all loop, so a short write is
reported rather than retried underneath the caller. 0 on success,
with the number of bytes actually written waiting in
Builtin::FsTakeBytes, encoded as an 8-byte little-endian count;
otherwise an IoErrorKind status code, as Builtin::FsReadToString.
Runtime symbol nova_rt_io_stdout_write
(crates/nova-runtime/src/io.rs). Std-only.
IoStderrWrite
io_stderr_write(buf: Bytes) -> Int — write buf to stderr. Mirrors
Builtin::IoStdoutWrite exactly, against the other stream.
Std-only.
IoStdoutFlush
io_stdout_flush() -> Int — flush stdout. A status code, as
Builtin::FsReadToString; unlike Builtin::IoStdoutWrite, a
successful flush stashes no payload of its own for
Builtin::FsTakeBytes to collect – it does not clear whatever a
prior operation left there either. Std-only.
IoStderrFlush
io_stderr_flush() -> Int — flush stderr. Mirrors
Builtin::IoStdoutFlush exactly, against the other stream.
Std-only.
NetConnect
net_connect(addr: String) -> Future<Int> — connect to addr
(“host:port”), non-blockingly.
A future constructor, not a status word — the one thing that makes
this builtin and the other future constructors in this group
(Builtin::NetRead, Builtin::NetWrite,
Builtin::NetReadTimeout, Builtin::NetAccept) unlike every
fs_*/file_*/io_* intrinsic above. Named rather than counted
positionally, and deliberately with no count at all: the variants below
this one are a mix of future constructors and status words in no
particular order, so “the three below it” would read as “the next
three” and be wrong that way, and any number written here goes stale
the next time std/net grows — this sentence has already been
rewritten twice for exactly that reason, once when
Builtin::NetLocalPort landed and again when
Builtin::NetAccept did.
The archaeology that used to close this paragraph is retracted rather
than recounted. It said: “Two rewrites over three staleness events:
main’s ‘the three below it’ first went wrong when
Builtin::NetListen arrived and was left standing for an
increment.” The count and the ordinal are both wrong, under either
reading of the wording they describe. Read as its own words invite –
the next three variants – “the three below it” was already wrong
on main, because Builtin::NetClose is the variant directly below
and is not a future constructor at all. Read as the three other
future constructors, it stayed true through both
Builtin::NetListen and Builtin::NetLocalPort, since both are
status words, and only Builtin::NetAccept falsified it. So
Builtin::NetListen falsified no wording here at all. The sentence
it did falsify was Builtin::NetClose’s own “the one member of this
group of five”, and that was corrected in the very commit that added
Builtin::NetListen rather than left standing.
Those status words return an i64 directly and synchronously; this
one returns a *mut u8 future state object
(surfaced to Nova as Future<Int>) that must itself be .awaited to
produce the Int status — 0 on success, with the new fd waiting in
Builtin::FsTakeBytes as an 8-byte little-endian payload, the same
reason Builtin::FileOpen’s new fd travels that way; otherwise an
IoErrorKind status code, as Builtin::FsReadToString, including
CONNECTION_REFUSED’s first producer. A reader arriving here from
file.rs should not expect the old shape. Runtime symbol
nova_rt_net_connect_future (crates/nova-runtime/src/net.rs).
Std-only.
NetClose
net_close(fd: Int) -> Int — close fd, dropping the underlying
handle and releasing its OS handle.
Not a future constructor, unlike every future constructor
Builtin::NetConnect’s own doc comment rosters — an ordinary status
word, exactly Builtin::FileClose’s shape, for the identical reason:
idempotent,
since std/net’s close cannot consume its receiver (Nova has no
move checking), so a caller can always reach a second call, and
closing an already-closed, stale, or forged fd finds nothing in the
runtime’s handle table and still reports success. No payload. Runtime
symbol nova_rt_net_close (crates/nova-runtime/src/net.rs).
That contrast read “unlike Builtin::NetConnect and the read/write
group below it”, phrased that way in the commit that added
Builtin::NetListen so it would survive the group growing. It did
not survive Builtin::NetAccept, which is a future constructor
below this one and is neither a read nor a write, so the one variant
added after the rewrite is exactly the one the growth-proof phrasing
excluded. Deferring to Builtin::NetConnect’s roster leaves one
list to keep current instead of two that can disagree.
Serves a listener as well as a connected stream, which is why
Builtin::NetListen adds no close of its own: the runtime keeps both
kinds in one handle table and removes an entry by key regardless of
which kind it holds. TcpListener::close in std/net calls this same
builtin. Std-only.
NetRead
net_read(fd: Int, max: Int) -> Future<Int> — read up to max bytes
from fd, non-blockingly.
A future constructor, as Builtin::NetConnect’s doc comment
explains — .awaiting it produces 0 on success, with the bytes
read waiting in Builtin::FsTakeBytes; otherwise an IoErrorKind
status code, as Builtin::FsReadToString — including a closed,
stale, or forged fd. An empty payload means end of stream; a
short read does not, the same contract Builtin::FileRead and
Builtin::IoStdinRead already carry. Runtime symbol
nova_rt_net_read_future (crates/nova-runtime/src/net.rs).
Std-only.
NetWrite
net_write(fd: Int, buf: Bytes) -> Future<Int> — write buf to fd
with one non-blocking Write::write attempt, not a write_all loop.
A future constructor, as Builtin::NetConnect’s doc comment
explains — .awaiting it produces 0 on success, with the number of
bytes actually written waiting in Builtin::FsTakeBytes, encoded
as an 8-byte little-endian count, the same shape
Builtin::FileWrite uses; otherwise an IoErrorKind status code,
as Builtin::FsReadToString — including a closed, stale, or forged
fd. Runtime symbol nova_rt_net_write_future
(crates/nova-runtime/src/net.rs). Std-only.
NetReadTimeout
net_read_timeout(fd: Int, max: Int, ms: Int) -> Future<Int> — read
up to max bytes from fd, non-blockingly, reporting TIMED_OUT if
ms milliseconds pass with nothing to read first.
A future constructor, as Builtin::NetConnect’s doc comment
explains — otherwise identical to Builtin::NetRead, including
EOF/short-read semantics and where the bytes land on success. Runtime
symbol nova_rt_net_read_timeout_future
(crates/nova-runtime/src/net.rs). Std-only.
NetListen
net_listen(addr: String) -> Int — bind and listen on addr
(“host:port”), registering a non-blocking listening socket.
Not a future constructor, one of the three builtins in this group
that are not, with Builtin::NetClose and
Builtin::NetLocalPort: the bind and listen syscalls
are immediate kernel bookkeeping and do not block, so there is no
suspension to model and std/net’s bind is a plain fn rather than
an async fn. The waiting a server does happens in
Builtin::NetAccept, which is a separate builtin and is a future
constructor.
That is a claim about the syscalls, not about every argument. A
numeric address never blocks, but this builtin’s parameter is a
String a user program chooses, and a hostname resolves through
std’s ToSocketAddrs — a blocking lookup with no future to park on.
resolve_addr’s own doc comment in crates/nova-runtime/src/net.rs
records that caveat for connect, and it applies here unchanged:
out of scope rather than handled. nova_rt_net_listen’s doc comment
also records where its resolution differs from connect’s, since it
does not go through resolve_addr at all.
Returns a status code as Builtin::FsReadToString does — 0 on
success, with the new fd waiting in Builtin::FsTakeBytes as an
8-byte little-endian payload, the same channel Builtin::NetConnect
and Builtin::FileOpen use for their own fds. The fd is closed with
Builtin::NetClose, which serves both kinds of handle.
An address already in use arrives as Other, not a distinct kind.
fs.rs’s IoErrorKind table has no AddrInUse variant, so the most
likely failure of this builtin is discriminable only by the message
text the operating system supplied. Adding a variant is a wire-contract
change across the runtime’s fail and std/io’s io_error_kind_of
together, and is deliberately not done. Runtime symbol
nova_rt_net_listen (crates/nova-runtime/src/net.rs). Std-only.
NetLocalPort
net_local_port(fd: Int) -> Int — the port the listening socket behind
fd is bound to, which is how a caller learns the kernel’s choice after
Builtin::NetListen on port 0.
Not a future constructor, joining Builtin::NetClose and
Builtin::NetListen rather than the future constructors
Builtin::NetConnect’s own doc comment rosters. This read “the third
builtin in this group that is not”, contrasted “rather than the
read/write group”: the ordinal ranks within a group that grows, and
“the read/write group” stopped naming the future constructors the
moment Builtin::NetAccept joined them, which is the same pair of
habits corrected at Builtin::NetConnect and Builtin::NetClose
above. local_addr is a getsockname call over
bookkeeping the kernel already holds, so there is no suspension to model
and std/net’s local_port is a plain fn rather than an async fn.
Unlike Builtin::NetListen, that claim needs no caveat about its
argument. This builtin takes an Int fd, not a String, so there is
no address for std’s ToSocketAddrs to resolve and no blocking lookup
to reach. It really cannot block, on any argument.
Returns a status code as Builtin::FsReadToString does — 0 on
success, with the port waiting in Builtin::FsTakeBytes as an
8-byte little-endian payload, the same channel Builtin::NetListen’s
and Builtin::NetConnect’s fds ride. The port cannot ride the return
value instead: that word is the IoErrorKind status, so a port there
would make 0 ambiguous and every non-zero port indistinguishable from
a failure.
An fd naming a connected stream rather than a listener is an error
here, and an Other one. The runtime keeps both kinds of handle in
one table and its kind-checked lookup collapses wrong-kind into the same
miss an absent, closed, stale or forged fd gives — so a stream’s own
local port is unreachable through this builtin, and no distinguishable
wrong-kind status exists to rely on. Runtime symbol
nova_rt_net_local_port (crates/nova-runtime/src/net.rs). Std-only.
NetAccept
net_accept(fd: Int) -> Future<Int> — wait for the next incoming
connection on the listening socket behind fd.
A future constructor, as Builtin::NetConnect’s doc comment
explains — unlike Builtin::NetClose and Builtin::NetLocalPort,
which are status words because their syscalls cannot wait on a peer.
Waiting on a peer is the whole of what this one does, which is why
std/net’s accept is an async fn while bind and
TcpListener::local_port beside it are plain fns. .awaiting it
produces 0 on success, with the accepted
connection’s new fd waiting in Builtin::FsTakeBytes as an 8-byte
little-endian payload, the same channel Builtin::NetListen’s and
Builtin::NetConnect’s own fds ride; otherwise an IoErrorKind
status code, as Builtin::FsReadToString — including a closed,
stale, or forged fd, and an fd naming a connected stream rather than a
listener, which is the same wrong-kind miss
Builtin::NetLocalPort describes.
The accepted fd is an ordinary TcpStream fd, indistinguishable
from one Builtin::NetConnect produced, so
Builtin::NetRead/Builtin::NetWrite/Builtin::NetReadTimeout
and Builtin::NetClose all work on it unchanged.
A task parked here cannot also be waiting on a connection. Staging
two I/O waits in one poll ends the process (stage_park in
crates/nova-runtime/src/task.rs), so a server that accepts while
serving needs at least two tasks, and this language has no
select/race to avoid that. Runtime symbol
nova_rt_net_accept_future (crates/nova-runtime/src/net.rs).
Std-only.
BytesLen
bytes_len(b: Bytes) -> Int — the byte length. Not a character
count: Bytes has no encoding. Backs std/bytes’s Bytes::len.
No primitive reads a Bytes value’s own header, exactly as none walks
a String, so this reaches the runtime the same way str_len_chars
does – and as there, the absence is one about primitives rather than
about what std/bytes then offers on top of them. Std-only.
BytesFromString
bytes_from_string_intrinsic(s: String) -> Bytes — a Bytes holding
s’s UTF-8 bytes. Backs the free function bytes_from_string in
std/bytes/lib.nova.
Named ..._intrinsic, not bytes_from_string, deliberately.
std/bytes is itself an entry of STD_MODULES, so Builtin::STD_ONLY
is seeded into its own scope before that module’s items are
collected (see resolve_program’s pass order). A pub fn bytes_from_string in that same file would then hit insert_value’s
scope.values.contains_key check against this builtin’s own
pre-seeded entry and fail name resolution with E0002 duplicate definition — not silently compile into a recursive call, and not
silently shadow the builtin either; insert_value has no soft/shadow
path for a module’s own item colliding with something already in its
own scope, unlike the separate, later, entry-style glob import
import_std_module uses to let one std module’s export lose to
another module’s own definition. Verified empirically (see the Task 2
report): naming this builtin bytes_from_string reproduces the
E0002 against std/bytes/lib.nova itself, on every compile. Std-only.
BytesIsUtf8
bytes_is_utf8(b: Bytes) -> Bool — whether b’s bytes are valid
UTF-8. Backs std/bytes’s Bytes::to_string, paired with
Builtin::BytesToStringUnchecked so that method can be a Nova-level
if rather than needing a status-code protocol for one boolean.
Std-only.
BytesToStringUnchecked
bytes_to_string_unchecked(b: Bytes) -> String — b’s bytes as a
String, without checking UTF-8 validity. Backs std/bytes’s
Bytes::to_string, whose only call site checks
Builtin::BytesIsUtf8 first — an invalid String would be unsound,
which is why that check is not optional at the call site even though
this builtin cannot enforce it itself. Std-only.
BytesAt
bytes_at(b: Bytes, i: Int) -> Int — the byte at i, in 0..=255.
Backs std/bytes’s Bytes::byte_at, which bounds-checks i first and
returns Option; this intrinsic aborts on an out-of-range index rather
than returning a sentinel, since that path guards a std/bytes bug
rather than a user mistake. Nova cannot index a Bytes value’s own
buffer (no indexing operator reaches the runtime), so this reaches the
runtime the same way bytes_len does. Std-only.
BytesSlice
bytes_slice(b: Bytes, start: Int, end: Int) -> Bytes — the bytes in
start..end, clamped to the buffer and to start <= end. Backs
std/bytes’s Bytes::slice. Clamps rather than aborting — a
deliberate divergence from std/strings’s String::slice, which
panics on an out-of-range bound; a Bytes length often comes from
disk rather than from a caller who already knows it, so clamping is
the better failure mode here. Recorded, accepted divergence — see the
design spec’s dated note — not agreement with String::slice.
Std-only.
BytesConcat
bytes_concat(a: Bytes, b: Bytes) -> Bytes — a’s bytes followed by
b’s. Backs std/bytes’s Bytes::concat. Std-only.
BytesToInts
bytes_to_ints(b: Bytes) -> [Int] — each byte as an Int in
0..=255, in order. Backs std/bytes’s Bytes::to_ints, and in turn
index_of/contains, which search over the resulting array in Nova
rather than through a per-search intrinsic. Std-only.
BytesFromInts
bytes_from_ints_intrinsic(ints: [Int]) -> Bytes — a Bytes holding
each element of ints as one byte. Aborts if any element is outside
0..=255. Backs the free function bytes_from_ints in
std/bytes/lib.nova.
Named ..._intrinsic, not bytes_from_ints, for the same reason as
Builtin::BytesFromString — see that variant’s doc comment.
std/bytes is itself an entry of STD_MODULES, so a pub fn bytes_from_ints there sharing this builtin’s name would collide with
its own pre-seeded builtin entry (insert_value’s E0002) rather than
calling it. Std-only.
BytesEq
bytes_eq(a: Bytes, b: Bytes) -> Bool — byte-for-byte equality. Backs
std/bytes’s impl Eq for Bytes. A dedicated intrinsic rather than an
operator lowering: unlike String’s == (a pure operator lowering
straight to nova_rt_str_eq, see Builtin::StrCmp’s doc comment),
Bytes equality is reached only through the Eq trait’s eq method,
so binary_result_ty needs no Ty::Bytes arm for ==/!=. Std-only.
IntHashSeed
int_hash_seed() -> Int — the per-process seed for std/core’s Int,
Bool and Char hashing, XORed into the input before mix64 runs, as
nova_rt_int_hash_seed draws it. What it buys is precomputation
resistance: a colliding key set cannot be built offline against a
process that has not started yet.
A SEPARATE call from the one behind Builtin::StrHash’s seed. Were
the two one value, (0).hash() would equal ("").hash() exactly, since
both reduce to the same finalizer applied to the seed alone. That the
two differ is what the separate call buys; whether recovering one yields
the other is a question about the draw’s internals, answered at
int_hash_seed in nova-runtime and not settled there either.
Nova code can recover this value in one call, since those Hash
impls XOR it in: (0).hash() is mix64(0 ^ seed), which is
mix64(seed), and mix64 is an invertible bijection. That is the same
shape ("").hash() already has for the string seed, it follows from ADR
0005’s one-shot Hash returning a plain Int, and the gate claim
already declines the adaptive attacker for whom it matters.
tests/runtime/hash.nova performs that recovery, to cancel the seed
when it asserts mix64’s canonical vectors. Std-only.
HttpParseRequest
http_parse_request(buf: Bytes) -> [Int] — an HTTP/1.1 request head
parsed into a flat table of byte offsets into buf itself. Copies
nothing, allocates nothing on the Rust heap, and holds no state between
calls, so std/http has nothing to release and nothing to leak per
request.
Element 0 is a status: 0 complete, 1 partial (read more and call
again), negative for an error. On any non-zero status the array has
length 1, so a caller who skips the status check indexes out of
bounds rather than reading a plausible-looking offset. The full
encoding lives on nova_rt_http_parse_request in
crates/nova-runtime/src/http.rs, which is the half that writes it.
Std-only.
CryptoHash
crypto_hash(op: Int, key: Bytes, data: Bytes, tag: Bytes) -> Int —
std/crypto’s hash/HMAC intrinsic: SHA-256, SHA-512, HMAC-SHA-256, or
HMAC-SHA-256’s constant-time tag check, selected by op (the OP_*
constants in crates/nova-runtime/src/crypto.rs). Nova has no way to
reach a vetted hash implementation from source, so every one of these
operations crosses into Rust, which calls into ring.
The return is a status word, not the digest. For the digest
operations, 0 means success, with the digest waiting in
Builtin::FsTakeBytes. For the tag check, 0 means the tag
matched and 1 means it did not — an answer, not an error. No
negative range at all: none of crypto_hash’s operations can fail
for any input a Nova program can construct. That scope is deliberate
rather than hedging — the digest, HMAC-key and HMAC-sign paths each
end in an .unwrap() inside ring, on an input-length error needing
roughly 2^61 bytes, so the bound is ring’s and not this tree’s; the
tag check’s ring::hmac::verify returns a Result and unwraps
nothing. crates/nova-runtime/src/crypto.rs’s ERR_* block states
this at length.
Runtime symbol nova_rt_crypto_hash
(crates/nova-runtime/src/crypto.rs). Std-only.
CryptoRandomBytes
crypto_random_bytes(n: Int) -> Int — std/crypto’s random-bytes
intrinsic: n bytes drawn from the OS entropy source via ring.
Nova has no way to reach an OS entropy source from source, so this
crosses into Rust.
The return is a status word, not the bytes. 0 on success, with
the bytes waiting in Builtin::FsTakeBytes; otherwise
negative, naming one of crypto.rs’s ERR_* kinds — an n that
does not fit a usize, a request over the size cap, or the entropy
source itself failing. Runtime symbol nova_rt_crypto_random_bytes
(crates/nova-runtime/src/crypto.rs). Std-only.
CryptoRandomInt
crypto_random_int(min: Int, max: Int) -> Int — std/crypto’s
bounded random-integer intrinsic: a uniform draw from min..=max by
rejection sampling against the OS entropy source. Nova has no way to
reach an OS entropy source from source, so this crosses into Rust.
The return is a status word, not the integer. 0 on success,
with the value waiting in the same Builtin::FsTakeBytes slot that
Builtin::CryptoHash and Builtin::CryptoRandomBytes use,
decoded on the Nova side as decode_count(fs_take_bytes());
otherwise negative, naming one of crypto.rs’s ERR_* kinds.
Three conditions reach that range, not two: an inverted range
(ERR_INVALID_RANGE), the entropy source itself failing, and the
bounded rejection loop running out of attempts without landing above
the biased tail — the last two share ERR_ENTROPY_UNAVAILABLE, so a
caller cannot tell them apart. Runtime symbol
nova_rt_crypto_random_int
(crates/nova-runtime/src/crypto.rs). Std-only.
TimeNowNanos
time_now_nanos() -> Int — nanoseconds since the runtime’s single
process epoch, monotonic and never negative.
The only part of std/time that cannot be Nova code: Instant and
Duration arithmetic is plain multiplication, division and
subtraction over a private Int, so nothing else in §9 needs to cross
into Rust. Saturates at i64::MAX rather than wrapping; see
nova_rt_time_now_nanos. Std-only.
TimeNowEpochNanos
time_now_epoch_nanos() -> Int — nanoseconds since the Unix
epoch, as read by nova_rt_time_now_epoch_nanos. Distinct from
TimeNowNanos, which is relative to this process’s own start, not
to 1970. Std-only.
LogConfigLevel
log_config_level() -> Int — the logger’s configured threshold, as
nova_rt_log_config_level reads it. Std-only.
LogConfigToStderr
log_config_to_stderr() -> Int — 1 for stderr, 0 for stdout, as
nova_rt_log_config_to_stderr reads it. Std-only.
LogSetConfig
log_set_config(level: Int, to_stderr: Int) -> unit — install a
logger configuration, overwriting any previous one, via
nova_rt_log_set_config. Std-only.
ShutdownRequested
shutdown_requested() -> Bool — whether the process has been asked to
stop: the first SIGTERM or SIGINT on Unix, CTRL_BREAK or CTRL_C on
Windows. The first call installs the handler that sets it, so a
program that never calls this keeps every signal’s default action.
Read by std/http’s Server::listen and its connections, once per
tick. Runtime symbol nova_rt_shutdown_requested
(crates/nova-runtime/src/signal.rs, docs/adr/0022). Std-only.
ProcessArgCount
process_arg_count() -> Int — how many arguments the program has,
counting the program itself at index 0. Runtime symbol
nova_rt_process_arg_count (crates/nova-runtime/src/process.rs,
docs/adr/0023). Std-only.
ProcessArg
process_arg(i: Int) -> String — argument i, or the empty string
for an index out of range. Runtime symbol nova_rt_process_arg.
Std-only.
ProcessExit
process_exit(code: Int) -> unit — ends the process with code
after flushing stdout, and never returns. Runtime symbol
nova_rt_process_exit. Std-only.
Implementations§
Source§impl Builtin
impl Builtin
Sourcepub const ALL: [Builtin; 86]
pub const ALL: [Builtin; 86]
Every Builtin variant, in the declaration order above — the
sole authoritative list of “every builtin”, generated by the
builtins! macro so a variant cannot exist without appearing
here (see the macro’s own doc comment for why a duplicate
entry can’t silently drop a different variant either).
builtin_signatures_are_what_the_std_call_sites_use iterates
this to check every variant’s signature.
Source§impl Builtin
impl Builtin
Sourcepub const GLOBAL: [Builtin; 5]
pub const GLOBAL: [Builtin; 5]
Builtins injected into every module’s scope — part of the user-visible language surface, and reserved words everywhere.
Sourcepub const STD_ONLY: [Builtin; 81]
pub const STD_ONLY: [Builtin; 81]
Builtins injected only into an std module’s own scope (any module in
STD_MODULES, not only std/core). These are implementation
details of the standard library, not user-visible language surface:
reserving one of these names in every module (as Builtin::GLOBAL
does) would permanently take it away from user code to serve the
standard library’s own internals. Each member exists because Nova
source cannot express what it does, and each is documented on its own
variant above, next to the capability it provides and the reason the
language cannot reach it. This list is membership only; call sites
are a grep away and are deliberately not enumerated here: doing so
produced stale or wrong counts in three places across three
consecutive review rounds (see the Phase 2.2b whole-branch review),
because the roster is duplicated information that only this array
needs to stay exact.
Trait Implementations§
impl Copy for Builtin
impl Eq for Builtin
impl StructuralPartialEq for Builtin
Auto Trait Implementations§
impl Freeze for Builtin
impl RefUnwindSafe for Builtin
impl Send for Builtin
impl Sync for Builtin
impl Unpin for Builtin
impl UnsafeUnpin for Builtin
impl UnwindSafe for Builtin
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.