summary refs log tree commit diff
path: root/lib/types.nix
diff options
context:
space:
mode:
authorSilvan Mosberger <infinisil@icloud.com>2019-10-12 21:18:53 +0200
committerSilvan Mosberger <contact@infinisil.com>2020-01-10 16:19:55 +0100
commitb48717d1eb9d4d9d60f3460274e7d9a961a402df (patch)
tree963ddca03bc11d61026ed701c521aa2633c65f63 /lib/types.nix
parent4268b4f9cffc46482ece4a8e0128b8ef09ea6db2 (diff)
downloadnixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar.gz
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar.bz2
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar.lz
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar.xz
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.tar.zst
nixpkgs-b48717d1eb9d4d9d60f3460274e7d9a961a402df.zip
lib/types: Introduce lazyAttrsOf
The standard attrsOf is strict in its *values*, meaning it's impossible to
access only one attribute value without evaluating all others as well.
lazyAttrsOf is a version that doesn't have that problem, at the expense
of conditional definitions not properly working anymore.
Diffstat (limited to 'lib/types.nix')
-rw-r--r--lib/types.nix24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/types.nix b/lib/types.nix
index f406cb9204b..e86f6d36476 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -302,6 +302,30 @@ rec {
       functor = (defaultFunctor name) // { wrapped = 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 ${elemType.description}s";
+      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);
+      emptyValue = { value = {}; };
+      getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
+      getSubModules = elemType.getSubModules;
+      substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
+      functor = (defaultFunctor name) // { wrapped = elemType; };
+    };
+
     # List or attribute set of ...
     loaOf = elemType:
       let