feat(tvix/eval): semi-strictly evaluate output values of the VM
This essentially makes the VM behave like `nix-instantiate --eval --strict`, i.e. data structures are traversed strictly and thunks are forced. Thunks embedded in closures are not forced. This allows us to re-enable tests that were disabled because they needed to output nested thunk contents, but is overall a behaviour that must be configurable later on, as it is not cmopatible with e.g. an evaluation of nixpkgs. Change-Id: I5303a5c8e4322feab1384fdb7712fecb950afca5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6372 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
parent
6c6f9ae661
commit
afcfa78364
3 changed files with 36 additions and 4 deletions
|
@ -1,3 +0,0 @@
|
|||
# TODO: temporarily disabled because need "strict output" (b is
|
||||
# thunked)
|
||||
{ a = { b = null; }; }
|
1
tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix
Normal file
1
tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix
Normal file
|
@ -0,0 +1 @@
|
|||
{ a = { b = null; }; }
|
|
@ -602,6 +602,38 @@ impl VM {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Strictly evaluate the supplied value for outputting it. This
|
||||
/// will ensure that lists and attribute sets do not contain
|
||||
/// chunks which, for users, are displayed in a strange and often
|
||||
/// unexpected way.
|
||||
fn force_for_output(&mut self, value: &Value) -> EvalResult<()> {
|
||||
match value {
|
||||
Value::Attrs(attrs) => {
|
||||
for (_, value) in attrs.iter() {
|
||||
self.force_for_output(value)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Value::List(list) => list.iter().try_for_each(|elem| self.force_for_output(elem)),
|
||||
|
||||
Value::Thunk(thunk) => {
|
||||
thunk.force(self)?;
|
||||
self.force_for_output(&thunk.value())
|
||||
}
|
||||
|
||||
// If any of these internal values are encountered here a
|
||||
// critical error has happened (likely a compiler bug).
|
||||
Value::AttrPath(_)
|
||||
| Value::AttrNotFound
|
||||
| Value::DynamicUpvalueMissing(_)
|
||||
| Value::Blueprint(_)
|
||||
| Value::DeferredUpvalue(_) => panic!("tvix bug: internal value left on stack"),
|
||||
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use Rc::unwrap_or_clone once it is stabilised.
|
||||
|
@ -618,5 +650,7 @@ pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> {
|
|||
};
|
||||
|
||||
vm.call(Rc::new(lambda), vec![], 0);
|
||||
vm.run()
|
||||
let value = vm.run()?;
|
||||
vm.force_for_output(&value)?;
|
||||
Ok(value)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue