diff options
Diffstat (limited to 'tvix/eval/src/value/mod.rs')
-rw-r--r-- | tvix/eval/src/value/mod.rs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 78f4f5de67a4..1dc39d6832c5 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -27,6 +27,8 @@ pub use path::canon_path; pub use string::NixString; pub use thunk::Thunk; +use self::thunk::ThunkSet; + #[warn(variant_size_differences)] #[derive(Clone, Debug, PartialEq)] pub enum Value { @@ -341,6 +343,49 @@ impl Value { _ => Ok(ForceResult::Immediate(self)), } } + + /// Ensure `self` is *deeply* forced, including all recursive sub-values + pub(crate) fn deep_force( + &self, + vm: &mut VM, + thunk_set: &mut ThunkSet, + ) -> Result<(), ErrorKind> { + match self { + Value::Null + | Value::Bool(_) + | Value::Integer(_) + | Value::Float(_) + | Value::String(_) + | Value::Path(_) + | Value::Closure(_) + | Value::Builtin(_) + | Value::AttrNotFound + | Value::Blueprint(_) + | Value::DeferredUpvalue(_) + | Value::UnresolvedPath(_) => Ok(()), + Value::Attrs(a) => { + for (_, v) in a.iter() { + v.deep_force(vm, thunk_set)?; + } + Ok(()) + } + Value::List(l) => { + for val in l { + val.deep_force(vm, thunk_set)?; + } + Ok(()) + } + Value::Thunk(thunk) => { + if !thunk_set.insert(thunk) { + return Ok(()); + } + + thunk.force(vm)?; + let value = thunk.value().clone(); + value.deep_force(vm, thunk_set) + } + } + } } impl Display for Value { |