diff --git a/pkgs/top-level/splice.nix b/pkgs/top-level/splice.nix index 2c6f060f23e1..5468d23c377d 100644 --- a/pkgs/top-level/splice.nix +++ b/pkgs/top-level/splice.nix @@ -31,43 +31,42 @@ let # The same pkgs sets one probably intends // inputs.buildHost // inputs.hostTarget; - merge = name: { - inherit name; - value = - let - defaultValue = mash.${name}; - # `or {}` is for the non-derivation attsert splicing case, where `{}` is the identity. - value' = mapCrossIndex (x: x.${name} or { }) inputs; + # perf: mapAttrs defers merge calls until a key is selected, avoiding + # ~60k eager closures that listToAttrs+map would create. + merge = + name: defaultValue: + let + # `or {}` is for the non-derivation attsert splicing case, where `{}` is the identity. + value' = mapCrossIndex (x: x.${name} or { }) inputs; - augmentedValue = defaultValue // { - __spliced = lib.filterAttrs (k: v: inputs.${k} ? ${name}) value'; - }; - # Get the set of outputs of a derivation. If one derivation fails to - # evaluate we don't want to diverge the entire splice, so we fall back - # on {} - tryGetOutputs = - value0: - let - inherit (builtins.tryEval value0) success value; - in - getOutputs (lib.optionalAttrs success value); - getOutputs = - value: lib.genAttrs (value.outputs or (lib.optional (value ? out) "out")) (output: value.${output}); - in - # The derivation along with its outputs, which we recur - # on to splice them together. - if lib.isDerivation defaultValue then - augmentedValue - // spliceReal (mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; }) - else if lib.isAttrs defaultValue then - spliceReal value' - else - # Don't be fancy about non-derivations. But we could have used used - # `__functor__` for functions instead. - defaultValue; - }; + augmentedValue = defaultValue // { + __spliced = lib.filterAttrs (k: v: inputs.${k} ? ${name}) value'; + }; + # Get the set of outputs of a derivation. If one derivation fails to + # evaluate we don't want to diverge the entire splice, so we fall back + # on {} + tryGetOutputs = + value0: + let + inherit (builtins.tryEval value0) success value; + in + getOutputs (lib.optionalAttrs success value); + getOutputs = + value: lib.genAttrs (value.outputs or (lib.optional (value ? out) "out")) (output: value.${output}); + in + # The derivation along with its outputs, which we recur + # on to splice them together. + if lib.isDerivation defaultValue then + augmentedValue + // spliceReal (mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; }) + else if lib.isAttrs defaultValue then + spliceReal value' + else + # Don't be fancy about non-derivations. But we could have used used + # `__functor__` for functions instead. + defaultValue; in - lib.listToAttrs (map merge (lib.attrNames mash)); + builtins.mapAttrs merge mash; splicePackages = {