pub enum Value {
Null,
Bool(bool),
Int(i64),
Float(f64),
String(Rc<NixString>),
Path(Box<SmolStr>),
List(Rc<NixList>),
Attrs(Rc<NixAttrs>),
Lambda(Rc<Closure>),
Builtin(Box<BuiltinFn>),
Thunk(Thunk),
}Expand description
A Nix value — potentially lazy (may be a Thunk).
To get a guaranteed-concrete value, call .demand() which returns
Concrete. The Concrete type has thunk-free accessors that the
compiler enforces — you cannot accidentally skip forcing.
Variants§
Null
Bool(bool)
Int(i64)
Float(f64)
String(Rc<NixString>)
Path(Box<SmolStr>)
List(Rc<NixList>)
Attrs(Rc<NixAttrs>)
Lambda(Rc<Closure>)
Builtin(Box<BuiltinFn>)
Thunk(Thunk)
A lazy value (thunk) with memoization and blackhole detection.
Implementations§
Source§impl Value
impl Value
Sourcepub fn string(s: impl Into<SmolStr>) -> Self
pub fn string(s: impl Into<SmolStr>) -> Self
Convenience constructor for a context-free string.
Sourcepub fn list(items: Vec<Value>) -> Self
pub fn list(items: Vec<Value>) -> Self
Convenience constructor that wraps a Vec<Value> in Rc for the
List variant.
Sourcepub fn is_uniquely_owned_list(&self) -> bool
pub fn is_uniquely_owned_list(&self) -> bool
True when self is a List whose backing Rc<Vec> is uniquely owned
(refcount 1). Used by concat_lists to decide the in-place fast path.
Sourcepub fn try_to_json(&self) -> Result<Value, EvalError>
pub fn try_to_json(&self) -> Result<Value, EvalError>
Like Self::to_json, but refuses where that one emits a
placeholder.
to_json renders a lambda as the string "<lambda>", a builtin as
"<builtin name>", and — worst — a thunk whose force FAILED as
"<thunk:error>". All three produce valid JSON and let the caller exit
0. Measured against nix 2.31.5:
nix eval --json --expr '{ f = x: x; }' exit 1
sui eval --json -E '{ f = x: x; }' exit 0 {"f":"<lambda>"}
nix eval --json --expr '{ x = throw "boom"; }' exit 1
sui eval --json -E '{ x = throw "boom"; }' exit 0 {"x":"<thunk:error>"}The last one is the sharpest silent divergence in the CLI: a real evaluation error becomes a VALUE, and a consumer parsing that JSON sees a string where nix would have refused outright.
to_json itself is deliberately left alone. It is the body of
builtins.toJSON, whose placeholder behaviour is load-bearing for the
existing corpus, and changing it would be a language-semantics change
rather than a CLI fix. This variant is for OUTPUT BOUNDARIES — where a
human or a script reads the result and an exit code is the contract.
§Errors
A function, a builtin, or a thunk whose force fails. The force error is
propagated verbatim so the operator sees the throw’s own message
rather than a generic refusal.
Sourcepub fn to_json_with_context(
&self,
ctx: &mut StringContext,
) -> Result<Value, EvalError>
pub fn to_json_with_context( &self, ctx: &mut StringContext, ) -> Result<Value, EvalError>
Like [to_json] but threads string context into ctx. Used by
__structuredAttrs derivation-env building: a derivation value
serializes to its outPath (a store-path string) and its drv reference
must flow into the derivation’s inputDrvs; a bare path is copy-to-store
coerced. (to_json drops context, which is fine for builtins.toJSON
but not for building a derivation’s __json.)
Sourcepub fn type_name(&self) -> &'static str
pub fn type_name(&self) -> &'static str
Return the Nix type name for this value (e.g. "int", "set").
Sourcepub fn as_string(&self) -> Result<&str, EvalError>
pub fn as_string(&self) -> Result<&str, EvalError>
Borrow the string content without forcing thunks.
Sourcepub fn as_nix_string(&self) -> Result<&NixString, EvalError>
pub fn as_nix_string(&self) -> Result<&NixString, EvalError>
Return a reference to the full NixString (with context).
Sourcepub fn to_str(&self) -> Result<String, EvalError>
pub fn to_str(&self) -> Result<String, EvalError>
Force-aware string extraction. Returns an owned String by forcing
thunks if needed. Use this instead of as_string() when you may
be operating on thunked attrset values.
Sourcepub fn to_nix_string(&self) -> Result<NixString, EvalError>
pub fn to_nix_string(&self) -> Result<NixString, EvalError>
Force-aware NixString extraction. Returns an owned NixString
(with context) by forcing thunks if needed.
Sourcepub fn as_attrs(&self) -> Result<&NixAttrs, EvalError>
pub fn as_attrs(&self) -> Result<&NixAttrs, EvalError>
Borrow the inner attrs without forcing. If the value is a thunk, the caller should have force_value’d it first; we return an error rather than silently mutating the thunk (which would require &mut self).
Most call sites should use to_attrs() (which forces and
clones) unless they’re certain the value is already
concrete and want to avoid the clone.
Sourcepub fn as_list(&self) -> Result<&[Value], EvalError>
pub fn as_list(&self) -> Result<&[Value], EvalError>
Borrow the list content without forcing thunks.
Sourcepub fn to_attrs(&self) -> Result<NixAttrs, EvalError>
pub fn to_attrs(&self) -> Result<NixAttrs, EvalError>
Force-aware attrs extraction. Forces the value if it is a thunk.
Sourcepub fn to_list(&self) -> Result<Vec<Value>, EvalError>
pub fn to_list(&self) -> Result<Vec<Value>, EvalError>
Force-aware list extraction. Forces the value if it is a thunk.
Sourcepub fn coerce_to_path(&self, context: &str) -> Result<String, EvalError>
pub fn coerce_to_path(&self, context: &str) -> Result<String, EvalError>
Extract a filesystem path from a Path or String value.
Many builtins (readFile, import, pathExists, etc.) accept
either Path or String arguments. This method centralises
that coercion so every call-site doesn’t repeat the same match.
Sourcepub fn coerce_to_realized_path(
&self,
context: &str,
) -> Result<String, EvalError>
pub fn coerce_to_realized_path( &self, context: &str, ) -> Result<String, EvalError>
Coerce to a filesystem path AND, if this value is a derivation whose output is not yet materialized on disk, realize that output first (import-from-derivation).
Used by the disk-read builtins (import, readFile, readDir,
pathExists, builtins.path) so a read under a derivation’s outPath
triggers a build/substitute of that output, exactly as cppnix does.
Semantics:
- A
Path/Stringcoerces as usual — no realize (nothing to build). - A derivation attrset (
type == "derivation"withdrvPath+outPath) whoseoutPath(after input-source materialization) does not exist on disk invokes the realize hook with(drvPath, outPath). On success the returned path is the (now-present)outPath. - A non-derivation attrset with
outPathcoerces viaoutPathas usual (no drv to realize). - If no realize hook is installed, this degrades to
coerce_to_path(the read that follows will ENOENT — a real error, never a wrong value).
The realize hook mutates no value the evaluator observes; it only makes
the bytes at the already-byte-correct outPath present on disk (see
crate::realize).
Sourcepub fn coerce_to_string(&self) -> Result<(String, StringContext), EvalError>
pub fn coerce_to_string(&self) -> Result<(String, StringContext), EvalError>
Coerce this value to a string following CppNix semantics.
This is the single source of truth for string coercion used by
string interpolation, builtins.toString, and derivation env
var construction.
Rules (in order):
- String → its content (with context)
- Path → path string (adds Plain context element)
- Int → decimal representation
- Float → decimal representation
- Bool → “1” for true, “” for false
- Null → “”
- Attrs with
__toString→ call__toString(self)and coerce result - Attrs with
outPath→ coerce outPath recursively - List → space-joined coerced elements
- Lambda/Builtin/Thunk → error
Sourcepub fn coerce_to_string_copy_to_store(
&self,
) -> Result<(String, StringContext), EvalError>
pub fn coerce_to_string_copy_to_store( &self, ) -> Result<(String, StringContext), EvalError>
Coerce to string in CppNix copy-to-store mode — the coercion used by
string interpolation ("${./foo}") and derivation-attribute population.
A source path that isn’t already in the store is absolutized,
canonicalized, required to exist, and NAR-copied into
/nix/store/<hash>-<basename>; the result string is that store path and
it carries store-path context. This is what makes src = ./. reference
the correct store path (and thus the correct drv hash) instead of a raw
filesystem path. builtins.toString keeps the plain mode
([coerce_to_string]) — it does not copy.
Trait Implementations§
Source§impl FromIterator<Value> for NixList
impl FromIterator<Value> for NixList
Auto Trait Implementations§
impl !RefUnwindSafe for Value
impl !Send for Value
impl !Sync for Value
impl !UnwindSafe for Value
impl Freeze for Value
impl Unpin for Value
impl UnsafeUnpin for Value
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
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<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.