diff options
author | Vincent Ambo <mail@tazj.in> | 2022-10-17T14·51+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2022-10-18T09·15+0000 |
commit | 13a5e7dd5ba6a5e448390e5ceb7f41825e7593c2 (patch) | |
tree | 9afe684d68521fc71d9273d3508de7f0eb869d15 | |
parent | 0063e7e913c199538fe67d55e714dd34c09cece3 (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>
4 files changed, 16 insertions, 3 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; } diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp new file mode 100644 index 000000000000..d81cc0710eb6 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp @@ -0,0 +1 @@ +42 diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix new file mode 100644 index 000000000000..22ac14b3f19e --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix @@ -0,0 +1,5 @@ +# The 'namespace' of a with should only be evaluated if an identifier +# from it is actually accessed. + +with (abort "should not be evaluated"); +let a = dynamic; in 42 diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix index e4377df97eeb..8b1a0191dcc0 100644 --- a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix @@ -1,6 +1,6 @@ # The 'namespace' of a with should only be evaluated if an identifier # from it is actually accessed. -with (builtins.throw "should not occur"); +with (abort "should not be evaluated"); 42 |