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 <tazjin@tvl.su> Tested-by: BuildkiteCI Reviewed-by: Adam Joseph <adam@westernsemico.com>
This commit is contained in:
parent
0063e7e913
commit
13a5e7dd5b
4 changed files with 16 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
42
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue