This will let us make assertions involving _module.args.pkgs, which is not an option but a value attribute, and therefore doesn't have its own highestPrio to inspect. The new function gives us that info.
···910910 else opt // { type = opt.type.substSubModules opt.options; options = []; };
911911912912913913+ /*
914914+ Merge an option's definitions in a way that preserves the priority of the
915915+ individual attributes in the option value.
916916+917917+ This does not account for all option semantics, such as readOnly.
918918+919919+ Type:
920920+ option -> attrsOf { highestPrio, value }
921921+ */
922922+ mergeAttrDefinitionsWithPrio = opt:
923923+ let subAttrDefs =
924924+ lib.concatMap
925925+ ({ value, ... }@def:
926926+ map
927927+ (value: def // { inherit value; })
928928+ (lib.pushDownProperties value)
929929+ )
930930+ opt.definitionsWithLocations;
931931+ defsByAttr =
932932+ lib.zipAttrs (
933933+ lib.concatLists (
934934+ lib.concatMap
935935+ ({ value, ... }@def:
936936+ map
937937+ (lib.mapAttrsToList (k: value: { ${k} = def // { inherit value; }; }))
938938+ (lib.pushDownProperties value)
939939+ )
940940+ opt.definitionsWithLocations
941941+ )
942942+ );
943943+ in
944944+ assert opt.type.name == "attrsOf" || opt.type.name == "lazyAttrsOf";
945945+ lib.mapAttrs
946946+ (k: v:
947947+ let merging = lib.mergeDefinitions (opt.loc ++ [k]) opt.type.nestedTypes.elemType v;
948948+ in {
949949+ value = merging.mergedValue;
950950+ inherit (merging.defsFinal') highestPrio;
951951+ })
952952+ defsByAttr;
953953+913954 /* Properties. */
914955915956 mkIf = condition: content:
···12561297 importJSON
12571298 importTOML
12581299 mergeDefinitions
13001300+ mergeAttrDefinitionsWithPrio
12591301 mergeOptionDecls # should be private?
12601302 mkAfter
12611303 mkAliasAndWrapDefinitions
+2
lib/tests/modules.sh
···6161# Shorthand meta attribute does not duplicate the config
6262checkConfigOutput '^"one two"$' config.result ./shorthand-meta.nix
63636464+checkConfigOutput '^true$' config.result ./test-mergeAttrDefinitionsWithPrio.nix
6565+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