types.attrListWith: review fixes

- Improve extractItem error messages: distinguish non-attrset elements
  from multi-key attrsets, and include the faulty definition via showDefs.
- Use isType instead of raw _type access for order detection.
- Disable type merging (typeMerge = t: null) instead of providing a
  functor-based merge. Add test confirming duplicate declarations fail.
This commit is contained in:
Johannes Kirschbauer
2026-05-24 15:23:24 +02:00
parent 8aa6e3dbb9
commit ae142b5738
3 changed files with 32 additions and 12 deletions

View File

@@ -902,13 +902,16 @@ checkConfigError 'Did you mean .services\.nginx\.virtualHosts\."example\.com"\.s
# types.attrListOf
checkConfigOutput '"ok"' config.assertions ./declare-attrList.nix
checkConfigError 'A definition for option .attrListInt.badValue.a. is not of type .signed integer.. Definition values:' config.attrListIntStrict.badValue ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badListElem. is not of type .attribute list of string.. Each list element must be a single-key attribute set.' config.attrListStrict.badListElem ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badListElem. is not of type .attribute list of string.. Each list element must be a single-key attribute set, but got 2 keys' config.attrListStrict.badListElem ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badString. is not of type .attribute list of string.. TypeError: Definition values:' config.attrListStrict.badString ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badListString. is not of type .attribute list of string.. Each list element must be a single-key attribute set.' config.attrListStrict.badListString ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badListString. is not of type .attribute list of string.. Each list element must be an attribute set, but got string' config.attrListStrict.badListString ./declare-attrList.nix
# attrListWith valueMeta.definitions: file propagation
checkConfigError 'the-defs-file\.nix' config.argv ./attrList-valueMeta-definitions-file-diagnostic-forwarding.nix
# attrListOf does not support type merging
checkConfigError 'The option .merged. in .*/declare-attrList-type-merge.nix. is already declared in .*/declare-attrList-type-merge.nix' config.merged ./declare-attrList-type-merge.nix
cat <<EOF
====== module tests ======
$pass Pass

View File

@@ -0,0 +1,12 @@
# Test that attrListOf does not support type merging:
# two declarations of the same option should fail.
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
imports = [
{ options.merged = mkOption { type = types.attrListOf types.str; }; }
{ options.merged = mkOption { type = types.attrListOf types.str; }; }
];
}

View File

@@ -876,7 +876,7 @@ rec {
extractItem =
file: raw:
let
hasOrder = raw._type or null == "order";
hasOrder = isType "order" raw;
item = if hasOrder then raw.content else raw;
key = head (attrNames item);
peeled = peelProperties item.${key};
@@ -888,7 +888,19 @@ rec {
prio = if hasOrder then raw.priority else peeled.prio;
}
else
throw "A definition for option `${showOption loc}' is not of type `${description}'. Each list element must be a single-key attribute set.";
throw "A definition for option `${showOption loc}' is not of type `${description}'. ${
if !isAttrs item then
"Each list element must be an attribute set, but got ${builtins.typeOf item}"
else
"Each list element must be a single-key attribute set, but got ${toString (length (attrNames item))} keys"
}.${
showDefs [
{
inherit file;
value = raw;
}
]
}";
# Convert a definition to a flat list of { file, key, value, prio, overridePrio }
defToItems =
@@ -969,14 +981,7 @@ rec {
inherit asAttrs mergeAttrValues;
elemType = elemType.substSubModules m;
};
functor = elemTypeFunctor name { inherit elemType; } // {
type =
payload:
types.attrListWith {
inherit asAttrs mergeAttrValues;
inherit (payload) elemType;
};
};
typeMerge = t: null; # Disable type merging
nestedTypes.elemType = elemType;
};