lib.types.functionTo: Support type merging

Changed files
+62
lib
tests
modules
+1
lib/tests/modules.sh
···
checkConfigError 'A definition for option .fun.\[function body\]. is not of type .string.. Definition values:\n\s*- In .*wrong-type.nix' config.result ./functionTo/wrong-type.nix
checkConfigOutput '^"b a"$' config.result ./functionTo/list-order.nix
checkConfigOutput '^"a c"$' config.result ./functionTo/merging-attrs.nix
+
checkConfigOutput '^"fun.\[function body\].a fun.\[function body\].b"$' config.result ./functionTo/submodule-options.nix
# moduleType
checkConfigOutput '^"a b"$' config.resultFoo ./declare-variants.nix ./define-variant.nix
+59
lib/tests/modules/functionTo/submodule-options.nix
···
+
{ lib, config, options, ... }:
+
let
+
inherit (lib) types;
+
in
+
{
+
imports = [
+
+
# fun.<function-body>.a
+
({ ... }: {
+
options = {
+
fun = lib.mkOption {
+
type = types.functionTo (types.submodule {
+
options.a = lib.mkOption { };
+
});
+
};
+
};
+
})
+
+
# fun.<function-body>.b
+
({ ... }: {
+
options = {
+
fun = lib.mkOption {
+
type = types.functionTo (types.submodule {
+
options.b = lib.mkOption { };
+
});
+
};
+
};
+
})
+
];
+
+
options = {
+
result = lib.mkOption
+
{
+
type = types.str;
+
default = lib.concatStringsSep " "
+
(lib.concatLists
+
(lib.mapAttrsToList
+
(k: v:
+
if k == "_module"
+
then [ ]
+
else [ (lib.showOption v.loc) ]
+
)
+
(
+
(options.fun.type.getSubOptions [ "fun" ])
+
)
+
)
+
);
+
};
+
};
+
+
config.fun = lib.mkMerge
+
[
+
(input: { inherit (input) a; })
+
(input: { inherit (input) b; })
+
(input: {
+
b = lib.mkForce input.c;
+
})
+
];
+
}
+2
lib/types.nix
···
getSubOptions = elemType.getSubOptions;
getSubModules = elemType.getSubModules;
substSubModules = m: functionTo (elemType.substSubModules m);
+
functor = (defaultFunctor "functionTo") // { wrapped = elemType; };
+
nestedTypes.elemType = elemType;
};
# A submodule (like typed attribute set). See NixOS manual.