From 13a5e7dd5ba6a5e448390e5ceb7f41825e7593c2 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 17 Oct 2022 17:51:38 +0300 Subject: fix(tvix/eval): wrap dynamic resolution in an extra thunk 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 Tested-by: BuildkiteCI Reviewed-by: Adam Joseph --- tvix/eval/src/compiler/bindings.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'tvix/eval/src/compiler') 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; } -- cgit 1.4.1