Skip to main content

Builtin

Enum Builtin 

Source
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

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

Source

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

Source

pub const GLOBAL: [Builtin; 5]

Builtins injected into every module’s scope — part of the user-visible language surface, and reserved words everywhere.

Source

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.

Source

pub fn name(self) -> &'static str

The source-level name of the builtin.

Trait Implementations§

Source§

impl Clone for Builtin

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Builtin

Source§

impl Debug for Builtin

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Builtin

Source§

impl Hash for Builtin

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Builtin

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Builtin

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.