about summary refs log tree commit diff
path: root/tvix/eval/src/compiler/mod.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-02T21·26+0300
committertazjin <tazjin@tvl.su>2022-09-08T13·36+0000
commit9973ddfcba57e1a2d1a72351814210ab652bd860 (patch)
tree824a7acc30ee414a93fa41896764ae269319d229 /tvix/eval/src/compiler/mod.rs
parent7bc6e5984dfd1f8717e28bbbcb97e078b6039558 (diff)
refactor(tvix/eval): refactor locals to use an enum for phantoms r/4754
Instead of using sentinel values and an additional bool, this tracks
the identifier of a local as an enum that is either a statically known
name, or a phantom.

To make this work correctly some more locals related logic has been
encapsulated in the `scope` module, which is a good thing (that's the
goal).

Phantom values are now not initialised by default, but the only
current call site of phantoms (`with` expression compilation) performs
the initialisation right away.

This commit changes no actual functionality right now, but paves the
way for fixing an issue related to `let` bodies.

Change-Id: I679f93a59a4daeacfe40f4012263cfb7bc05034e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6421
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/compiler/mod.rs')
-rw-r--r--tvix/eval/src/compiler/mod.rs20
1 files changed, 12 insertions, 8 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 242001c81f..d02c0e69c5 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -29,7 +29,7 @@ use crate::opcode::{CodeIdx, Count, JumpOffset, OpCode, UpvalueIdx};
 use crate::value::{Closure, Lambda, Thunk, Value};
 use crate::warnings::{EvalWarning, WarningKind};
 
-use self::scope::{Local, LocalIdx, LocalPosition, Scope, Upvalue, UpvalueKind};
+use self::scope::{LocalIdx, LocalPosition, Scope, Upvalue, UpvalueKind};
 
 /// Represents the result of compiling a piece of Nix code. If
 /// compilation was successful, the resulting bytecode can be passed
@@ -842,7 +842,14 @@ impl Compiler<'_> {
         self.emit_force(&node.namespace().unwrap());
 
         let span = self.span_for(&node.namespace().unwrap());
+
+        // The attribute set from which `with` inherits values
+        // occupies a slot on the stack, but this stack slot is not
+        // directly accessible. As it must be accounted for to
+        // calculate correct offsets, what we call a "phantom" local
+        // is declared here.
         let local_idx = self.scope_mut().declare_phantom(span);
+        self.scope_mut().mark_initialised(local_idx);
         let with_idx = self.scope().stack_index(local_idx);
 
         self.scope_mut().push_with();
@@ -1058,12 +1065,9 @@ impl Compiler<'_> {
             // While removing the local, analyse whether it has been
             // accessed while it existed and emit a warning to the
             // user otherwise.
-            if let Some(Local {
-                span, used, name, ..
-            }) = self.scope_mut().locals.pop()
-            {
-                if !used && !name.starts_with('_') {
-                    self.emit_warning(span, WarningKind::UnusedBinding);
+            if let Some(local) = self.scope_mut().locals.pop() {
+                if !local.used && !local.is_ignored() {
+                    self.emit_warning(local.span, WarningKind::UnusedBinding);
                 }
             }
         }
@@ -1106,7 +1110,7 @@ impl Compiler<'_> {
 
         let mut shadowed = false;
         for other in self.scope().locals.iter().rev() {
-            if other.name == name && other.depth == depth {
+            if other.has_name(&name) && other.depth == depth {
                 shadowed = true;
                 break;
             }