diff options
author | Adam Joseph <adam@westernsemico.com> | 2022-09-25 00:09:13 -0700 |
---|---|---|
committer | Adam Joseph <adam@westernsemico.com> | 2022-09-25 00:09:15 -0700 |
commit | 037cf2fad190766319c6c40b931b49c075ce5e78 (patch) | |
tree | 8e6ed01234d418241fc7c52c5e3fcdcf8b5eced0 /lib | |
parent | 99da19387705b90647741f020ad2f835e6c8056b (diff) |
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/attrsets.nix | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix index 31dc27969cc04..de88763854d69 100644 --- a/lib/attrsets.nix +++ b/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 ***/ |