fix(tvix/eval): ensure callable is forced when using call_with

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>
This commit is contained in:
Vincent Ambo 2022-11-20 23:31:08 +01:00 committed by tazjin
parent e1e8285ecf
commit 994bf03b74
2 changed files with 9 additions and 1 deletions

View file

@ -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.

View file

@ -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();
}