-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disallow declaring options named config
and options
(and others)
#162398
Comments
Sounds good, disallowing defining options that could also be in the top-level makes sense since we're allowing to collapse the One way to fix that is to check those during evaluation and fail if they exist. Then add yet another top-level There are some other points presented, but they don't seem more adjacent than being a requirement to this core change (I would love to rename |
What about the |
Yes. We should take care not to make it worse than the current situation, where the user can solve it by putting the settings in a |
Oh damn yeah I didn't think of that, that makes this a bit more tricky.. So I think we can still allow arbitrary option names, but throw an ambiguity error when shorthand syntax is used with a value that could be either a section name or an option name, which then forces the canonical syntax to be used in such cases. While this makes setting options matching a section name a bit annoying (since you have to do {
options.options = lib.mkOption {
# If this is not passed, a warning or an error is thrown
# This is only needed (and allowed) for options that match a section name
# The effect of this option is that it requires canonical syntax in ambiguous cases
ignoreSectionNameConflict = true;
};
} This way, we can restrict such options only to where they're really needed with NixOS/rfcs#42 |
Sounds good. For new nixos users, this collapsing logic is not super clear. Most examples they first encounter are config-only and they get confused about the nature of nixos modules. Anything that makes this a bit stricter and exposes the underlying structure is a good thing. I would even be in favour of forcing the |
I agree. Having multiple ways to do the same basic thing made NixOS options quite confusing to me when I started, and still sometimes tricks me today. |
Issue description
Options being allowed to be named
config
andoptions
causes problems related to module syntax. The canonical module syntax has a number of sections, mainlyconfig
,options
,imports
,disabledModules
andfreeformType
, which are the only allowed top-level attributes. This might look likeBut another syntax, sometimes called shorthand syntax, is also supported, which triggers when neither
options
norconfig
is set. In this alternate syntax, setting arbitrary attributes is valid, with the semantics that they get put into theconfig
section. This might look like this:This is then equivalent to
If you don't need any option definitions, this syntax is more convenient.
The problem arises when you have options with names matching the section names, such as
config
,options
,imports
, or others. Assuming we have an option namedoptions
, then we can't use the convenient shorthand syntax:To actually declare this option you need to use
Similarly, if you have an option named
config
, you can't dobut instead need to write
If options have a name matching another section name, like
imports
ordisallowedModules
, shorthand syntax also can't be used, because these attributes are interpreted as sections, not options definitions. E.g. with an option namedimports
, the following doesn't work:Instead this is needed:
These same problems are also caused by submodules, except that there it's even more nuanced, because submodules declared with
types.submodule
historically have always forced the shorthand syntax by wrapping its definitions into aconfig
value. This was done to prevent surprises when trying to set aconfig
option. E.g. if you have an optionfoo
of typetypes.submodule
, which itself has a nestedconfig
option, then you can do this:Instead of having to do this:
But the flip side is that there's no way to then declare non-
config
sections. The only known hack around this is to declare values as a function, because only attribute values are wrapped underconfig
(since anything else wouldn't be valid as av config value):With the introduction of
types.submoduleWith
, a parametershorthandOnlyDefinesConfig
was introduced, which controls whether thisconfig
wrapping is done, defaulting to it not being done (in contrast withtypes.submodule
)Suggested solution
By disallowing options to be named according to a section name, we can always know whether an attribute is a section or an option name, allowing us to avoid all these problems:
config
wrapping fortypes.submodule
andtypes.submoduleWith
can be removed, cleaning up code and removing the need for function hacks.options
orconfig
being set implies canonical syntax" to just "config
being set implies canonical syntax". If options can't be namedoptions
, then there's no reason options couldn't be declared using anoptions
attribute while using shorthand syntax forconfig
.The hardest part is backwards compatibility and transition, because in NixOS there are a whole bunch of options named
config
and some namedoptions
(and one namedimports
). Another section name that could be problematic iskey
.We should also consider whether it's possible to rename
config
andoptions
to something else. I've heard complaints in the past that these have been confusing.Ping @roberth @zimbatm
The text was updated successfully, but these errors were encountered: