summaryrefslogtreecommitdiffstats
path: root/lib/modules.nix
AgeCommit message (Collapse)Author
2020-10-26Merge pull request #101139 from roberth/lib-use-static-scope-checkingRobert Hensing
lib: Use Nix's static scope checking, fix error message, optimize
2020-10-24docs: update documentation of `mkRemovedOptionModule`Robert Helgesson
Since b08b0bcbbec77046e5a7082177cedc12fbf1dc6c, the function actually causes an assertion error, not a warning.
2020-10-22lib/modules: Simplify inheritsRobert Hensing
2020-10-22lib: Use Nix's static scope checking, fix error message, optimizeRobert Hensing
Nix can perform static scope checking, but whenever code is inside a `with` expression, the analysis breaks down, because it can't know statically what's in the attribute set whose attributes were brought into scope. In those cases, Nix has to assume that everything works out. Except it doesnt. Removing `with` from lib/ revealed an undefined variable in an error message. If that doesn't convince you that we're better off without `with`, I can tell you that this PR results in a 3% evaluation performance improvement because Nix can look up local variables by index. This adds up with applications like the module system. Furthermore, removing `with` makes the binding site of each variable obvious, which helps with comprehension.
2020-10-09Merge pull request #96641 from zimbatm/data-module-importszimbatm
nixos: Data module imports
2020-09-12lib: allow to import JSON and TOML fileszimbatm
The vision here is that configuration tools can generate .json or .toml files, which can be plugged into an existing configuration. Eg: { lib, ... }: { imports = [ (lib.modules.importJSON ./hardware-configuration.json) ]; }
2020-09-07lib/types: Allow types to emit a deprecation warningSilvan Mosberger
Previously the only way to deprecate a type was using theType = lib.warn "deprecated" (mkOptionType ...) This caused the warning to be emitted when the type was evaluated, but the error didn't include which option actually used that type. With this commit, types can specify a deprecationMessage, which when non-null, is printed along with the option that uses the type
2020-09-02treewide: completely remove types.loaOfrnhmjoj
2020-08-18lib/modules: improve error-message for undeclared options if prefix contains ↵Maximilian Bosch
no options An easy-to-make mistake when declaring e.g. a submodule is the accidental confusion of `options` and `config`: types.submodule { config = { foo = mkOption { /* ... */ }; }; } However the error-message The option `[definition 1-entry 1].foo' defined in `<expr.nix>' does not exist. is fairly unhelpful because it seems as the options are declared at the first sight. In fact, it took a colleague and me a while to track down such a mistake a few days ago and we both agreed that this should be somehow caught to save the time we spent debugging the module in question. At first I decided to catch this error in the `submodules`-type directly by checking whether `options` is undeclared, however this becomes fairly complicated as soon as a submodule-declaration e.g. depends on existing `config`-values which would've lead to some ugly `builtins.tryExec`-heuristic. This patch now simply checks if the option's prefix has any options defined if a point in evaluation is reached where it's clear that the option in question doesn't exist. This means that this patch doesn't change the logic of the module system, it only provides a more detailed error in certain cases: The option `[definition 1-entry 1].foo' defined in `<expr.nix>' does not exist. However it seems as there are no options defined in [definition 1-entry 1]. Are you sure you've declared your options properly? This happens if you e.g. declared your options in `types.submodule' under `config' rather than `options'.
2020-08-18lib/modules: Fix nonexistant option errorSilvan Mosberger
The refactoring in https://github.com/NixOS/nixpkgs/commit/fd75dc876586bde8cdb683a6952a41132e8db166 introduced a mistake in the error message that doesn't show the full context anymore. E.g. with this module: options.foo.bar = lib.mkOption { type = lib.types.submodule { baz = 10; }; default = {}; }; You'd get the error The option `baz' defined in `/home/infinisil/src/nixpkgs/config.nix' does not exist. instead of the previous The option `foo.bar.baz' defined in `/home/infinisil/src/nixpkgs/config.nix' does not exist. This commit undoes this regression
2020-08-14lib/modules: Add syntactic sugar for config._module.freeformTypeSilvan Mosberger
This introduces `freeformType` as a top-level module attribute, allowing definitions like { freeformType = ...; options = ...; config = ...; }
2020-08-10lib/modules: Fix freeform modules when there's no definitionsSilvan Mosberger
2020-08-03lib/modules: Implement freeform modulesSilvan Mosberger
For programs that have a lot of (Nix-representable) configuration options, a simple way to represent this in a NixOS module is to declare an option of a type like `attrsOf str`, representing a key-value mapping which then gets generated into a config file. However with such a type, there's no way to add type checking for only some key values. On the other end of the spectrum, one can declare a single separate option for every key value that the program supports, ending up with a module with potentially 100s of options. This has the benefit that every value gets type checked, catching mistakes at evaluation time already. However the disadvantage is that the module becomes big, becomes coupled to the program version and takes a lot of effort to write and maintain. Previously there was a middle ground between these two extremes: Declare an option of a type like `attrsOf str`, but declare additional separate options for the values you wish to have type checked, and assign their values to the `attrsOf str` option. While this works decently, it has the problem of duplicated options, since now both the additional options and the `attrsOf str` option can be used to set a key value. This leads to confusion about what should happen if both are set, which defaults should apply, and more. Now with this change, a middle ground becomes available that solves above problems: The module system now supports setting a freeform type, which gets used for all definitions that don't have an associated option. This means that you can now declare all options you wish to have type checked, while for the rest a freeform type like `attrsOf str` can be used.
2020-08-03lib/modules: Internally collect all unmatched definitionsSilvan Mosberger
This fundamentally changes how the module evaluation internally handles definitions without an associated option. Previously the values of these definitions were discarded and only the names were propagated. This was fine because that's all that's needed for optionally checking whether all definitions have an associated option with _module.check. However with the upcoming change of supporting freeform modules, we *do* need the values of these. With this change, the module evaluation cleanly separates definitions that match an option, and ones that do not.
2020-08-03lib/modules: Scope module evaluation variables more tightlySilvan Mosberger
This is a purely cosmetic change so it's easier to see dependencies between variables.
2020-09-21lib/modules: Evaluate single defs for readOnly errorSilvan Mosberger
If multiple definitions are passed, this evaluates them all as if they were the only one, for a better error message. In particular this won't show module-internal properties like `_type = "override"` and co.
2020-09-21lib/modules: Improve error messages using showDefsSilvan Mosberger
2020-03-19Revert "lib/modules: Throw better error when definitions assign to an option ↵Silvan Mosberger
set" This reverts commit 15c873b486347e7861c64fb0b5a7852be9fc82e4. This was causing infinite recursion when depending on nested options
2020-03-18lib/modules: Fix type checks not being done before mergingSilvan Mosberger
Co-Authored-By: Robert Hensing <robert@roberthensing.nl>
2020-03-18lib/modules: Throw better error when definitions assign to an option setSilvan Mosberger
2020-03-17lib/modules: Remove internal _module attribute from configSilvan Mosberger
The _module option is added as an internal option set, and it messes up the results of module evaluations, requiring people to manually filter _modules out. If people depend on this, they can still use config._module from inside the modules, exposing _module as an explicitly declared user option. Or alternatively with the _module attribute now returned by evalModules.
2020-02-24lib/modules.nix: Add file context to unmerged values in mergeDefinitionsRobert Hensing
This helps with troubleshooting exceptions in config values, which were hard to track down for options with many definitions. The trace will look like: error: while evaluating the attribute 'config.foo' at undefined position: [...] while evaluating the option `foo': [...] while evaluating definitions from `/home/user/mymod.nix': while evaluating 'dischargeProperties' at /home/user/nixpkgs/lib/modules.nix:464:25, called from /home/user/nixpkgs/lib/modules.nix:392:137: while evaluating the attribute 'value' at /home/user/nixpkgs/lib/modules.nix:277:44: Value error! where the `/home/user/mymod.nix` module is { lib, ... }: { options.foo = lib.mkOption { type = lib.types.lines; }; config.foo = builtins.throw "Value error!"; }
2020-01-20nixos/lib: Inherit type for doRename optionsJanne Heß
Co-authored-by: Silvan Mosberger <contact@infinisil.com>
2020-01-10lib/modules: Switch _module.args from attrsOf to lazyAttrsOfSilvan Mosberger
2020-01-10lib/modules: Move the isDefined check into mergedValueSilvan Mosberger
Without this change, accessing `mergedValue` from `mergeDefinitions` in case there are no definitions will throw an error like error: evaluation aborted with the following error message: 'This case should never happen.' This change makes it throw the appropriate error error: The option `foo' is used but not defined. This is fully backwards compatible.
2020-01-10lib/modules: Fix store importsSilvan Mosberger
This fixes imports from the store not being possible, which was caused by https://github.com/NixOS/nixpkgs/pull/76857 E.g. such a case: imports = [ "${home-manager}/nixos" ];
2020-01-09Merge pull request #76857 from Infinisil/recursive-disableModulesSilvan Mosberger
Apply `disabledModules` recursively
2020-01-09lib/modules: Recursive disabledModulesSilvan Mosberger
With this change, disabledModules applies recursively, meaning if you have a module "foo.nix" with imports = [ ./bar.nix ]; then setting disabledModules = [ "foo.nix" ]; will disable both "foo.nix" and "bar.nix", whereas previously only "foo.nix" would be disabled. This change along with https://github.com/NixOS/nixpkgs/pull/61570 allows modules to be fully disabled even when they have some `mkRenamedOption` imports.
2020-01-08Clarify error message of 'assigning to top-level attribute' (#76702)Silvan Mosberger
Clarify error message of 'assigning to top-level attribute'
2020-01-05lib/modules: clarify error message of 'assigning to top-level attribute'Arnout Engelen
If I understand correctly, the problem isn't so much that you're assigning to that top-level attribute, but that the assignment to the attribute (or any child of the attribute) introduces the 'config' object and prevents 'lifting' all settings to a generated 'config' object.
2020-01-01lib/modules: Don't pack submodules speciallySilvan Mosberger
This has the beneficial side effect of allowing paths to be used as modules in types.{submodule,submoduleWith}
2019-12-05lib/modules: Make unifyModuleSyntax fully idempotentSilvan Mosberger
Because why not
2019-12-05lib/modules: file -> _file for a more idempotent unifyModuleSyntaxSilvan Mosberger
This will be useful for doing more complicated module evaluations
2019-11-04Add note: Keep error message in sync with nixos-optionChuck
2019-10-02Merge pull request #69746 from Infinisil/rem-opt-usage-messageSilvan Mosberger
lib.mkRemovedOptionModule: Show replacement for option usage too
2019-09-30mkRemovedOptionModule: assert on removed optionsRobin Gloster
We don't want to ignore config that can mess up machines. In general this should always fail evaluation, as you think you are changing behaviour and don't, which can easily create run-time errors we can catch early.
2019-09-28lib.mkRemovedOptionModule: Show replacement for option usage tooSilvan Mosberger
Previously mkRemovedOptionModule would only show the replacement instructions when the removed option was *defined*. With this change, it also does so when an option is *used*. This is essential for options that are only intended to be used such as `security.acme.directory`, whose replacement instructions would never trigger without this change because almost everybody only uses the option and isn't defining it.
2019-08-10lib/modules: Use options `apply` function even if no values are definedSilvan Mosberger
This allows `apply` functions to return a valid value if they completely ignore their argument, which is the case for the option renaming functions like `mkAliasOptionModule`. Therefore this solves issue #63693
2019-03-07module system: revert "remove types.optionSet", just deprecate (#56857)Danylo Hlynskyi
The explicit remove helped to uncover some hidden uses of `optionSet` in NixOps. However it makes life harder for end-users of NixOps - it will be impossible to deploy 19.03 systems with old NixOps, but there is no new release of NixOps with `optionSet` fixes. Also, "deprecation" process isn't well defined. Even that `optionSet` was declared "deprecated" for many years, it was never announced. Hence, I leave "deprecation" announce. Then, 3 releases after announce, we can announce removal of this feature. This type has to be removed, not `throw`-ed in runtime, because it makes some perfectly fine code to fail. For example: ``` $ nix-instantiate --eval -E '(import <nixpkgs/lib>).types' --strict trace: `types.list` is deprecated; use `types.listOf` instead error: types.optionSet is deprecated; use types.submodule instead (use '--show-trace' to show detailed location information) ```
2019-02-23Merge pull request #54528 from cdepillabout/module-alias-uses-prioritySilvan Mosberger
lib/modules: Change mkAliasOptionModule to use the priority for the alias
2019-01-31types.optionSet: deprecate and remove last usagesdanbst
2019-01-30lib/modules.nix: small eval optimization (foldl' + foldl' + attrNames -> ↵danbst
foldl' + mapAttrs)
2019-01-24lib/modules: Change mkAliasOptionModule to use the priority for the alias.(cdep)illabout
This commit changes the `mkAliasOptionModule` function to make sure that the priority for the aliased option is propagated to the non-aliased option. This also affects the `mkRenamedOptionModule` function in a similar fashion. This also removes the `mkAliasOptionModuleWithPriority` function, since its functionality is now subsumed by `mkAliasOptionModule`. This change was recommended by @nbp: https://github.com/NixOS/nixpkgs/pull/53397#discussion_r245487432
2019-01-06Pull out defaultPriority to a top-level definition.(cdep)illabout
2019-01-04lib/modules: Add a function to create an option alias that respects the priority(cdep)illabout
This commit adds a function `mkAliasOptionModuleWithPriority`. This function will make an alias to an existing option and copy over the priority. This functionality is needed for PRs like #53041. In that case `nixos-generate-config` added an option to `hardware-configuration.nix` with `mkDefault`. That option was then changed and an alias created for the old name. The end user should be able to set the non-alias option in their `configuration.nix` and have everything work correctly. Without this function, the priority for the option won't be copied over correctly and the end-user will get a message saying they have the same option set to two different values.
2018-08-27module system: rework module mergingSymphorien Gibol
The asymptotic complexity is now much lower.
2018-07-20[bot]: remove unreferenced codevolth
2018-06-27Merge pull request #42138 from NixOS/yegortimoshenko-patch-6xeji
lib/modules: decrease mkOptionDefault priority to 1500
2018-06-17lib/modules: bump mkOptionDefault priority to 1500Yegor Timoshenko
2018-06-11lib: fix and simplify `doRename`Jan Malakhovski
Before this change `mkRenamedOptionModule` would override option defaults even when the old option name is left unused. For instance ```nix { optios = { services.name.new = mkOption { default = { one = {}; }; }; }; imports = [ (mkRenamedOptionModule [ "services" "name" "old" ] [ "services" "name" "new" "two" ]) ]; config = {}; } ``` would evaluate to `{ config.services.name.new = { two = {}; }; }` when you'd expect it to evaluate to `{ config.services.name.new = { one = {}; }; }`.