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.
main
Adam Joseph 2 years ago
parent 99da193877
commit 037cf2fad1
  1. 13
      lib/attrsets.nix

@ -627,11 +627,14 @@ rec {
`y`, and all values `assert` with an error message. This
operator is commutative, unlike (//). */
unionOfDisjoint = x: y:
x // (mapAttrs
(name: val:
if hasAttr name x
then builtins.throw "attribute collision: ${name}"
else val) y);
let
intersection = builtins.intersectAttrs x y;
collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
mask = builtins.mapAttrs (name: value: builtins.throw
"unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
intersection;
in
(x // y) // mask;
/*** deprecated stuff ***/

Loading…
Cancel
Save