about summary refs log tree commit diff
path: root/tvix/eval/src/compiler/bindings.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-10-17T14·51+0300
committerclbot <clbot@tvl.fyi>2022-10-18T09·15+0000
commit13a5e7dd5ba6a5e448390e5ceb7f41825e7593c2 (patch)
tree9afe684d68521fc71d9273d3508de7f0eb869d15 /tvix/eval/src/compiler/bindings.rs
parent0063e7e913c199538fe67d55e714dd34c09cece3 (diff)
fix(tvix/eval): wrap dynamic resolution in an extra thunk r/5156
Without this change it was possible to cause situations (see the new
test) in which a `with`-namespace was forced prematurely.

Change-Id: I879ea7763b43edc693feace2c73c890d426fafd3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7031
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Reviewed-by: Adam Joseph <adam@westernsemico.com>
Diffstat (limited to 'tvix/eval/src/compiler/bindings.rs')
-rw-r--r--tvix/eval/src/compiler/bindings.rs11
1 files changed, 9 insertions, 2 deletions
diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs
index 9f7df1fdca19..4283b21276d4 100644
--- a/tvix/eval/src/compiler/bindings.rs
+++ b/tvix/eval/src/compiler/bindings.rs
@@ -694,9 +694,16 @@ impl Compiler<'_> {
 
                 // If there is a non-empty `with`-stack (or a parent context
                 // with one), emit a runtime dynamic resolution instruction.
+                //
+                // Since it is possible for users to e.g. assign a variable to a
+                // dynamic resolution without actually using it, this operation
+                // is wrapped in an extra thunk.
                 if self.has_dynamic_ancestor() {
-                    self.emit_constant(Value::String(SmolStr::new(ident).into()), node);
-                    self.push_op(OpCode::OpResolveWith, node);
+                    self.thunk(slot, node, |c, _| {
+                        c.context_mut().captures_with_stack = true;
+                        c.emit_constant(Value::String(SmolStr::new(ident).into()), node);
+                        c.push_op(OpCode::OpResolveWith, node);
+                    });
                     return;
                 }