lol

lib.modules: Use types.optionType for _module.freeformType

This ensures that the module file locations are propagated to the
freeform type, which makes it so that submodules in freeform types now
have their declaration location shown in the manual, fixing
https://github.com/NixOS/nixpkgs/issues/132085.

In addition, this also newly allows freeformTypes to be declared
multiple times and all declarations being merged together according to
normal option merging.

This also removes some awkwardness regarding the type of `freeformType`

+28 -2
+1 -2
lib/modules.nix
··· 151 151 }; 152 152 153 153 _module.freeformType = mkOption { 154 - # Disallow merging for now, but could be implemented nicely with a `types.optionType` 155 - type = types.nullOr (types.uniq types.attrs); 154 + type = types.nullOr types.optionType; 156 155 internal = true; 157 156 default = null; 158 157 description = ''
+5
lib/tests/modules.sh
··· 240 240 checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.nix ./freeform-unstr-dep-str.nix 241 241 checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix 242 242 checkConfigOutput '^"24"$' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix 243 + # submodules in freeformTypes should have their locations annotated 244 + checkConfigOutput '/freeform-submodules.nix"$' config.fooDeclarations.0 ./freeform-submodules.nix 245 + # freeformTypes can get merged using `types.type`, including submodules 246 + checkConfigOutput '^10$' config.free.xxx.foo ./freeform-submodules.nix 247 + checkConfigOutput '^10$' config.free.yyy.bar ./freeform-submodules.nix 243 248 244 249 ## types.anything 245 250 # Check that attribute sets are merged recursively
+22
lib/tests/modules/freeform-submodules.nix
··· 1 + { lib, options, ... }: with lib.types; { 2 + 3 + options.fooDeclarations = lib.mkOption { 4 + default = (options.free.type.getSubOptions [])._freeformOptions.foo.declarations; 5 + }; 6 + 7 + options.free = lib.mkOption { 8 + type = submodule { 9 + config._module.freeformType = lib.mkMerge [ 10 + (attrsOf (submodule { 11 + options.foo = lib.mkOption {}; 12 + })) 13 + (attrsOf (submodule { 14 + options.bar = lib.mkOption {}; 15 + })) 16 + ]; 17 + }; 18 + }; 19 + 20 + config.free.xxx.foo = 10; 21 + config.free.yyy.bar = 10; 22 + }