about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-05T14·01+0300
committertazjin <tazjin@tvl.su>2022-09-11T12·04+0000
commit27e69503a7374d7758a7c6145427265712d45f9c (patch)
tree50a41c04030cb3e922cf83d40dc335f758e4bbbf /tvix/eval
parentbb34665abdf82227abdf0fc726abe2df57f3193e (diff)
fix(tvix/eval): avoid forcing with-target until absolutely necessary r/4793
Change-Id: I00efbbb8b9d3d22f32becf0919c6adf1be8b4b69
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6465
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/compiler/mod.rs1
-rw-r--r--tvix/eval/src/vm.rs15
2 files changed, 11 insertions, 5 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 6be2a1fb05a5..d05989562f66 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -862,7 +862,6 @@ impl Compiler<'_, '_> {
         // resolve that directly (thus avoiding duplication on the
         // stack).
         self.compile(slot, node.namespace().unwrap());
-        self.emit_force(&node.namespace().unwrap());
 
         let span = self.span_for(&node.namespace().unwrap());
 
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 89702a090fff..c124a653a019 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -635,10 +635,17 @@ impl<'o> VM<'o> {
     }
 
     /// Resolve a dynamic identifier through the with-stack at runtime.
-    fn resolve_with(&self, ident: &str) -> EvalResult<Value> {
-        for idx in self.with_stack.iter().rev() {
-            let with = fallible!(self, self.stack[*idx].to_attrs());
-            match with.select(ident) {
+    fn resolve_with(&mut self, ident: &str) -> EvalResult<Value> {
+        // Iterate over the with_stack manually to avoid borrowing
+        // self, which is required for forcing the set.
+        for with_stack_idx in (0..self.with_stack.len()).rev() {
+            let with = self.stack[self.with_stack[with_stack_idx]].clone();
+
+            if let Value::Thunk(thunk) = &with {
+                fallible!(self, thunk.force(self));
+            }
+
+            match fallible!(self, with.to_attrs()).select(ident) {
                 None => continue,
                 Some(val) => return Ok(val.clone()),
             }