diff --git a/lib/modules.nix b/lib/modules.nix index ad573da990f4..a3c3fe7fc1ae 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -250,14 +250,14 @@ rec { # Add in the default value for this option, if any. defs' = (optional (opt ? default) { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs; + # Handle properties, check types, and merge everything together - inherit (mergeDefinitions loc opt.type defs') defsFinal mergedValue; + inherit (mergeDefinitions loc opt.type defs') isDefined defsFinal mergedValue; files = map (def: def.file) defsFinal; merged = - if defsFinal == [] then - throw "The option `${showOption loc}' is used but not defined." - else - mergedValue; + if isDefined then mergedValue + else throw "The option `${showOption loc}' is used but not defined."; + # Finally, apply the ‘apply’ function to the merged # value. This allows options to yield a value computed # from the definitions. @@ -265,8 +265,7 @@ rec { in opt // { value = addErrorContext "while evaluating the option `${showOption loc}':" value; definitions = map (def: def.value) defsFinal; - isDefined = defsFinal != []; - inherit files; + inherit isDefined files; }; # Merge definitions of a value of a given type @@ -295,6 +294,11 @@ rec { if type.check def.value then res else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.") (type.merge loc defsFinal) defsFinal; + + isDefined = defsFinal != []; + optionalValue = + if isDefined then { value = mergedValue; } + else {}; }; /* Given a config set, expand mkMerge properties, and push down the diff --git a/lib/types.nix b/lib/types.nix index 32f332ed21bb..f836b07e335f 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -6,10 +6,9 @@ with import ./attrsets.nix; with import ./options.nix; with import ./trivial.nix; with import ./strings.nix; +with {inherit (import ./modules.nix) mergeDefinitions; }; -let - inherit (import ./modules.nix) mergeDefinitions; -in rec { +rec { isType = type: x: (x._type or "") == type; @@ -114,11 +113,12 @@ in rec { check = isList; merge = loc: defs: map (x: x.value) (filter (x: x ? value) (concatLists (imap (n: def: imap (m: def': - let - inherit (mergeDefinitions (loc ++ ["[definition ${toString n}-entry ${toString m}]"]) - elemType [{ inherit (def) file; value = def'; }] - ) defsFinal mergedValue; - in if defsFinal == [] then {} else { value = mergedValue; }) def.value) defs))); + (mergeDefinitions + (loc ++ ["[definition ${toString n}-entry ${toString m}]"]) + elemType + [{ inherit (def) file; value = def'; }] + ).optionalValue + ) def.value) defs))); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); getSubModules = elemType.getSubModules; substSubModules = m: listOf (elemType.substSubModules m); @@ -129,10 +129,8 @@ in rec { check = isAttrs; merge = loc: defs: mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs: - let - inherit (mergeDefinitions (loc ++ [name]) elemType defs) - defsFinal mergedValue; - in if defsFinal == [] then {} else { value = mergedValue; }) + (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue + ) # Push down position info. (map (def: listToAttrs (mapAttrsToList (n: def': { name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs)));