pub const CORE: &str = "//! The types and traits every module sees without an import.\n//!\n//! `Option` holds a value that may be absent, `Result` the outcome of an\n//! operation that can fail, and `Ordering` the result of a comparison. The\n//! traits `Display`, `Debug`, `Eq`, `Ord`, `Clone`, `Default` and `Hash`\n//! come with impls for `Int`, `Float`, `Bool`, `Char` and `String`, except\n//! `Hash` for `Float`. `Iterator` yields values one at a time, and its `map`\n//! and `filter` return a `MapIter` and a `FilterIter`. A module\'s own\n//! definition of one of these names shadows the one here.\n//!\n//! An absent value, a failure, and an iterator\'s lazy `filter` and `map`,\n//! run by `collect`:\n//!\n//! ```\n//! // `Option` holds a value that may be absent.\n//! let port: Option<Int> = Some(8080)\n//! assert_eq(port.map(|p| p + 1).unwrap_or(80), 8081)\n//! let missing: Option<Int> = None\n//! assert_eq(missing.unwrap_or(80), 80)\n//!\n//! // `Result` is the outcome of something that can fail.\n//! let checked: Result<Int, String> = missing.ok_or(\"no port given\")\n//! assert(checked.is_err(), \"None became an Err\")\n//!\n//! // An iterator\'s `filter` and `map` are lazy; `collect` runs them.\n//! let mut nums: Vec<Int> = Vec::new()\n//! for n in 1..6 { nums.push(n) }\n//! let tens = nums.iter().filter(|n| n % 2 == 0).map(|n| n * 10).collect()\n//! assert_eq(tens.len(), 2)\n//! assert_eq(tens.get(1).unwrap(), 40)\n//! ```\n\n// Nova standard library \u{2014} core.\n//\n// Compiled as an implicit module and glob-imported into every user module, so\n// these names need no `import`. A user definition of the same name shadows the\n// one here (see docs/adr/0004-stdlib-compile-model.md).\n\n/// A value that may be absent: `Some` value, or `None`.\npub type Option<T> =\n /// Holds a value.\n | Some(T)\n /// Holds no value.\n | None\n\n/// The outcome of an operation that can fail: `Ok` with a value, or `Err`\n/// with an error.\npub type Result<T, E> =\n /// Holds the value of a success.\n | Ok(T)\n /// Holds the error of a failure.\n | Err(E)\n\nimpl<T> Option<T> {\n /// Returns `true` if the option is `Some`.\n pub fn is_some(self) -> Bool {\n match self {\n Some(_) => true\n None => false\n }\n }\n\n /// Returns `true` if the option is `None`.\n pub fn is_none(self) -> Bool { !self.is_some() }\n\n /// Applies `f` to the value, if there is one.\n ///\n /// Returns `Some(f(v))` for `Some(v)`, and `None` for `None`.\n pub fn map<U>(self, f: fn(T) -> U) -> Option<U> {\n match self {\n Some(v) => Some(f(v))\n None => None\n }\n }\n\n /// Calls `f` with the value, if there is one, and returns its result.\n ///\n /// Returns `None` for `None`, without calling `f`.\n pub fn and_then<U>(self, f: fn(T) -> Option<U>) -> Option<U> {\n match self {\n Some(v) => f(v)\n None => None\n }\n }\n\n /// Returns the value.\n ///\n /// Panics if the option is `None`.\n pub fn unwrap(self) -> T {\n match self {\n Some(v) => v\n None => panic(\"called `unwrap` on a `None` value\")\n }\n }\n\n /// Returns the value, or `default` if the option is `None`.\n pub fn unwrap_or(self, default: T) -> T {\n match self {\n Some(v) => v\n None => default\n }\n }\n\n /// Converts the option to a `Result`: `Ok(v)` for `Some(v)`, and\n /// `Err(err)` for `None`.\n pub fn ok_or<E>(self, err: E) -> Result<T, E> {\n match self {\n Some(v) => Ok(v)\n None => Err(err)\n }\n }\n}\n\nimpl<T, E> Result<T, E> {\n /// Returns `true` if the result is `Ok`.\n pub fn is_ok(self) -> Bool {\n match self {\n Ok(_) => true\n Err(_) => false\n }\n }\n\n /// Returns `true` if the result is `Err`.\n pub fn is_err(self) -> Bool { !self.is_ok() }\n\n /// Applies `f` to the value of an `Ok`, leaving an `Err` as it is.\n pub fn map<U>(self, f: fn(T) -> U) -> Result<U, E> {\n match self {\n Ok(v) => Ok(f(v))\n Err(e) => Err(e)\n }\n }\n\n /// Applies `f` to the error of an `Err`, leaving an `Ok` as it is.\n pub fn map_err<F>(self, f: fn(E) -> F) -> Result<T, F> {\n match self {\n Ok(v) => Ok(v)\n Err(e) => Err(f(e))\n }\n }\n\n /// Calls `f` with the value of an `Ok` and returns its result.\n ///\n /// Returns an `Err` as it is, without calling `f`.\n pub fn and_then<U>(self, f: fn(T) -> Result<U, E>) -> Result<U, E> {\n match self {\n Ok(v) => f(v)\n Err(e) => Err(e)\n }\n }\n\n /// Returns the value of an `Ok`.\n ///\n /// Panics if the result is an `Err`.\n pub fn unwrap(self) -> T {\n match self {\n Ok(v) => v\n Err(_) => panic(\"called `unwrap` on an `Err` value\")\n }\n }\n\n /// Returns the value of an `Ok`, or `default` for an `Err`.\n pub fn unwrap_or(self, default: T) -> T {\n match self {\n Ok(v) => v\n Err(_) => default\n }\n }\n}\n\n// Core traits, and their impls for the five primitive types.\n//\n// `Ord` cannot be written uniformly: `<` works for Int/Float/Char but not\n// for Bool or String (E0013 for both). Bool is ordered with `if` alone;\n// String has neither length nor indexing in Nova, so it goes through\n// `str_cmp`, a compiler builtin (see `nova-resolver`\'s `Builtin` enum) that\n// reaches the runtime\'s byte-lexicographic `nova_rt_str_cmp` directly: a\n// named function, resolved specially by the compiler and lowered straight to\n// a runtime call \u{2014} the same way `println`/`print`/`panic` reach the runtime.\n// This is *not* how `==` on `String` reaches `nova_rt_str_eq`: `==` is a\n// pure operator lowering (`binary_result_ty` permits `Eq`/`Ne` for\n// `Ty::String`; MIR\'s `lower_binary` intercepts it) that introduces no name\n// in any namespace, so it has no \"reserved word\" concern to begin with.\n// `str_cmp` does, and unlike `println`/`print`/`panic` it is not meant to be\n// user-visible language surface, so it is seeded only into std modules\' own\n// scopes (`Builtin::STD_ONLY`), not into every module \u{2014} a user program\n// may freely define its own `str_cmp` (String is not FFI-safe, and\n// `nova_`-prefixed extern symbols are reserved by the compiler, so a\n// user-visible `extern` was not an option either).\n\n// `Hash` reaches the runtime the same way, through two more std-only\n// builtins: `str_hash` (no primitive walks a `String`, so a NAMED operation\n// over its bytes needs a builtin -- `==` reaches the runtime as a plain\n// operator lowering and introduces no name, so it is not one; an absence\n// about the primitive layer, NOT\n// about what Nova code can reach, since `std/bytes` and `std/strings` build\n// byte and char access on builtins of this kind and this module walks a\n// string itself at `impl Debug for String` below; an earlier wording here\n// read as the wider claim and was quoted as one, which ADR 0005\'s 2026-08-27\n// amendment records) and `char_to_int` (Nova has no `as` casts and\n// no other `Char` -> `Int` conversion). `char_to_int` is the one builtin that\n// is *not* a runtime call \u{2014} `Char` and `Int` are the same machine class, so\n// nova-mir lowers it to a register move. See ADR 0005 section 2 for why\n// `Hash` is one-shot (`fn hash(self) -> Int`) rather than streaming, and why\n// there is deliberately no `Hash for Float`.\n\n/// The result of comparing two values, as `Ord::cmp` returns it.\npub type Ordering =\n /// The first value is less than the second.\n | Less\n /// The two values are equal.\n | Equal\n /// The first value is greater than the second.\n | Greater\n\n/// A type whose values can be shown as text for people to read.\n///\n/// String interpolation, `\"${value}\"`, uses it for a value of a type that\n/// implements it.\npub trait Display {\n /// Returns the value as text.\n fn fmt(self) -> String\n}\n\n/// A type whose values can be shown as text for debugging.\npub trait Debug {\n /// Returns the value as text for debugging.\n ///\n /// For `Int`, `Float` and `Bool` it is the text `Display` gives. A `Char`\n /// or `String` comes out as a quoted Nova literal, escaped so that it\n /// reads back as the same value.\n fn dbg(self) -> String\n}\n\n/// A type whose values can be compared for equality.\npub trait Eq {\n /// Returns `true` if `self` equals `other`.\n ///\n /// For `Float`, `NaN` equals no value, not even itself.\n fn eq(self, other: Self) -> Bool\n /// Returns `true` if `self` does not equal `other`.\n ///\n /// By default it is the opposite of `eq`.\n fn ne(self, other: Self) -> Bool { !self.eq(other) }\n}\n\n/// A type whose values are ordered.\npub trait Ord: Eq {\n /// Returns whether `self` is less than, equal to or greater than `other`.\n ///\n /// std orders `false` before `true`, a `Char` by its code point, and a\n /// `String` by its UTF-8 bytes. For `Float`, how `NaN` orders is\n /// unspecified: today any comparison involving it gives `Greater`, even\n /// `NaN` with itself.\n fn cmp(self, other: Self) -> Ordering\n}\n\n/// A type whose values can be copied.\npub trait Clone {\n /// Returns a copy of `self`.\n fn clone(self) -> Self\n}\n\n/// A type with a default value.\npub trait Default {\n /// Returns the type\'s default value.\n ///\n /// For `Int`, `Float`, `Bool`, `Char` and `String` it is `0`, `0.0`,\n /// `false`, `\'\\0\'` and `\"\"`.\n fn default() -> Self\n}\n\n// One-shot hashing: a value\'s hash is a single `Int`, not a stream folded into\n// a `Hasher` (ADR 0005 section 2). There is no `Hash for Float` on purpose:\n// NaN never equals itself, so a NaN key would be unreachable in a hash map,\n// and `0.0`/`-0.0` are `==` but would hash differently.\n//\n// An implementor\'s contract: if `a.eq(b)` then `a.hash() == b.hash()`.\n//\n// HOW TO USE A HASH: **mask it. Never shift it, and never read its high\n// bits.** `hash & (cap - 1)` over a power-of-two capacity is the only\n// supported way to turn a hash into a bucket index, for three separate\n// reasons:\n//\n// - `hash % cap` can be *negative*: `str_hash` reinterprets an unsigned\n// 64-bit result as `Int`, and `mix64` spans the full `Int` range too, so a\n// remainder inherits the sign. `&` with a positive mask is non-negative\n// for every `Int`.\n// - The high bits are not a usable second hash. A `hash >> 57`-style tag\n// byte is *not* independent of the low bits used for the bucket, and for\n// `str_hash` a negative hash sign-extends into any such tag, so the tag\n// loses half its range on exactly the keys that need distinguishing.\n// - `mix64`\'s guarantees are stated over its whole 64-bit result; nothing\n// promises that any particular slice of it is uniform on its own.\n/// A type whose values can be hashed to an `Int`.\n///\n/// A `Map`\'s keys and a `Set`\'s values must implement it, and `Eq`.\n/// Two values equal by `eq` must have the same hash. `Float` has no impl:\n/// `NaN` equals no value, and `0.0` and `-0.0` are equal though their bits\n/// differ.\n///\n/// A record of your own as a `Map` key, with `Eq` and `Hash` that\n/// agree:\n///\n/// ```\n/// record Point { x: Int, y: Int }\n///\n/// impl Eq for Point {\n/// fn eq(self, other: Point) -> Bool { self.x == other.x && self.y == other.y }\n/// }\n///\n/// // Points equal by `eq` must hash alike, so combine the fields\' hashes.\n/// impl Hash for Point {\n/// fn hash(self) -> Int { self.x.hash() * 31 + self.y.hash() }\n/// }\n///\n/// fn main() {\n/// let mut names: Map<Point, String> = Map::new()\n/// names.insert(Point { x: 0, y: 0 }, \"origin\")\n/// assert_eq(names.get(Point { x: 0, y: 0 }).unwrap(), \"origin\")\n/// assert(!names.contains_key(Point { x: 1, y: 0 }), \"a different point\")\n/// }\n/// ```\npub trait Hash {\n /// Returns the value\'s hash.\n ///\n /// A hash can be negative. To pick one of `n` buckets, where `n` is a\n /// power of two, mask it, `hash & (n - 1)`, rather than taking a\n /// remainder, which can be negative, or using its high bits. std seeds\n /// the hashes of `Int`, `Bool`, `Char` and `String` once per run, so they\n /// can differ from one run of a program to the next.\n fn hash(self) -> Int\n}\n\n// The iteration protocol, and the first trait in this file with an associated\n// type. `next` advances the iterator and yields the next element, or `None`\n// once exhausted; `Item` is what it yields, chosen by the implementor.\n//\n// `mut self` is load-bearing rather than stylistic: an iterator has to advance,\n// which means mutating its own state, so a `next` taking plain `self` would\n// either not advance or advance invisibly. It is also the first `mut self` in\n// any `impl Trait for Type` in std \u{2014} closing the trait-method half of the\n// mutable-receiver rule was a hard gate before this trait could be declared at\n// all (ADR 0005 \u{a7}1). The consequence for callers: calling `next` itself needs\n// the iterator held in a `mut` binding or arriving as a `mut` parameter, or\n// the call is `E0060` \u{2014} true of `next` specifically, and no longer true of\n// the four default consumer methods below (see the comment above `fold`).\n//\n// `Option<Self::Item>` is the projection this whole increment exists to make\n// expressible. It is deliberately spelled with `::` and not the `.` that\n// nova-spec/20-STDLIB.md used, because `::` is already how Nova reaches into a\n// type (`Vec::new`, `T::default`) while `.` is field access everywhere else.\n//\n// `map`/`filter`/`fold`/`count`/`any`/`collect` are default methods below,\n// so a caller reaches `MapIter`/`FilterIter` (see below) through `.map()`/\n// `.filter()` and never has to name them directly. Still NOT YET, and still\n// deliberately deferred rather than overlooked: `IntoIterator`, so `for x in\n// v` does not work \u{2014} write `v.iter()`. `Map::iter` is not merely unwritten\n// but impossible \u{2014} it would yield a pair and Nova has no tuples. Iterating\n// means a hand-written `while` plus a `match` on the `Option`, or `for x in\n// it`, or now one of the six methods below.\n//\n// Unlike the traits above, this one is implemented for **no** primitive, so\n// `next` is not taken away from user code on `Int`/`Float`/`Bool`/`Char`/\n// `String` the way each of *their* methods is (ADR 0004, \"Method names are not\n// soft-reserved\"). A user `trait Feed { fn next(...) }` stays usable on those\n// types.\n//\n// Deliberately no count and no method list here. Both used to be written out \u{2014}\n// \"the **six** traits above\" and `fmt`/`eq`/`cmp`/`clone`/`default` \u{2014} and both\n// were wrong by the time anyone read them: `Hash` landing in Phase 2.2a left\n// the tally short, and the list silently omitted `dbg` and `hash`. \"Six\" was\n// correct when written, and the list was never complete. A hand-maintained\n// tally of \"the traits above\", in the one file that gains traits, drifts by\n// construction; grep `^pub trait` above this line for the current set, and the\n// `impl <Trait> for <primitive>` block near the bottom of this file for which\n// of their methods each primitive really has.\n/// A source of values, yielded one at a time by `next`.\n///\n/// A `for` loop runs over any iterator: `for x in v.iter()`. `map` and\n/// `filter` are lazy, and `fold`, `count`, `any` and `collect` consume the\n/// iterator. A record iterator is shared, not copied: the one these methods\n/// were called on is the one that advances, even when it is held in a\n/// binding that is not `mut`.\n///\n/// The adapters are lazy; a consumer runs them:\n///\n/// ```\n/// let mut words: Vec<String> = Vec::new()\n/// words.push(\"map\")\n/// words.push(\"filter\")\n/// words.push(\"fold\")\n///\n/// // `filter` and `map` do nothing until a consumer such as `fold` runs them.\n/// // A closure that calls a method on its parameter names the parameter\'s type.\n/// let lengths = words.iter().filter(|w: String| w.starts_with(\"f\")).map(|w: String| w.len())\n/// assert_eq(lengths.fold(0, |acc, n| acc + n), 10)\n/// assert(words.iter().any(|w| w == \"map\"), \"`any` stops at the first match\")\n/// ```\npub trait Iterator {\n /// The type of the values the iterator yields.\n type Item\n /// Advances the iterator and returns its next value, or `None` when it\n /// has no more.\n ///\n /// Calling it needs a mutable iterator, such as one held in a `mut`\n /// binding.\n fn next(mut self) -> Option<Self::Item>\n\n // --- adapters (lazy: nothing is consumed until a consumer runs) ---\n\n /// Returns an iterator that yields `f(x)` for each value `x` of this one.\n ///\n /// It is lazy: it calls `f` only as it is advanced.\n fn map<U>(self, f: fn(Self::Item) -> U) -> MapIter<Self, U> { MapIter { it: self, f: f } }\n\n /// Returns an iterator that yields the values of this one for which\n /// `keep` returns `true`.\n ///\n /// It is lazy: it calls `keep` only as it is advanced.\n fn filter(self, keep: fn(Self::Item) -> Bool) -> FilterIter<Self> {\n FilterIter { it: self, keep: keep }\n }\n\n // --- consumers (each drives the iterator to exhaustion or short-circuits) ---\n\n // Plain `self`, not `mut self`, on all four consumers below \u{2014} `next` is\n // still `mut self` (it is the one method a caller invokes repeatedly on a\n // binding they hold), but a consumer runs to exhaustion in one call, so it\n // does not need its *own* receiver to already be a mutable place; it only\n // needs a mutable place to drive `next` through, and it makes its own with\n // `let mut it = self`. Records are heap objects with no copy semantics\n // anywhere in this compiler, so for a record `Self` `it` is an alias of\n // exactly the storage `self` pointed to, not a copy \u{2014} advancing `it`\n // advances the same iterator the caller passed in.\n // `an_iterators_own_storage_still_advances_when_a_consumer_takes_\n // plain_self` (`crates/nova-cli/tests/run_tests.rs`) pins the aliasing.\n //\n // \"For a record `Self`\" is a real condition, not a hedge: nothing in this\n // trait requires one. `impl Iterator for Int` compiles, a primitive is\n // passed by value, so the rebind copies and all four consumers **diverge**\n // rather than returning a wrong number. Pre-existing (hand-driving such an\n // impl loops forever too) and measured \u{2014} see ADR 0007 \u{a7}2, \"Why it is safe\".\n //\n // This is what lets `v.iter().filter(f).map(g).collect()` \u{2014} the form this\n // feature exists to make possible \u{2014} compile at all: `.filter()`/`.map()`\n // each return a temporary, and only a plain-`self` method can be called on\n // one (`place_root` classifies a call result `PlaceRoot::NotAPlace`, and a\n // `mut self` receiver requires `PlaceRoot::Mutable`).\n //\n // Dropping `mut self` relaxes *two* of `place_root`\'s classifications, not\n // only the one this design needed: `NotAPlace` (the temporary above, the\n // actual goal) and, as a side effect, `ImmutableLocal` too \u{2014} a caller may\n // now hold the iterator in a binding that is never declared `mut` at all,\n // and one of these four methods still silently advances or fully consumes\n // it:\n //\n // let it = some_record // NOT mut\n // it.count() // 3\n // it.count() // 0 -- silently advanced, no diagnostic\n //\n // Under `mut self` the first call alone was `E0060`. This is not a new\n // capability, only a wider door to an old one: the compiler\'s own\n // `for x in <expr>` desugar already launders exactly this way\n // (`check_for_iterator`, `crates/nova-typeck/src/check.rs`:\n // `let mut __it = <expr>`), so `for x in <an immutable local>` already\n // advanced that local before this trait had a single default method \u{2014}\n // this is that laundering\'s first appearance in a *library* API, not a\n // new mechanism. Nor does any new iterator *state* become reachable: a\n // `mut` binding could always be partially consumed and reused. The only\n // thing that changed is which receivers these four methods accept\n // syntactically.\n // `iterator_any_short_circuits_and_does_not_scan_past_the_first_match`\n // (`crates/nova-cli/tests/run_tests.rs`) pins a non-`mut` receiver being\n // silently advanced through `any` as accepted, current behavior.\n\n // The fold primitive. `count` and `collect` could be written over it;\n // `any` cannot, because `fold` visits every element and `any` must stop.\n /// Folds the values into one, calling `f(acc, x)` for each value `x`.\n ///\n /// `acc` starts as `init` and becomes each call\'s result, and the last\n /// result is returned. Returns `init` if there are no values.\n fn fold<A>(self, init: A, f: fn(A, Self::Item) -> A) -> A {\n let mut it = self\n let mut acc = init\n while true {\n let n = it.next()\n if n.is_none() { return acc }\n let g = f\n acc = g(acc, n.unwrap())\n }\n acc\n }\n\n // `count`, not `len`: this consumes the iterator, where `Vec::len` is cheap\n // and non-destructive. Naming it `len` would invite the wrong assumption.\n /// Counts the values, consuming the iterator.\n fn count(self) -> Int {\n let mut it = self\n let mut n = 0\n while true {\n let x = it.next()\n if x.is_none() { return n }\n n = n + 1\n }\n n\n }\n\n // Short-circuits, which is why it is not written over `fold`.\n /// Returns `true` if `p` returns `true` for any value, and `false`\n /// otherwise.\n ///\n /// It stops at the first value `p` accepts.\n fn any(self, p: fn(Self::Item) -> Bool) -> Bool {\n let mut it = self\n while true {\n let n = it.next()\n if n.is_none() { return false }\n let q = p\n if q(n.unwrap()) { return true }\n }\n false\n }\n\n // Returns a `Vec`, which makes `std/core` depend on `std/collections` for\n // the first time. Accepted deliberately: one method, one type, and the\n // whole-program merge means there is no layering mechanism to violate, only\n // a convention. The alternative was `Vec::from_iter(it)` in\n // `std/collections`, which keeps `std/core` free of collections and reads\n // worse at the call site.\n /// Collects the values into a `Vec`, in order.\n fn collect(self) -> Vec<Self::Item> {\n let mut it = self\n let mut out = Vec::new()\n while true {\n let n = it.next()\n if n.is_none() { return out }\n out.push(n.unwrap())\n }\n out\n }\n}\n\n// A lazy `map`: yields `f(x)` for each `x` the inner iterator yields.\n//\n// `f: fn(I::Item) -> U` is why `I` carries a bound. A bound on a record\'s type\n// parameter is a resolution scope, not a constraint (ADR 0007): it lets this\n// field name `I::Item` at all, and it is not itself checked when a `MapIter`\n// is built \u{2014} `impl<I: Iterator, U> Iterator for MapIter<I, U>` below is what\n// makes a `MapIter` iterable, not this declaration.\n//\n// That does not make a `MapIter<Int, U>` freely buildable, though: `f`\'s own\n// field type names `I::Item`, and `Int::Item` has nothing to resolve to (`Int`\n// has no `Iterator` impl), so `f`\'s declared type never normalizes. What\n// happens then depends on the closure and on reachability, and it is ADR 0007\n// \u{a7}1 (case 1, and its routing table) that has the mechanism \u{2014} read it there\n// rather than reconstructing it from here. Two things this comment used to get\n// wrong, both measured:\n//\n// - \"no closure \u{2014} none, for any `f` \u{2014} can unify against it\" is **false**.\n// `MapIter { it: 5, f: |x| x }` produces no unification error at all:\n// typeck accepts it and monomorphization refuses it with\n// `error[E0079]: \'Int::Item\' is still an unresolved associated type after\n// instantiating \'main\'`. A fresh inference variable binds to an\n// unnormalized projection just as happily as to a concrete type. Only an\n// *annotated* closure fails to unify \u{2014} `f: |x: Int| x` is\n// `error[E0010]: field \'f\' expects \'fn(Int::Item) -> ?N\' but found\n// \'fn(Int) -> Int\'`, plus four `E0011`s for the variables it left free.\n// - \"unconstructible\" full stop, and \"caught at construction\" full stop, are\n// **false when the construction is not reachable from `main`**, because the\n// mechanism is monomorphization and it inherits monomorphization\'s reach. A\n// `MapIter { it: 5, f: |x| x }` inside a function `main` never calls is\n// accepted: `nova check` exits 0 with no diagnostic and the program runs.\n// ADR 0007 \u{a7}1 states the qualifier and shows the measurement.\n//\n// So: a bad instantiation of these two shapes is refused wherever it is\n// actually instantiated, and nowhere else. That is still earlier and stronger\n// than the bound itself promises \u{2014} the bound was meant to leave construction\n// unconstrained and block only *use* as an iterator \u{2014} and it still has nothing\n// to do with the bound.\n//\n// Holds `it` by pointer, like every record, so it SHARES the source iterator\n// rather than copying it \u{2014} advancing this adapter advances the source, and\n// mutating the source mid-iteration is observable. Same alias visibility\n// `VecIter` documents; preventing it needs borrow tracking Nova lacks.\n/// An iterator that yields a function\'s result for each value of another.\n///\n/// `Iterator::map` returns one. It shares the iterator it wraps rather than\n/// copying it.\npub record MapIter<I: Iterator, U> { it: I, f: fn(I::Item) -> U }\n\nimpl<I: Iterator, U> Iterator for MapIter<I, U> {\n type Item = U\n fn next(mut self) -> Option<U> {\n let n = self.it.next()\n if n.is_none() {\n None\n } else {\n // Bound to a local first: `(self.f)(x)` is `E0014: no method f`.\n let g = self.f\n Some(g(n.unwrap()))\n }\n }\n}\n\n// A lazy `filter`: yields only the elements `keep` accepts.\n//\n// `type Item = I::Item` is a projection-valued binding \u{2014} the associated type is\n// itself a projection \u{2014} which is the `Assoc { on: Assoc }` shape Phase 2.2c\n// could only reach from a hand-built unit test. This is its first appearance in\n// real source.\n//\n// `I`\'s bound is a resolution scope here for the same reason it is on `MapIter`\n// above \u{2014} it is what lets `keep` name `I::Item` at all, and it is not checked\n// when a `FilterIter` is built. See `MapIter`\'s comment and ADR 0007 \u{a7}1 (case 1\n// and its routing table) for the full account, including what actually happens\n// to a `FilterIter<Int>`: it is refused wherever it is instantiated \u{2014} measured,\n// `FilterIter { it: 5, keep: |x| true }` in `main` is one `E0079` from\n// monomorphization, and `keep: |x: Int| true` is instead one `E0010` naming\n// `fn(Int::Item) -> Bool` \u{2014} but **not** when the construction site is\n// unreachable from `main`, since the mechanism is monomorphization. This\n// comment previously said \"unconstructible\" without that qualifier.\n/// An iterator that yields the values of another that a predicate accepts.\n///\n/// `Iterator::filter` returns one. It shares the iterator it wraps rather\n/// than copying it.\npub record FilterIter<I: Iterator> { it: I, keep: fn(I::Item) -> Bool }\n\nimpl<I: Iterator> Iterator for FilterIter<I> {\n type Item = I::Item\n fn next(mut self) -> Option<I::Item> {\n // `while true`, not `loop`: Nova has no `loop` keyword.\n while true {\n let n = self.it.next()\n if n.is_none() { return None }\n let p = self.keep\n if p(n.unwrap()) { return Some(n.unwrap()) }\n }\n None\n }\n}\n\nimpl Display for Int {\n fn fmt(self) -> String { \"${self}\" }\n}\n\nimpl Display for Float {\n fn fmt(self) -> String { \"${self}\" }\n}\n\nimpl Display for Bool {\n fn fmt(self) -> String { \"${self}\" }\n}\n\nimpl Display for Char {\n fn fmt(self) -> String { \"${self}\" }\n}\n\nimpl Display for String {\n fn fmt(self) -> String { self }\n}\n\n// `Debug`\'s contract is that its output is a *Nova literal* for the value, so\n// `Char` and `String` are quoted where `Display` is not. Nova\'s lexer accepts\n// `\\n \\t \\r \\\\ \\0 \\u{\u{2026}}` plus `\\\"` in a string literal and `\\\'` in a char\n// literal (`nova-lexer`\'s string scanner and `lex_char`); `\\\"` is not valid in\n// a char literal, nor `\\\'` in a string one, so each form escapes the quote\n// that delimits it, plus the backslash. `String` also escapes every `$` (as\n// `\\u{24}`): a string literal, unlike a char literal, opens an interpolation\n// hole on `$` immediately followed by `{`, so a literal `$` left in the\n// output could silently reopen one when the output is pasted back as\n// source. `Char` never interpolates, so it needs no such rule.\nimpl Debug for Int {\n fn dbg(self) -> String { \"${self}\" }\n}\n\nimpl Debug for Float {\n fn dbg(self) -> String { \"${self}\" }\n}\n\nimpl Debug for Bool {\n fn dbg(self) -> String { \"${self}\" }\n}\n\n// The escape sequence for `c` inside a string literal, or `None` when `c`\n// needs none. Quoting differs between a `Char` literal and a `String`\n// literal, so the quote characters are the callers\' business: `Debug for\n// Char` escapes `\'`, `Debug for String` escapes `\"`, and both need the rest\n// of this identically \u{2014} shared here rather than duplicated a second time, the\n// way `Map::get`/`remove`\'s probe scan was in Phase 2.2a.\nfn escape_common(c: Char) -> Option<String> {\n if c == \'\\\\\' { return Some(\"\\\\\\\\\") }\n if c == \'\\n\' { return Some(\"\\\\n\") }\n if c == \'\\t\' { return Some(\"\\\\t\") }\n if c == \'\\r\' { return Some(\"\\\\r\") }\n if c == \'\\0\' { return Some(\"\\\\0\") }\n None\n}\n\n// `\'` is the one escape `Char` needs that `escape_common` does not cover\n// (mirrored by `\"` in `Debug for String` below), so it is handled directly;\n// everything else comes from `escape_common`. The escaped set is exactly\n// what `lex_char` accepts, so every output here round-trips back through the\n// lexer to `self`. A raw newline/tab/NUL does lex inside `\'\u{2026}\'`, but emitting\n// one would put a control character in the middle of debug output, which\n// defeats the purpose.\nimpl Debug for Char {\n fn dbg(self) -> String {\n if self == \'\\\'\' {\n \"\'\\\\\'\'\"\n } else {\n match escape_common(self) {\n Some(e) => \"\'${e}\'\"\n None => \"\'${self}\'\"\n }\n }\n }\n}\n\n// `str_chars` (a `Builtin::STD_ONLY` member added for `std/strings`, so it is\n// already visible here with no import and no dependency on `std/strings`)\n// lets this inspect the string\'s contents directly \u{2014} which turned out to be\n// all that closing this ever needed. No dedicated ABI symbol was added: `\"`\n// is handled the same way `\'` is handled above; `$` gets its own arm too,\n// escaped unconditionally as `\\u{24}` rather than only when immediately\n// followed by `{` \u{2014} a plain per-character rule like every other entry here,\n// with no lookahead to get wrong, and it costs nothing since a `$` not\n// before `{` was already safe to leave alone. That arm has to live here\n// rather than in `escape_common`: `\\u{24}` does not lex inside a char\n// literal (`\'\\u{24}\'` fails with `unexpected character \'`), so routing it\n// through the shared helper would make `Debug for Char` emit `\'\\u{24}\'`,\n// which does not parse; `\\$` is not an escape sequence either. Everything\n// else comes from `escape_common`. Building `out` by repeated interpolation\n// (rather than `str_from_chars`) is quadratic in the string\'s length, since\n// each `${out}${piece}` copies `out` again; `dbg` is a diagnostic path, not\n// a hot one, so that trade is the right one rather than pretending\n// otherwise.\nimpl Debug for String {\n fn dbg(self) -> String {\n let cs = str_chars(self)\n let mut out = \"\\\"\"\n for i in 0..cs.len() {\n let c = cs[i]\n if c == \'\"\' {\n out = \"${out}\\\\\\\"\"\n } else if c == \'$\' {\n out = \"${out}\\\\u{24}\"\n } else {\n match escape_common(c) {\n Some(e) => out = \"${out}${e}\"\n None => out = \"${out}${c}\"\n }\n }\n }\n \"${out}\\\"\"\n }\n}\n\nimpl Eq for Int {\n fn eq(self, other: Int) -> Bool { self == other }\n}\n\n// Not reflexive for NaN: `NaN == NaN` is `false`, so `eq(NaN, NaN)` is\n// `false` too (NaN is reachable, e.g. via `0.0 / 0.0`). See the `Ord for\n// Float` impl below for the related non-total-order caveat.\nimpl Eq for Float {\n fn eq(self, other: Float) -> Bool { self == other }\n}\n\nimpl Eq for Bool {\n fn eq(self, other: Bool) -> Bool { self == other }\n}\n\nimpl Eq for Char {\n fn eq(self, other: Char) -> Bool { self == other }\n}\n\nimpl Eq for String {\n fn eq(self, other: String) -> Bool { self == other }\n}\n\nimpl Ord for Int {\n fn cmp(self, other: Int) -> Ordering {\n if self < other { Less } else { if self == other { Equal } else { Greater } }\n }\n}\n\nimpl Ord for Float {\n // Not a total order for NaN: `<` and `==` are both `false` whenever\n // either operand is NaN, so this falls through to `Greater` for any\n // comparison involving NaN \u{2014} including `cmp(NaN, NaN)`, which is\n // `Greater`, not `Equal`. Ordering NaN is unspecified; do not rely on it\n // (e.g. for a future sorted collection) until addressed by design.\n fn cmp(self, other: Float) -> Ordering {\n if self < other { Less } else { if self == other { Equal } else { Greater } }\n }\n}\n\nimpl Ord for Char {\n fn cmp(self, other: Char) -> Ordering {\n if self < other { Less } else { if self == other { Equal } else { Greater } }\n }\n}\n\nimpl Ord for Bool {\n // `<` is not defined for Bool; false sorts before true.\n fn cmp(self, other: Bool) -> Ordering {\n if self { if other { Equal } else { Greater } } else { if other { Less } else { Equal } }\n }\n}\n\nimpl Ord for String {\n // String has neither length nor indexing in Nova, so ordering comes from\n // `str_cmp`, a compiler builtin backed by the runtime\'s byte-lexicographic\n // compare (see the module-level note above for why not `extern`).\n fn cmp(self, other: String) -> Ordering {\n let c = str_cmp(self, other)\n if c < 0 { Less } else { if c == 0 { Equal } else { Greater } }\n }\n}\n\nimpl Clone for Int {\n fn clone(self) -> Int { self }\n}\n\nimpl Clone for Float {\n fn clone(self) -> Float { self }\n}\n\nimpl Clone for Bool {\n fn clone(self) -> Bool { self }\n}\n\nimpl Clone for Char {\n fn clone(self) -> Char { self }\n}\n\nimpl Clone for String {\n fn clone(self) -> String { self }\n}\n\nimpl Default for Int {\n fn default() -> Int { 0 }\n}\n\nimpl Default for Float {\n fn default() -> Float { 0.0 }\n}\n\nimpl Default for Bool {\n fn default() -> Bool { false }\n}\n\nimpl Default for Char {\n fn default() -> Char { \'\\0\' }\n}\n\nimpl Default for String {\n fn default() -> String { \"\" }\n}\n\n// The splitmix64 finalizer: three xor-shift/multiply rounds. `Map` selects\n// buckets with `hash & (cap - 1)`, so it is the *low* bits that must be\n// spread; `fn hash(self) -> Int { self }` would send every multiple of the\n// capacity to bucket 0. A known-good mixer is used rather than an invented\n// one, and this is bit-identical to the canonical splitmix64 finalizer.\n//\n// Getting there needs two workarounds for what `Int` cannot express, and both\n// are load-bearing rather than cosmetic:\n//\n// - The constants are `0xbf58476d1ce4e5b9` and `0x94d049bb133111eb`, which\n// exceed `Int`\'s range, so they are written as the two\'s-complement\n// negatives of those bit patterns. Hex is not an option \u{2014} the lexer\'s\n// `lex_hex_int` parses as `i64`, so `0xbf58\u{2026}` silently fails to lex \u{2014} but\n// each negative *is* `-` applied to a decimal literal below `i64::MAX`,\n// which lexes, and `*` wraps rather than trapping, so the arithmetic\n// agrees modulo 2^64.\n// - Nova\'s `>>` is **arithmetic** and there is no `>>>`, so each shift is\n// masked to clear the sign extension: `& (2^(64-k) - 1)`, i.e.\n// `17179869183` for `>> 30`, `137438953471` for `>> 27`, `8589934591`\n// for `>> 31`. The mask is not optional. Without it, arithmetic shift\n// commutes with complement (`!(x >> k) == (!x) >> k`) and XOR is\n// invariant under complementing both operands, so `x ^ (x >> k)` returns\n// the *same value* for `x` and `!x == -1 - x`. Every later stage is a\n// function of that output, so the whole finalizer folded 2-to-1 with\n// `mix64(x) == mix64(-1 - x)` \u{2014} identical hashes, not merely congruent\n// ones, so each pair shared a bucket at *every* capacity and no resize\n// could ever separate them. Pinned by `tests/runtime/hash.nova`.\n//\n// NOT SEEDED, and that is a decision rather than an oversight. The\n// per-process seed is XORed into the *input* by the `Int`, `Bool` and `Char`\n// `Hash` impls below, before this function runs, so `mix64` itself stays\n// bit-identical to canonical splitmix64\'s finalizer and the canonical vectors\n// in `tests/runtime/hash.nova` keep testing the same function they always\n// tested.\n//\n// The masks stay load-bearing for exactly the reason given above, because\n// seeding does not rescue an unmasked finalizer. XOR with a constant commutes\n// with complement \u{2014} `(!k) ^ s == !(k ^ s)` \u{2014} so an unmasked stage 1 still maps\n// `k ^ s` and `!(k ^ s)` to one value, and the pair `k`, `!k` still folds\n// together whatever the seed is.\n//\n// Module-private, and it stays that way: ADR 0005 records the privacy as a\n// decision, since this is an implementation detail of the primitive impls\n// rather than a published utility and publishing it would make its exact\n// definition a compatibility surface, and the same ADR reserves the freedom to\n// replace these constants or rounds. So `tests/runtime/hash.nova` cannot call\n// this function at all; it recovers the seed from `(0).hash()` and cancels it,\n// carrying its own inverse of the arithmetic below. If these constants ever\n// change, that inverse changes with them.\nfn mix64(x: Int) -> Int {\n let a = x ^ ((x >> 30) & 17179869183)\n let b = a * -4658895280553007687\n let c = b ^ ((b >> 27) & 137438953471)\n let d = c * -7723592293110705685\n d ^ ((d >> 31) & 8589934591)\n}\n\n// The per-process seed goes into `mix64`\'s INPUT, not its output, and that is\n// load-bearing rather than stylistic. `Map` selects buckets with\n// `hash & (cap - 1)`, so post-XOR \u{2014} `mix64(x) ^ int_hash_seed()` \u{2014} would leave\n// the low bits as `(mix64(x) & mask) XOR (seed & mask)`, which *permutes*\n// buckets and leaves every colliding pair still colliding. It would look like\n// seeding and buy nothing.\n//\n// What pre-XOR buys is precomputation resistance: a key set built to collide\n// against one process, or offline, does not collide here. What it does not\n// claim, and how Nova code can recover the seed in one call, is at\n// `int_hash_seed` in the resolver and `nova_rt_int_hash_seed` in the runtime.\n// A consequence worth stating where the reader meets it: an `Int`, `Bool` or\n// `Char` hashes to one value for the whole of a run and can hash to a\n// different one in the next run of the same program.\nimpl Hash for Int {\n fn hash(self) -> Int { mix64(self ^ int_hash_seed()) }\n}\n\nimpl Hash for Bool {\n fn hash(self) -> Int {\n if self { mix64(1 ^ int_hash_seed()) } else { mix64(0 ^ int_hash_seed()) }\n }\n}\n\n// Hashes the Unicode scalar value, so it agrees with `Hash for Int` on that\n// codepoint. `char_to_int` is a compiler builtin because Nova has no `as`\n// casts and `Char` has no other conversion.\nimpl Hash for Char {\n fn hash(self) -> Int { mix64(char_to_int(self) ^ int_hash_seed()) }\n}\n\n// Seeded FNV-1a over the bytes then splitmix64\'s finalizer, in the runtime\n// (see the module note above), with its unsigned result reinterpreted as `Int`\n// \u{2014} so it is the impl most obviously able to return a negative hash. See the\n// masking rule on `Hash` above.\n//\n// The seed is drawn once per process, so a given `String` hashes to one value\n// for the whole of a run and can hash to a different one in the next run of the\n// same program \u{2014} not must, since two seeds may agree on one string. What\n// that buys and what it does not is documented at `nova_rt_str_hash` in the\n// runtime. The `Int`, `Bool` and `Char` impls above are seeded too, from a\n// separate draw (`int_hash_seed`), so they are not stable across runs either;\n// what stays unseeded is `mix64`, which those impls XOR the seed in *ahead* of.\nimpl Hash for String {\n fn hash(self) -> Int { str_hash(self) }\n}\n";Expand description
std/core/lib.nova.