Module eval_state

Module eval_state 

Source
Expand description

§Nix Expression Evaluation

This module provides the core EvalState type for evaluating Nix expressions and extracting typed values from the results.

§Overview

The EvalState manages the evaluation context for Nix expressions, including:

§Construction

Create an EvalState using EvalState::new or EvalStateBuilder for advanced configuration:

let store = Store::open(None, HashMap::new())?;

// Simple creation
let mut es = EvalState::new(store.clone(), [])?;

// With custom lookup paths
let mut es = EvalStateBuilder::new(store)?
    .lookup_path(["nixpkgs=/path/to/nixpkgs"])?
    .build()?;

§Value Extraction

All require_* methods perform these steps:

  1. Evaluation: Force evaluation of thunks as needed
  2. Type checking: Verify the value matches the expected type
  3. Extraction: Return the typed Rust value or an error

Methods with _strict in their name also evaluate their return values before returning them.

§Evaluation Strictness

§Laziness and Strictness

The terms “lazy” and “strict” in this API refer to Nix’s Weak Head Normal Form (WHNF) evaluation model, not the kind of deep strictness that is exercised by functions such as builtins.toJSON or builtins.deepSeq.

  • WHNF evaluation: Values are evaluated just enough to determine their type and basic structure
  • Deep evaluation: All nested values are recursively forced (like builtins.deepSeq)

For example, a list in WHNF has its length determined but individual elements may remain unevaluated thunks. Methods marked as “strict” in this API force WHNF evaluation of their results, but do not perform deep evaluation of arbitrarily nested structures unless explicitly documented otherwise.

§Thread Safety and Memory Management

Before using EvalState in a thread, register it with the (process memory) garbage collector:

init()?; // Initialize Nix library
let guard = gc_register_my_thread()?; // Register thread with GC
// Now safe to use EvalState in this thread
drop(guard);

§Error Handling

Evaluation methods return Result types. Common error scenarios include:

  • Type mismatches: Expected type doesn’t match actual value type
  • Evaluation errors: Nix expressions that throw or have undefined behavior
  • Bounds errors: Out-of-range access for indexed operations

§Examples

use nix_bindings_expr::eval_state::{EvalState, test_init, gc_register_my_thread};
use nix_bindings_store::store::Store;
use std::collections::HashMap;

test_init(); // init() in non-test code
let guard = gc_register_my_thread()?;

let store = Store::open(None, HashMap::new())?;
let mut es = EvalState::new(store, [])?;

// Evaluate a list expression
let list_value = es.eval_from_string("[1 2 3]", "<example>")?;

// Check the size (lazy - doesn't evaluate elements)
let size = es.require_list_size(&list_value)?;
println!("List has {} elements", size);

// Access specific elements (evaluates only accessed elements)
if let Some(first) = es.require_list_select_idx_strict(&list_value, 0)? {
    let value = es.require_int(&first)?;
    println!("First element: {}", value);
}

// Process all elements (evaluates all elements)
let all_elements: Vec<_> = es.require_list_strict(&list_value)?;
for element in all_elements {
    let value = es.require_int(&element)?;
    println!("Element: {}", value);
}

drop(guard);

Structs§

EvalState
EvalStateBuilder
Builder for configuring and creating an EvalState.
EvalStateWeak
A Weak reference to an EvalState.
RealisedString
A string value with its associated store paths.
ThreadRegistrationGuard
RAII guard for thread registration with the garbage collector.

Functions§

gc_now
Triggers garbage collection immediately.
gc_register_my_thread
init
test_init
Initialize the Nix library for testing. This includes some modifications to the Nix settings, that must not be used in production. Use at your own peril, in rust test suites.