refactor(eval/builtins/intersectAttrs): use kv iterator instead of unsafe get

We can just iterate key-value pairs for our merge sort, rather than
relying on unsafe to get us the value without costing us a presence
check.

Change-Id: I7145a1b2f33a8510de8d7fbd1a12804517a78042
Reviewed-on: https://cl.snix.dev/c/snix/+/30371
Tested-by: besadii
Reviewed-by: Florian Klink <flokli@flokli.de>
This commit is contained in:
edef 2025-05-01 14:01:17 +00:00
parent 94ba112360
commit 3d95109328

View file

@ -789,19 +789,19 @@ mod pure_builtins {
if left_set.is_empty() { if left_set.is_empty() {
return Ok(Value::attrs(NixAttrs::empty())); return Ok(Value::attrs(NixAttrs::empty()));
} }
let mut left_keys = left_set.keys_sorted(); let mut left_iter = left_set.iter_sorted();
let right_set = y.to_attrs()?; let right_set = y.to_attrs()?;
if right_set.is_empty() { if right_set.is_empty() {
return Ok(Value::attrs(NixAttrs::empty())); return Ok(Value::attrs(NixAttrs::empty()));
} }
let mut right_keys = right_set.keys_sorted(); let mut right_iter = right_set.iter_sorted();
let mut out: BTreeMap<NixString, Value> = BTreeMap::new(); let mut out: BTreeMap<NixString, Value> = BTreeMap::new();
// Both iterators have at least one entry // Both iterators have at least one entry
let mut left = left_keys.next().unwrap(); let mut left = left_iter.next().unwrap();
let mut right = right_keys.next().unwrap(); let mut right = right_iter.next().unwrap();
// Calculate the intersection of two attribute sets by iterating them // Calculate the intersection of two attribute sets by iterating them
// simultaneously in lexicographic order, similar to a merge sort. // simultaneously in lexicographic order, similar to a merge sort.
@ -811,22 +811,15 @@ mod pure_builtins {
// We opted for this implementation over simpler ones because of the // We opted for this implementation over simpler ones because of the
// heavy use of this function in nixpkgs. // heavy use of this function in nixpkgs.
loop { loop {
if left == right { if left.0 == right.0 {
// We know that the key exists in the set, and can out.insert(right.0.clone(), right.1.clone());
// skip the check instructions.
unsafe {
out.insert(
right.clone(),
right_set.select(right).unwrap_unchecked().clone(),
);
}
left = match left_keys.next() { left = match left_iter.next() {
Some(x) => x, Some(x) => x,
None => break, None => break,
}; };
right = match right_keys.next() { right = match right_iter.next() {
Some(x) => x, Some(x) => x,
None => break, None => break,
}; };
@ -834,16 +827,16 @@ mod pure_builtins {
continue; continue;
} }
if left < right { if left.0 < right.0 {
left = match left_keys.next() { left = match left_iter.next() {
Some(x) => x, Some(x) => x,
None => break, None => break,
}; };
continue; continue;
} }
if right < left { if right.0 < left.0 {
right = match right_keys.next() { right = match right_iter.next() {
Some(x) => x, Some(x) => x,
None => break, None => break,
}; };