diff --git a/lib/modules.nix b/lib/modules.nix index 959abf5e51e..f64adaf1b19 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -264,43 +264,46 @@ rec { 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') isDefined defsFinal mergedValue; - files = map (def: def.file) defsFinal; - merged = - if isDefined then mergedValue - else throw "The option `${showOption loc}' is used but not defined."; + # Handle properties, check types, and merge everything together. + res = mergeDefinitions loc opt.type defs'; + + # Check whether the option is defined, and apply the ‘apply’ + # function to the merged value. This allows options to yield a + # value computed from the definitions. + value = + if !res.isDefined then + throw "The option `${showOption loc}' is used but not defined." + else if opt ? apply then + opt.apply res.mergedValue + else + res.mergedValue; - # Finally, apply the ‘apply’ function to the merged - # value. This allows options to yield a value computed - # from the definitions. - value = (opt.apply or id) merged; in opt // { value = addErrorContext "while evaluating the option `${showOption loc}':" value; definitions = map (def: def.value) defsFinal; - inherit isDefined files; + files = map (def: def.file) res.defsFinal; + inherit (res) isDefined; }; # Merge definitions of a value of a given type. mergeDefinitions = loc: type: defs: rec { defsFinal = let - # Process mkMerge and mkIf properties - processIfAndMerge = defs: concatMap (m: + # Process mkMerge and mkIf properties. + defs' = concatMap (m: map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value) ) defs; - # Process mkOverride properties - processOverride = defs: filterOverrides defs; + # Process mkOverride properties. + defs'' = filterOverrides defs'; - # Sort mkOrder properties - processOrder = defs: + # Sort mkOrder properties. + defs''' = # Avoid sorting if we don't have to. - if any (def: def.value._type or "" == "order") defs - then sortProperties defs - else defs; - in - processOrder (processOverride (processIfAndMerge defs)); + if any (def: def.value._type or "" == "order") defs'' + then sortProperties defs'' + else defs''; + in defs'''; # Type-check the remaining definitions, and merge them. mergedValue = foldl' (res: def: