summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2019-12-13 01:12:41 +0100
committerSilvan Mosberger <contact@infinisil.com>2020-01-10 16:19:54 +0100
commit4268b4f9cffc46482ece4a8e0128b8ef09ea6db2 (patch)
tree910e0c2983dc0472b46ce62cea1879f5dd8f4758 /lib
parentd5a292264121e3a3e4015a1d7fb8ccb0bb985ab7 (diff)
downloadnixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar.gz
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar.bz2
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar.lz
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar.xz
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.tar.zst
nixpkgs-4268b4f9cffc46482ece4a8e0128b8ef09ea6db2.zip
lib/types: Add emptyValue attribute to types
Co-Authored-By: Robert Hensing <roberth@users.noreply.github.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/types.nix20
1 files changed, 18 insertions, 2 deletions
diff --git a/lib/types.nix b/lib/types.nix
index 4872a676657..f406cb9204b 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -65,6 +65,11 @@ rec {
       # definition values and locations (e.g. [ { file = "/foo.nix";
       # value = 1; } { file = "/bar.nix"; value = 2 } ]).
       merge ? mergeDefaultOption
+    , # Whether this type has a value representing nothingness. If it does,
+      # this should be a value of the form { value = <the nothing value>; }
+      # If it doesn't, this should be {}
+      # This may be used when a value is required for `mkIf false`. This allows the extra laziness in e.g. `lazyAttrsOf`.
+      emptyValue ? {}
     , # Return a flat list of sub-options.  Used to generate
       # documentation.
       getSubOptions ? prefix: {}
@@ -88,7 +93,7 @@ rec {
       functor ? defaultFunctor name
     }:
     { _type = "option-type";
-      inherit name check merge getSubOptions getSubModules substSubModules typeMerge functor;
+      inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor;
       description = if description == null then name else description;
     };
 
@@ -225,6 +230,7 @@ rec {
       description = "attribute set";
       check = isAttrs;
       merge = loc: foldl' (res: def: mergeAttrs res def.value) {};
+      emptyValue = { value = {}; };
     };
 
     # derivation is a reserved keyword.
@@ -265,6 +271,7 @@ rec {
             ) def.value
           else
             throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs)));
+      emptyValue = { value = {}; };
       getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
       getSubModules = elemType.getSubModules;
       substSubModules = m: listOf (elemType.substSubModules m);
@@ -273,7 +280,10 @@ rec {
 
     nonEmptyListOf = elemType:
       let list = addCheck (types.listOf elemType) (l: l != []);
-      in list // { description = "non-empty " + list.description; };
+      in list // {
+        description = "non-empty " + list.description;
+        # Note: emptyValue is left as is, because another module may define an element.
+      };
 
     attrsOf = elemType: mkOptionType rec {
       name = "attrsOf";
@@ -285,6 +295,7 @@ rec {
           )
           # 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);
@@ -339,6 +350,7 @@ rec {
         description = "list or attribute set of ${elemType.description}s";
         check = x: isList x || isAttrs x;
         merge = loc: defs: attrOnly.merge loc (convertAllLists loc defs);
+        emptyValue = { value = {}; };
         getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
         getSubModules = elemType.getSubModules;
         substSubModules = m: loaOf (elemType.substSubModules m);
@@ -350,6 +362,7 @@ rec {
       name = "uniq";
       inherit (elemType) description check;
       merge = mergeOneOption;
+      emptyValue = elemType.emptyValue;
       getSubOptions = elemType.getSubOptions;
       getSubModules = elemType.getSubModules;
       substSubModules = m: uniq (elemType.substSubModules m);
@@ -367,6 +380,7 @@ rec {
         else if nrNulls != 0 then
           throw "The option `${showOption loc}` is defined both null and not null, in ${showFiles (getFiles defs)}."
         else elemType.merge loc defs;
+      emptyValue = { value = null; };
       getSubOptions = elemType.getSubOptions;
       getSubModules = elemType.getSubModules;
       substSubModules = m: nullOr (elemType.substSubModules m);
@@ -407,6 +421,7 @@ rec {
             args.name = last loc;
             prefix = loc;
           }).config;
+        emptyValue = { value = {}; };
         getSubOptions = prefix: (evalModules
           { inherit modules prefix specialArgs;
             # This is a work-around due to the fact that some sub-modules,
@@ -515,6 +530,7 @@ rec {
               if finalType.check val then val
               else coerceFunc val;
           in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
+        emptyValue = finalType.emptyValue;
         getSubOptions = finalType.getSubOptions;
         getSubModules = finalType.getSubModules;
         substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);