about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/compiler/mod.rs13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix10
3 files changed, 19 insertions, 5 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 731ba9179c..f9a2dd32c8 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -973,17 +973,20 @@ impl Compiler<'_> {
     /// Emit the data instructions that the runtime needs to correctly
     /// assemble the provided upvalues array.
     fn emit_upvalue_data(&mut self, slot: LocalIdx, upvalues: Vec<Upvalue>) {
+        let this_depth = self.scope()[slot].depth;
         let this_stack_slot = self.scope().stack_index(slot);
+
         for upvalue in upvalues {
             match upvalue.kind {
                 UpvalueKind::Local(idx) => {
+                    let target_depth = self.scope()[idx].depth;
                     let stack_idx = self.scope().stack_index(idx);
 
-                    // If the upvalue slot is located *after* the
-                    // closure, the upvalue resolution must be
-                    // deferred until the scope is fully initialised
-                    // and can be finalised.
-                    if this_stack_slot < stack_idx {
+                    // If the upvalue slot is located at the same
+                    // depth, but *after* the closure, the upvalue
+                    // resolution must be deferred until the scope is
+                    // fully initialised and can be finalised.
+                    if this_depth == target_depth && this_stack_slot < stack_idx {
                         self.push_op(OpCode::DataDeferredLocal(stack_idx), &upvalue.node);
                         self.scope_mut().mark_needs_finaliser(slot);
                     } else {
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp
new file mode 100644
index 0000000000..edca9baca9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp
@@ -0,0 +1 @@
+{ a = 1; b = 2; c = 3; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix
new file mode 100644
index 0000000000..4c6884bec3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix
@@ -0,0 +1,10 @@
+# A simple expression with upvalue resolution beyond the target stack
+# index of the root expression.
+
+let
+  a = 1;
+  b = 2;
+  c = 3;
+in {
+  inherit a b c;
+}