about summary refs log tree commit diff
path: root/tvix/eval/src/value/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/value/mod.rs')
-rw-r--r--tvix/eval/src/value/mod.rs45
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 {