diff --git a/lib/modules.nix b/lib/modules.nix index 8b9a925d718a..d7125e60b8e5 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1185,29 +1185,32 @@ let throw "The option `${showOption loc}' was accessed but has no value defined. Try setting the option."; - ensureMergedValueEnvelope = - v: - if attrNames v == attrNames defaultCheckedAndMerged then - v - else - throw "Invalid 'type.merge.v2' of type: '${type.name}' must return exactly the following attributes: ${builtins.toJSON (attrNames defaultCheckedAndMerged)} but got ${builtins.toJSON (attrNames v)}"; - - defaultCheckedAndMerged = { - headError = null; - value = mergedValue; - valueMeta = { }; - }; - - checkedAndMerged = ensureMergedValueEnvelope ( - if type.merge ? v2 then - type.merge.v2 { - inherit loc; - defs = defsFinal; - } - else - defaultCheckedAndMerged - - ); + checkedAndMerged = + ( + # This function (which is immediately applied) checks that type.merge + # returns the proper attrset. + # Once use of the merge.v2 feature has propagated, consider removing this + # for an estimated one thousandth performance improvement (NixOS by nr.thunks). + { + headError, + value, + valueMeta, + }@args: + args + ) + ( + if type.merge ? v2 then + type.merge.v2 { + inherit loc; + defs = defsFinal; + } + else + { + headError = null; + value = mergedValue; + valueMeta = { }; + } + ); isDefined = defsFinal != [ ]; diff --git a/lib/types.nix b/lib/types.nix index a6b3e6fb83fb..40d0eb6c49f8 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -1503,23 +1503,27 @@ let v2 = { loc, defs }: let - isMergeV2 = coercedType.merge ? v2; - coerceDef = - def: - let - merged = coercedType.merge.v2 { - inherit loc; - defs = [ def ]; - }; - in - if isMergeV2 then - if merged.headError == null then coerceFunc def.value else def.value - else if coercedType.check def.value then - coerceFunc def.value - else - def.value; - - finalDefs = (map (def: def // { value = coerceDef def; }) defs); + finalDefs = ( + map ( + def: + def + // { + value = + let + merged = coercedType.merge.v2 { + inherit loc; + defs = [ def ]; + }; + in + if coercedType.merge ? v2 then + if merged.headError == null then coerceFunc def.value else def.value + else if coercedType.check def.value then + coerceFunc def.value + else + def.value; + } + ) defs + ); in if finalType.merge ? v2 then finalType.merge.v2 { @@ -1530,7 +1534,7 @@ let { value = finalType.merge loc finalDefs; valueMeta = { }; - headError = checkDefsForError check loc finalDefs; + headError = checkDefsForError check loc defs; }; }; emptyValue = finalType.emptyValue;