diff options
author | Vincent Ambo <mail@tazj.in> | 2022-11-20T22·31+0100 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-11-21T14·14+0000 |
commit | 994bf03b74672d3a8602e7dc1b73de1fd97830a3 (patch) | |
tree | 0917daf072d88d45d17520e0f80854c83cc69774 /tvix/eval/src | |
parent | e1e8285ecfe94fc9afd33110ff63ce707fa4369a (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/eval/src')
-rw-r--r-- | tvix/eval/src/value/thunk.rs | 4 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 6 |
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(); } |