lib.types.attrTag: Support type merging

This commit is contained in:
Robert Hensing 2024-01-29 08:14:36 +01:00
parent 42d3b54f0d
commit 0bc9783221
2 changed files with 32 additions and 1 deletions

View File

@ -39,6 +39,9 @@ in
yay = mkOption {
type = types.int;
};
extensible = mkOption {
type = types.enum [ "foo" ];
};
}
);
};
@ -71,6 +74,9 @@ in
nay = mkOption {
type = types.bool;
};
extensible = mkOption {
type = types.enum [ "bar" ];
};
}
);
};
@ -89,11 +95,15 @@ in
nested.right.left = "not a number";
merged.negative.nay = false;
merged.positive.yay = 100;
merged.extensi-foo.extensible = "foo";
merged.extensi-bar.extensible = "bar";
okChecks =
assert config.intStrings.hello.right == "hello world";
assert config.intStrings.numberOne.left == 1;
assert config.merged.negative.nay == false;
assert config.merged.positive.yay == 100;
assert config.merged.extensi-foo.extensible == "foo";
assert config.merged.extensi-bar.extensible == "bar";
# assert lib.foldl' (a: b: builtins.trace b a) true (lib.attrNames config.docs);
assert config.docs."submodules.<name>.foo.bar".type == "signed integer";
assert config.docs."submodules.<name>.qux".type == "string";

View File

@ -667,7 +667,28 @@ rec {
}
else throw "The option `${showOption loc}` is defined as ${lib.strings.escapeNixIdentifier choice}, but ${lib.strings.escapeNixIdentifier choice} is not among the valid choices (${choicesStr}). Value ${choice} was defined in ${showFiles (getFiles defs)}.";
nestedTypes = tags;
functor = (defaultFunctor "attrTagWith") // { payload = { inherit tags; }; binOp = a: b: { tags = a.tags // b.tags; }; };
functor = (defaultFunctor "attrTagWith") // {
payload = { inherit tags; };
binOp =
let
# Add metadata in the format that submodules work with
wrapOptionDecl =
option: { options = option; _file = "<attrTag {...}>"; pos = null; };
in
a: b: {
tags = a.tags // b.tags //
mapAttrs
(tagName: bOpt:
lib.mergeOptionDecls
# FIXME: loc is not accurate; should include prefix
# Fortunately, it's only used for error messages, where a "relative" location is kinda ok.
# It is also returned though, but use of the attribute seems rare?
[tagName]
[ (wrapOptionDecl a.tags.${tagName}) (wrapOptionDecl bOpt) ]
)
(builtins.intersectAttrs a.tags b.tags);
};
};
};
uniq = unique { message = ""; };