File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 910910 else opt // { type = opt . type . substSubModules opt . options ; options = [ ] ; } ;
911911
912912
913+ /*
914+ Merge an option's definitions in a way that preserves the priority of the
915+ individual attributes in the option value.
916+
917+ This does not account for all option semantics, such as readOnly.
918+
919+ Type:
920+ option -> attrsOf { highestPrio, value }
921+ */
922+ mergeAttrDefinitionsWithPrio = opt :
923+ let subAttrDefs =
924+ lib . concatMap
925+ ( { value , ... } @def :
926+ map
927+ ( value : def // { inherit value ; } )
928+ ( lib . pushDownProperties value )
929+ )
930+ opt . definitionsWithLocations ;
931+ defsByAttr =
932+ lib . zipAttrs (
933+ lib . concatLists (
934+ lib . concatMap
935+ ( { value , ... } @def :
936+ map
937+ ( lib . mapAttrsToList ( k : value : { ${ k } = def // { inherit value ; } ; } ) )
938+ ( lib . pushDownProperties value )
939+ )
940+ opt . definitionsWithLocations
941+ )
942+ ) ;
943+ in
944+ assert opt . type . name == "attrsOf" || opt . type . name == "lazyAttrsOf" ;
945+ lib . mapAttrs
946+ ( k : v :
947+ let merging = lib . mergeDefinitions ( opt . loc ++ [ k ] ) opt . type . nestedTypes . elemType v ;
948+ in {
949+ value = merging . mergedValue ;
950+ inherit ( merging . defsFinal' ) highestPrio ;
951+ } )
952+ defsByAttr ;
953+
913954 /* Properties. */
914955
915956 mkIf = condition : content :
@@ -1256,6 +1297,7 @@ private //
12561297 importJSON
12571298 importTOML
12581299 mergeDefinitions
1300+ mergeAttrDefinitionsWithPrio
12591301 mergeOptionDecls # should be private?
12601302 mkAfter
12611303 mkAliasAndWrapDefinitions
Original file line number Diff line number Diff line change @@ -61,6 +61,8 @@ checkConfigError() {
6161# Shorthand meta attribute does not duplicate the config
6262checkConfigOutput ' ^"one two"$' config.result ./shorthand-meta.nix
6363
64+ checkConfigOutput ' ^true$' config.result ./test-mergeAttrDefinitionsWithPrio.nix
65+
6466# Check boolean option.
6567checkConfigOutput ' ^false$' config.enable ./declare-enable.nix
6668checkConfigError ' The option .* does not exist. Definition values:\n\s*- In .*: true' config.enable ./define-enable.nix
Original file line number Diff line number Diff line change 1+ { lib , options , ... } :
2+
3+ let
4+ defs = lib . modules . mergeAttrDefinitionsWithPrio options . _module . args ;
5+ assertLazy = pos : throw "${ pos . file } :${ toString pos . line } :${ toString pos . column } : The test must not evaluate this the assertLazy thunk, but it did. Unexpected strictness leads to unexpected errors and performance problems." ;
6+ in
7+
8+ {
9+ options . result = lib . mkOption { } ;
10+ config . _module . args = {
11+ default = lib . mkDefault ( assertLazy __curPos ) ;
12+ regular = null ;
13+ force = lib . mkForce ( assertLazy __curPos ) ;
14+ unused = assertLazy __curPos ;
15+ } ;
16+ config . result =
17+ assert defs . default . highestPrio == ( lib . mkDefault ( assertLazy __curPos ) ) . priority ;
18+ assert defs . regular . highestPrio == lib . modules . defaultOverridePriority ;
19+ assert defs . force . highestPrio == ( lib . mkForce ( assertLazy __curPos ) ) . priority ;
20+ true ;
21+ }
You can’t perform that action at this time.
0 commit comments