diff --git a/lib/modules.nix b/lib/modules.nix index e9fc1007fc20..79d54e4a5387 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -151,8 +151,7 @@ rec { }; _module.freeformType = mkOption { - # Disallow merging for now, but could be implemented nicely with a `types.optionType` - type = types.nullOr (types.uniq types.attrs); + type = types.nullOr types.optionType; internal = true; default = null; description = '' diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index d11f32e59964..e4bb7ad21900 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -240,6 +240,11 @@ checkConfigOutput '^"24"$' config.foo ./freeform-attrsOf.nix ./freeform-str-dep- checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.nix ./freeform-unstr-dep-str.nix checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix checkConfigOutput '^"24"$' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix +# submodules in freeformTypes should have their locations annotated +checkConfigOutput '/freeform-submodules.nix"$' config.fooDeclarations.0 ./freeform-submodules.nix +# freeformTypes can get merged using `types.type`, including submodules +checkConfigOutput '^10$' config.free.xxx.foo ./freeform-submodules.nix +checkConfigOutput '^10$' config.free.yyy.bar ./freeform-submodules.nix ## types.anything # Check that attribute sets are merged recursively diff --git a/lib/tests/modules/freeform-submodules.nix b/lib/tests/modules/freeform-submodules.nix new file mode 100644 index 000000000000..3910435a7b5c --- /dev/null +++ b/lib/tests/modules/freeform-submodules.nix @@ -0,0 +1,22 @@ +{ lib, options, ... }: with lib.types; { + + options.fooDeclarations = lib.mkOption { + default = (options.free.type.getSubOptions [])._freeformOptions.foo.declarations; + }; + + options.free = lib.mkOption { + type = submodule { + config._module.freeformType = lib.mkMerge [ + (attrsOf (submodule { + options.foo = lib.mkOption {}; + })) + (attrsOf (submodule { + options.bar = lib.mkOption {}; + })) + ]; + }; + }; + + config.free.xxx.foo = 10; + config.free.yyy.bar = 10; +}