diff options
| author | Johannes Kirschbauer <hsjobeki@gmail.com> | 2024-11-09 11:22:25 +0100 |
|---|---|---|
| committer | Johannes Kirschbauer <hsjobeki@gmail.com> | 2024-11-25 15:11:45 +0100 |
| commit | c4a9529071d5464d0c778690d8219f3548151b0b (patch) | |
| tree | c29700215644300a45fa05cc2244a91972ab11d3 /lib/types.nix | |
| parent | prometheus-statsd-exporter: 0.27.2 -> 0.28.0 (#358715) (diff) | |
| download | nixpkgs-c4a9529071d5464d0c778690d8219f3548151b0b.tar.gz | |
lib/types: init {types.attrsWith}
Diffstat (limited to 'lib/types.nix')
| -rw-r--r-- | lib/types.nix | 89 |
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; }; |
