summaryrefslogtreecommitdiff
path: root/lib/types.nix
diff options
context:
space:
mode:
authorJohannes Kirschbauer <hsjobeki@gmail.com>2024-11-09 11:22:25 +0100
committerJohannes Kirschbauer <hsjobeki@gmail.com>2024-11-25 15:11:45 +0100
commitc4a9529071d5464d0c778690d8219f3548151b0b (patch)
treec29700215644300a45fa05cc2244a91972ab11d3 /lib/types.nix
parentprometheus-statsd-exporter: 0.27.2 -> 0.28.0 (#358715) (diff)
downloadnixpkgs-c4a9529071d5464d0c778690d8219f3548151b0b.tar.gz
lib/types: init {types.attrsWith}
Diffstat (limited to 'lib/types.nix')
-rw-r--r--lib/types.nix89
1 files changed, 58 insertions, 31 deletions
diff --git a/lib/types.nix b/lib/types.nix
index 82d7425ca643..3078cc4de609 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -582,48 +582,75 @@ rec {
substSubModules = m: nonEmptyListOf (elemType.substSubModules m);
};
- attrsOf = elemType: mkOptionType rec {
- name = "attrsOf";
- description = "attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
- descriptionClass = "composite";
- check = isAttrs;
- merge = loc: defs:
- mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
- (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
- )
- # Push down position info.
- (map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs)));
- emptyValue = { value = {}; };
- getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
- getSubModules = elemType.getSubModules;
- substSubModules = m: attrsOf (elemType.substSubModules m);
- functor = (defaultFunctor name) // { wrapped = elemType; };
- nestedTypes.elemType = elemType;
- };
+ attrsOf = elemType: attrsWith { inherit elemType; };
# A version of attrsOf that's lazy in its values at the expense of
# conditional definitions not working properly. E.g. defining a value with
# `foo.attr = mkIf false 10`, then `foo ? attr == true`, whereas with
# attrsOf it would correctly be `false`. Accessing `foo.attr` would throw an
# error that it's not defined. Use only if conditional definitions don't make sense.
- lazyAttrsOf = elemType: mkOptionType rec {
- name = "lazyAttrsOf";
- description = "lazy attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
+ lazyAttrsOf = elemType: attrsWith { inherit elemType; lazy = true; };
+
+ # base type for lazyAttrsOf and attrsOf
+ attrsWith = {
+ elemType,
+ lazy ? false,
+ }:
+ let
+ typeName = if lazy then "lazyAttrsOf" else "attrsOf";
+ # Push down position info.
+ pushPositions = map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value);
+ in
+ mkOptionType {
+ name = typeName;
+ description = (if lazy then "lazy attribute set" else "attribute set") + " of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
descriptionClass = "composite";
check = isAttrs;
- merge = loc: defs:
- zipAttrsWith (name: defs:
- let merged = mergeDefinitions (loc ++ [name]) elemType defs;
- # mergedValue will trigger an appropriate error when accessed
- in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
- )
- # Push down position info.
- (map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs);
+ merge = if lazy then (
+ # Lazy merge Function
+ loc: defs:
+ zipAttrsWith (name: defs:
+ let merged = mergeDefinitions (loc ++ [name]) elemType defs;
+ # mergedValue will trigger an appropriate error when accessed
+ in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
+ )
+ # Push down position info.
+ (pushPositions defs)
+ ) else (
+ # Non-lazy merge Function
+ loc: defs:
+ mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
+ (mergeDefinitions (loc ++ [name]) elemType (defs)).optionalValue
+ )
+ # Push down position info.
+ (pushPositions defs)))
+ );
emptyValue = { value = {}; };
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
getSubModules = elemType.getSubModules;
- substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
- functor = (defaultFunctor name) // { wrapped = elemType; };
+ substSubModules = m: attrsWith { elemType = elemType.substSubModules m; inherit lazy; };
+ functor = defaultFunctor "attrsWith" // {
+ wrapped = elemType;
+ payload = {
+ # Important!: Add new function attributes here in case of future changes
+ inherit elemType lazy;
+ };
+ binOp = lhs: rhs:
+ let
+ elemType = lhs.elemType.typeMerge rhs.elemType.functor;
+ lazy =
+ if lhs.lazy == rhs.lazy then
+ lhs.lazy
+ else
+ null;
+ in
+ if elemType == null || lazy == null then
+ null
+ else
+ {
+ inherit elemType lazy;
+ };
+ };
nestedTypes.elemType = elemType;
};