about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
Diffstat (limited to 'tvix')
-rw-r--r--tvix/eval/src/value/attrs.rs12
-rw-r--r--tvix/eval/src/vm.rs2
2 files changed, 13 insertions, 1 deletions
diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs
index 4109691992ca..bbff79fc0d1a 100644
--- a/tvix/eval/src/value/attrs.rs
+++ b/tvix/eval/src/value/attrs.rs
@@ -66,6 +66,14 @@ impl AttrsRep {
             AttrsRep::Map(map) => map.get(&key.into()),
         }
     }
+
+    fn contains(&self, key: &str) -> bool {
+        match self {
+            AttrsRep::Empty => false,
+            AttrsRep::KV { .. } => key == "name" || key == "value",
+            AttrsRep::Map(map) => map.contains_key(&key.into()),
+        }
+    }
 }
 
 #[repr(transparent)]
@@ -202,6 +210,10 @@ impl NixAttrs {
         self.0.select(key)
     }
 
+    pub fn contains(&self, key: &str) -> bool {
+        self.0.contains(key)
+    }
+
     /// Implement construction logic of an attribute set, to encapsulate
     /// logic about attribute set optimisations inside of this module.
     pub fn construct(count: usize, mut stack_slice: Vec<Value>) -> EvalResult<Self> {
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index b6d5a9838c3a..1e39792cd56f 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -242,7 +242,7 @@ impl VM {
                 OpCode::OpAttrsIsSet => {
                     let key = self.pop().to_string()?;
                     let result = match self.pop() {
-                        Value::Attrs(attrs) => attrs.select(key.as_str()).is_some(),
+                        Value::Attrs(attrs) => attrs.contains(key.as_str()),
 
                         // Nix allows use of `?` on non-set types, but
                         // always returns false in those cases.