From 162e21f2bb326960770ed55ee44170b924c72fd8 Mon Sep 17 00:00:00 2001 From: sterni Date: Mon, 12 Sep 2022 18:03:43 +0200 Subject: [PATCH] fix(tvix/eval): force left argument of `?` before checking for attrs OpAttrsIsSet and OpAttrsTrySelect will fail silently if the attribute set value on the stack is actually a thunk, so we need to make sure to force at every step of the way. Emitting the force instructions in the compiler because it is easier to add, but maybe the VM should do this when handling the relevant opcodes? Comments welcome. Change-Id: I65c5ef348d59b2d07c9bb06abb24f9f3e6a0fdb2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6540 Reviewed-by: grfn Autosubmit: sterni Tested-by: BuildkiteCI Reviewed-by: tazjin --- tvix/eval/src/compiler/attrs.rs | 2 ++ .../tvix_tests/eval-okay-nested-has-attrs.exp | 1 + .../tvix_tests/eval-okay-nested-has-attrs.nix | 26 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp create mode 100644 tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix diff --git a/tvix/eval/src/compiler/attrs.rs b/tvix/eval/src/compiler/attrs.rs index bb48ffbb0..c9897daac 100644 --- a/tvix/eval/src/compiler/attrs.rs +++ b/tvix/eval/src/compiler/attrs.rs @@ -113,12 +113,14 @@ impl Compiler<'_, '_> { pub(super) fn compile_has_attr(&mut self, slot: LocalIdx, node: ast::HasAttr) { // Put the attribute set on the stack. self.compile(slot, node.expr().unwrap()); + self.emit_force(&node); // Push all path fragments with an operation for fetching the // next nested element, for all fragments except the last one. for (count, fragment) in node.attrpath().unwrap().attrs().enumerate() { if count > 0 { self.push_op(OpCode::OpAttrsTrySelect, &fragment); + self.emit_force(&fragment); } self.compile_attr(slot, fragment); diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp new file mode 100644 index 000000000..d2c1c04da --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp @@ -0,0 +1 @@ +[ true true true true true true true false false false false false ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix new file mode 100644 index 000000000..47dcec7a9 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix @@ -0,0 +1,26 @@ +let + set = { + a.b.c = 123; + foo = { + bar = 23; + }; + baz = 1; + }; + + tes = "random value"; +in + +[ + (set ? a) + (set ? a.b) + (set ? a.b.c) + (set ? foo) + (set ? foo.bar) + (set.foo ? bar) + (set ? baz) + (set ? x) + (set ? x.y.z) + (tes ? bar) + (tes ? x.y.z) + (null ? null) +]