Skip to content
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

Submodules need a default value #161566

Open
roberth opened this issue Feb 23, 2022 · 1 comment
Open

Submodules need a default value #161566

roberth opened this issue Feb 23, 2022 · 1 comment
Labels
0.kind: bug Something is broken 6.topic: developer experience 6.topic: module system About "NixOS" module system internals

Comments

@roberth
Copy link
Member

roberth commented Feb 23, 2022

Describe the bug

Unconfigured submodules don't work unless they specify a default, which should always be { } to avoid surprises.

Steps To Reproduce

nix-repl> (lib.evalModules { modules = [ ({ lib, ... }: { options.it = lib.mkOption { type = lib.types.submodule {}; }; }) ]; }).config
{ it = «error: error: The option `it' is used but not defined.»; }

Expected behavior

The module system is clever enough to figure out that modules have their own defaults and are always attrsets, making { } the obvious default.

Possible implementation

This works, but it's too broad.

diff --git a/lib/modules.nix b/lib/modules.nix
index e9fc1007fc2..80da5e51e36 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -649,6 +649,8 @@ rec {
         if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
         else let allInvalid = filter (def: ! type.check def.value) defsFinal;
         in throw "A definition for option `${showOption loc}' is not of type `${type.description}'. Definition values:${showDefs allInvalid}"
+      else if type.emptyValue?value then
+        type.emptyValue.value
       else
         # (nixos-option detects this specific error message and gives it special
         # handling.  If changed here, please change it there too.)

Perhaps defaultValue should be added to types, or emptyValue could be renamed.

Additional context

NixOS/nixops#1508 (comment)

Notify maintainers

@infinisil

@roberth roberth added 0.kind: bug Something is broken 6.topic: developer experience 6.topic: module system About "NixOS" module system internals labels Feb 23, 2022
@roberth roberth changed the title Submodules need a default valuee Submodules need a default value Feb 23, 2022
@infinisil
Copy link
Member

infinisil commented Feb 25, 2022

I also originally did this in #132448, but then decided against that, because it could break things that rely on submodule values not being defined. I'm thinking of use cases where the "option is not defined" error tells the user that they need to define it.

But I thought about it again, and I now think that options being allowed to not have a value defined is almost certainly an anti-pattern, it feels like one of the few thorns sticking out of the module system. You can always make it have a default value (e.g. null) and then handle the logic for such a value at the call site. While it's possible to handle this similarly with options.*.isDefined, once an option is defined you can't undefine it.

  • Though for values nested within an option, I think we still want a way to unset it, see e.g. lib/modules: add mkUnset, mkOverrideUnset #63553. The main difference between options being unset and values within them is that the attributes of options can't disappear (you can always rely on options.environment.systemPackages existing), while the same doesn't hold for values within an option (e.g. hardware.bluetooth.settings.General.ControllerMode could be not defined). While I think it's a bad idea for programs to depend on options being defined or not, we need something like mkUnset for the few that do.

So this means that I feel like it might be a good idea to introduce default values for not just submodules, but also other types where it makes sense (maybe by reusing emptyValue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
0.kind: bug Something is broken 6.topic: developer experience 6.topic: module system About "NixOS" module system internals
Projects
None yet
Development

No branches or pull requests

2 participants