about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGriffin Smith <root@gws.fyi>2022-10-10T19·57-0400
committerclbot <clbot@tvl.fyi>2022-10-10T20·35+0000
commit25921134353e785b509d4debeb11b3bf209c92b3 (patch)
treeb570ab1d762108121f93b22ee77da39ed8567e54
parent4fd18cbc9a756ea51dd04fa7bde9cfc79f4f8fa3 (diff)
fix(tvix/eval): Thunk `if` expr r/5090
Since the body of an `if` expr can refer to deferred upvalues, it needs
to be thunked so when we actually compile those deferred upvalues we
have something for the finalize op to point at. Without this all sorts
of weird things can happen due to the finalize op being run in the wrong
lambda context, up to and including a panic.

Change-Id: I040d5e1a7232fd841cfa4953539898fa49cbbb83
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6929
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: grfn <grfn@gws.fyi>
Tested-by: BuildkiteCI
-rw-r--r--tvix/eval/src/compiler/mod.rs4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix6
3 files changed, 10 insertions, 1 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index cfb0ee64a6..fa08d626aa 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -212,7 +212,9 @@ impl Compiler<'_> {
             ast::Expr::Assert(assert) => {
                 self.thunk(slot, assert, move |c, s| c.compile_assert(s, assert))
             }
-            ast::Expr::IfElse(if_else) => self.compile_if_else(slot, if_else),
+            ast::Expr::IfElse(if_else) => {
+                self.thunk(slot, if_else, move |c, s| c.compile_if_else(s, if_else))
+            }
             ast::Expr::LetIn(let_in) => self.compile_let_in(slot, let_in),
             ast::Expr::Ident(ident) => self.compile_ident(slot, ident),
             ast::Expr::With(with) => self.thunk(slot, with, |c, s| c.compile_with(s, with)),
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp
new file mode 100644
index 0000000000..ffcd4415b0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp
@@ -0,0 +1 @@
+{ }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix
new file mode 100644
index 0000000000..65e9e66d74
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix
@@ -0,0 +1,6 @@
+let
+  a = {};
+in let
+  c = if builtins.isFunction a then a b else a;
+  b = {};
+in c