Skip to content

Commit 037cf2f

Browse files
author
Adam Joseph
committed
unionOfDisjoint: use builtins.intersectAttrs
This brings two benefits: 1. The complete list of collisions is printed in the whenever any colliding attribute is accessed. 2. The sets are intersected using a C++ primitive, which runs in O(n) time (intersecting pre-sorted lists) with small constants rather than interpreted Nix code. Thanks to @toonn for prompting this improvement.
1 parent 99da193 commit 037cf2f

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

lib/attrsets.nix

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,11 +627,14 @@ rec {
627627
`y`, and all values `assert` with an error message. This
628628
operator is commutative, unlike (//). */
629629
unionOfDisjoint = x: y:
630-
x // (mapAttrs
631-
(name: val:
632-
if hasAttr name x
633-
then builtins.throw "attribute collision: ${name}"
634-
else val) y);
630+
let
631+
intersection = builtins.intersectAttrs x y;
632+
collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
633+
mask = builtins.mapAttrs (name: value: builtins.throw
634+
"unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
635+
intersection;
636+
in
637+
(x // y) // mask;
635638

636639
/*** deprecated stuff ***/
637640

0 commit comments

Comments
 (0)