about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-22T21·51+0300
committertazjin <tazjin@tvl.su>2022-09-22T23·23+0000
commit1015f2f8e7c37c5c4b4ebca799579c5f6c0d5100 (patch)
tree73ea1853815f8ddf4f720121af70580633833093
parentbd9cda2af7d9fd8064b719e9135b3a48cf13c36a (diff)
fix(tvix/eval): manually count entries in recursive scopes r/4962
The previous version had a bug where we assumed that the number of
entries in an attribute set AST node would be equivalent to the number
of entries in the runtime attribute set, but due to inherit nodes
containing a variable number of entries, this did not work out.

Fixes b/199

Change-Id: I6f7f7729f3512b297cf29a2e046302ca28477854
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6749
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
-rw-r--r--tvix/eval/src/compiler/attrs.rs4
-rw-r--r--tvix/eval/src/compiler/mod.rs12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix1
4 files changed, 14 insertions, 4 deletions
diff --git a/tvix/eval/src/compiler/attrs.rs b/tvix/eval/src/compiler/attrs.rs
index b4d183c51d..704bf211ff 100644
--- a/tvix/eval/src/compiler/attrs.rs
+++ b/tvix/eval/src/compiler/attrs.rs
@@ -241,8 +241,8 @@ impl Compiler<'_> {
         self.scope_mut().begin_scope();
 
         if node.rec_token().is_some() {
-            self.compile_recursive_scope(slot, true, &node);
-            self.push_op(OpCode::OpAttrs(Count(node.entries().count())), &node);
+            let count = self.compile_recursive_scope(slot, true, &node);
+            self.push_op(OpCode::OpAttrs(Count(count)), &node);
         } else {
             let mut count = self.compile_inherit_attrs(slot, node.inherits());
 
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 55b8d960a9..21f131e454 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -552,10 +552,11 @@ impl Compiler<'_> {
         self.patch_jump(else_idx); // patch jump *over* else body
     }
 
-    fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, rec_attrs: bool, node: &N)
+    fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, rec_attrs: bool, node: &N) -> usize
     where
         N: ToSpan + ast::HasEntry,
     {
+        let mut count = 0;
         self.scope_mut().begin_scope();
 
         // First pass to find all plain inherits (if they are not useless).
@@ -588,6 +589,8 @@ impl Compiler<'_> {
                             }
                         };
 
+                        count += 1;
+
                         // If the identifier resolves statically in a
                         // `let`, it has precedence over dynamic
                         // bindings, and the inherit is useless.
@@ -625,6 +628,7 @@ impl Compiler<'_> {
                             }
                         };
 
+                        count += 1;
                         inherit_froms.push((from.expr().unwrap(), name, self.span_for(&attr)));
                     }
                 }
@@ -632,7 +636,7 @@ impl Compiler<'_> {
         }
 
         // Data structures to track the bindings observed in the
-        // second path, and forward the information needed to compile
+        // second pass, and forward the information needed to compile
         // their value.
         enum BindingKind {
             InheritFrom {
@@ -689,6 +693,8 @@ impl Compiler<'_> {
 
         // Declare all regular bindings
         for entry in node.attrpath_values() {
+            count += 1;
+
             let mut path = match self.normalise_ident_path(entry.attrpath().unwrap().attrs()) {
                 Ok(p) => p,
                 Err(err) => {
@@ -773,6 +779,8 @@ impl Compiler<'_> {
                 self.push_op(OpCode::OpFinalise(stack_idx), node);
             }
         }
+
+        count
     }
 
     /// Compile a standard `let ...; in ...` expression.
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp
new file mode 100644
index 0000000000..ffcd4415b0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp
@@ -0,0 +1 @@
+{ }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix
new file mode 100644
index 0000000000..a1181431de
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix
@@ -0,0 +1 @@
+rec { inherit; }