Skip to content

Commit

Permalink
lib/modules: Report a good error when option tree has bare type
Browse files Browse the repository at this point in the history
Note that this removes the possibility of declaring an option
named `_type`.
  • Loading branch information
roberth committed Aug 14, 2023
1 parent 450d643 commit 0d472a6
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 1 deletion.
34 changes: 33 additions & 1 deletion lib/modules.nix
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,13 @@ let
loc = prefix ++ [name];
defns = pushedDownDefinitionsByName.${name} or [];
defns' = rawDefinitionsByName.${name} or [];
optionDecls = filter (m: isOption m.options) decls;
optionDecls = filter
(m: m.options?_type
&& (m.options._type == "option"
|| throwDeclarationTypeError loc m.options._type
)
)
decls;
in
if length optionDecls == length decls then
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
Expand Down Expand Up @@ -692,6 +698,32 @@ let
) unmatchedDefnsByName);
};

throwDeclarationTypeError = loc: actualTag:
let
name = lib.strings.escapeNixIdentifier (lib.lists.last loc);
path = showOption loc;
depth = length loc;

paragraphs = [
"Expected an option declaration at option path `${path}` but got an attribute set with type ${actualTag}"
] ++ optional (actualTag == "option-type") ''
When declaring an option, you must wrap the type in a `mkOption` call. It should look somewhat like:
${comment}
${name} = lib.mkOption {
description = ...;
type = <the type you wrote for ${name}>;
...
};
'';

# Ideally we'd know the exact syntax they used, but short of that,
# we can only reliably repeat the last. However, we repeat the
# full path in a non-misleading way here, in case they overlook
# the start of the message. Examples attract attention.
comment = optionalString (depth > 1) "\n # ${showOption loc}";
in
throw (concatStringsSep "\n\n" paragraphs);

/* Merge multiple option declarations into a single declaration. In
general, there should be only one declaration of each option.
The exception is the ‘options’ attribute, which specifies
Expand Down
5 changes: 5 additions & 0 deletions lib/tests/modules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,11 @@ checkConfigError \
config.set \
./declare-set.nix ./declare-enable-nested.nix

# Options: accidental use of an option-type instead of option (or other tagged type; unlikely)
checkConfigError 'Expected an option declaration at option path .result. but got an attribute set with type option-type' config.result ./options-type-error-typical.nix
checkConfigError 'Expected an option declaration at option path .result.here. but got an attribute set with type option-type' config.result.here ./options-type-error-typical-nested.nix
checkConfigError 'Expected an option declaration at option path .result. but got an attribute set with type configuration' config.result ./options-type-error-configuration.nix

# Check that that merging of option collisions doesn't depend on type being set
checkConfigError 'The option .group..*would be a parent of the following options, but its type .<no description>. does not support nested options.\n\s*- option.s. with prefix .group.enable..*' config.group.enable ./merge-typeless-option.nix

Expand Down
6 changes: 6 additions & 0 deletions lib/tests/modules/options-type-error-configuration.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ lib, ... }: {
options = {
# unlikely mistake, but we can catch any attrset with _type
result = lib.evalModules { modules = []; };
};
}
5 changes: 5 additions & 0 deletions lib/tests/modules/options-type-error-typical-nested.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{ lib, ... }: {
options = {
result.here = lib.types.str;
};
}
5 changes: 5 additions & 0 deletions lib/tests/modules/options-type-error-typical.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{ lib, ... }: {
options = {
result = lib.types.str;
};
}

0 comments on commit 0d472a6

Please sign in to comment.