about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-11-20T22·31+0100
committertazjin <tazjin@tvl.su>2022-11-21T14·14+0000
commit994bf03b74672d3a8602e7dc1b73de1fd97830a3 (patch)
tree0917daf072d88d45d17520e0f80854c83cc69774 /tvix
parente1e8285ecfe94fc9afd33110ff63ce707fa4369a (diff)
fix(tvix/eval): ensure callable is forced when using call_with r/5297
When passing multiple arguments, every intermediate callable needs to
be forced as this is expected by the VM's call_value function.

Also adds a debug assertion for this which makes it easier to spot
exactly what went wrong.

Change-Id: I3aa519cb6cdaab713bd18282bef901c4cd77c535
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7312
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix')
-rw-r--r--tvix/eval/src/value/thunk.rs4
-rw-r--r--tvix/eval/src/vm.rs6
2 files changed, 9 insertions, 1 deletions
diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs
index 549534b04ec7..5eee07a9e7ac 100644
--- a/tvix/eval/src/value/thunk.rs
+++ b/tvix/eval/src/value/thunk.rs
@@ -133,6 +133,10 @@ impl Thunk {
         }
     }
 
+    pub fn is_evaluated(&self) -> bool {
+        matches!(*self.0.borrow(), ThunkRepr::Evaluated(_))
+    }
+
     /// Returns a reference to the inner evaluated value of a thunk.
     /// It is an error to call this on a thunk that has not been
     /// forced, or is not otherwise known to be fully evaluated.
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 127d9bfa513c..17a7e0ce2758 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -230,7 +230,10 @@ impl<'o> VM<'o> {
 
             Value::Builtin(b) => self.call_builtin(b.clone()),
 
-            Value::Thunk(t) => self.call_value(&t.value()),
+            Value::Thunk(t) => {
+                debug_assert!(t.is_evaluated(), "call_value called with unevaluated thunk");
+                self.call_value(&t.value())
+            }
 
             // Attribute sets with a __functor attribute are callable.
             Value::Attrs(ref attrs) => match attrs.select("__functor") {
@@ -277,6 +280,7 @@ impl<'o> VM<'o> {
         let mut res = self.pop();
 
         for _ in 0..(num_args - 1) {
+            res.force(self).map_err(|e| self.error(e))?;
             self.call_value(&res)?;
             res = self.pop();
         }