about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/vm.rs47
1 files changed, 27 insertions, 20 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index b81281cf51..90f5f45f61 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -234,12 +234,7 @@ impl VM {
             //
             let key = self.pop();
             match key {
-                Value::String(ks) => {
-                    // TODO(tazjin): try_insert (rust#82766) or entry API
-                    if attrs.insert(ks.clone(), value).is_some() {
-                        return Err(Error::DuplicateAttrsKey { key: ks.0 });
-                    }
-                }
+                Value::String(ks) => set_attr(&mut attrs, ks, value)?,
 
                 Value::AttrPath(mut path) => {
                     set_nested_attr(
@@ -299,6 +294,29 @@ pub enum NumberPair {
     Integer(i64, i64),
 }
 
+// Set an attribute on an in-construction attribute set, while
+// checking against duplicate key.s
+fn set_attr(
+    attrs: &mut BTreeMap<NixString, Value>,
+    key: NixString,
+    value: Value,
+) -> EvalResult<()> {
+    let entry = attrs.entry(key);
+
+    match entry {
+        std::collections::btree_map::Entry::Occupied(entry) => {
+            return Err(Error::DuplicateAttrsKey {
+                key: entry.key().0.clone(),
+            })
+        }
+
+        std::collections::btree_map::Entry::Vacant(entry) => {
+            entry.insert(value);
+            return Ok(());
+        }
+    };
+}
+
 // Set a nested attribute inside of an attribute set, throwing a
 // duplicate key error if a non-hashmap entry already exists on the
 // path.
@@ -311,25 +329,14 @@ fn set_nested_attr(
     mut path: Vec<NixString>,
     value: Value,
 ) -> EvalResult<()> {
-    let entry = attrs.entry(key);
-
     // If there is no next key we are at the point where we
     // should insert the value itself.
     if path.is_empty() {
-        match entry {
-            std::collections::btree_map::Entry::Occupied(entry) => {
-                return Err(Error::DuplicateAttrsKey {
-                    key: entry.key().0.clone(),
-                })
-            }
-
-            std::collections::btree_map::Entry::Vacant(entry) => {
-                entry.insert(value);
-                return Ok(());
-            }
-        };
+        return set_attr(attrs, key, value);
     }
 
+    let entry = attrs.entry(key);
+
     // If there is not we go one step further down, in which case we
     // need to ensure that there either is no entry, or the existing
     // entry is a hashmap into which to insert the next value.