about summary refs log tree commit diff
path: root/tvix/eval/src
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2023-03-03T07·54+0300
committertazjin <tazjin@tvl.su>2023-03-13T20·30+0000
commiteef48b8f1f3c7ae37a793bfef22c276dfd69767c (patch)
tree10eff587a994bcea2ca075638dd0ec5613fb088d /tvix/eval/src
parent43d04d9b985855cb431024d9895d52ea52fd4180 (diff)
fix(tvix/eval): correctly thunk deferred formals access r/5970
Formals can be initialised with deferred default values (see the test
cases), in which case they need an extra thunk to have something that
can be finalised appropriately when the setup is done.

Fixes: b/255
Change-Id: I380e3770be68eaa83ace96d450c7cead32dacc9f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8196
Tested-by: BuildkiteCI
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Diffstat (limited to 'tvix/eval/src')
-rw-r--r--tvix/eval/src/compiler/mod.rs12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix6
3 files changed, 18 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 5460514ba1ed..39b706cb487a 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -937,7 +937,17 @@ impl Compiler<'_> {
                 let jump_over_default = self.push_op(OpCode::OpJump(JumpOffset(0)), &default_expr);
 
                 self.patch_jump(jump_to_default);
-                self.compile(idx, default_expr);
+
+                // Thunk the default expression, but only if it is something
+                // other than an identifier.
+                if let ast::Expr::Ident(_) = &default_expr {
+                    self.compile(idx, default_expr);
+                } else {
+                    self.thunk(idx, &self.span_for(&default_expr), move |c, s| {
+                        c.compile(s, default_expr)
+                    });
+                }
+
                 self.patch_jump(jump_over_default);
             } else {
                 self.push_op(OpCode::OpAttrsSelect, &entry.ident().unwrap());
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp
new file mode 100644
index 000000000000..5993db7ccc5a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp
@@ -0,0 +1 @@
+[ false -2 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix
new file mode 100644
index 000000000000..1fbb3e853af4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix
@@ -0,0 +1,6 @@
+# Application of unary operators on deferred formals arguments (via
+# defaulting), see also b/255.
+[
+  (({ b ? !a, a }: b) { a = true; })
+  (({ b ? -a, a }: b) { a = 2; })
+]