From 8054785157119ea12e526481924d6676427904bb Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 17 Apr 2023 19:48:53 +0200 Subject: [PATCH] lib/modules: Move class out of specialArgs --- doc/doc-support/default.nix | 2 +- doc/module-system/module-system.chapter.md | 6 ++--- lib/modules.nix | 26 ++++++++++++++++------ lib/tests/modules/class-check.nix | 6 ++--- lib/types.nix | 10 +++++++-- nixos/lib/eval-config-minimal.nix | 5 ++--- nixos/lib/testing/default.nix | 2 +- nixos/modules/misc/documentation.nix | 2 +- pkgs/top-level/default.nix | 2 +- 9 files changed, 39 insertions(+), 22 deletions(-) diff --git a/doc/doc-support/default.nix b/doc/doc-support/default.nix index 67195a4a58b0..cfa7cbdc8283 100644 --- a/doc/doc-support/default.nix +++ b/doc/doc-support/default.nix @@ -47,7 +47,7 @@ let optionsDoc = pkgs.nixosOptionsDoc { inherit (pkgs.lib.evalModules { modules = [ ../../pkgs/top-level/config.nix ]; - specialArgs.class = "nixpkgsConfig"; + class = "nixpkgsConfig"; }) options; documentType = "none"; transformOptions = opt: diff --git a/doc/module-system/module-system.chapter.md b/doc/module-system/module-system.chapter.md index 9a24ab70c6c1..51e600d75640 100644 --- a/doc/module-system/module-system.chapter.md +++ b/doc/module-system/module-system.chapter.md @@ -28,11 +28,11 @@ An attribute set of module arguments that can be used in `imports`. This is in contrast to `config._module.args`, which is only available after all `imports` have been resolved. -#### `specialArgs.class` {#module-system-lib-evalModules-param-specialArgs-class} +#### `class` {#module-system-lib-evalModules-param-class} -If the `class` attribute is set in `specialArgs`, the module system will reject modules with a different `class`. +If the `class` attribute is set and non-`null`, the module system will reject `imports` with a different `class`. -The `class` value should be in lower [camel case](https://en.wikipedia.org/wiki/Camel_case). +The `class` value should be a string in lower [camel case](https://en.wikipedia.org/wiki/Camel_case). If applicable, the `class` should match the "prefix" of the attributes used in (experimental) [flakes](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#description). Some examples are: diff --git a/lib/modules.nix b/lib/modules.nix index e83d5b6d1cae..3550ebddaeac 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -78,13 +78,13 @@ let # when resolving module structure (like in imports). For everything else, # there's _module.args. If specialArgs.modulesPath is defined it will be # used as the base path for disabledModules. - # - # `specialArgs.class`: + specialArgs ? {} + , # `class`: # A nominal type for modules. When set and non-null, this adds a check to # make sure that only compatible modules are imported. - specialArgs ? {} - , # This would be remove in the future, Prefer _module.args option instead. - args ? {} + # This would be remove in the future, Prefer _module.args option instead. + class ? null + , args ? {} , # This would be remove in the future, Prefer _module.check option instead. check ? true }: @@ -220,6 +220,16 @@ let within a configuration, but can be used in module imports. ''; }; + + _module.class = mkOption { + readOnly = true; + internal = true; + description = lib.mdDoc '' + If the `class` attribute is set and non-`null`, the module system will reject `imports` with a different `class`. + + This option contains the expected `class` attribute of the current module evaluation. + ''; + }; }; config = { @@ -227,13 +237,14 @@ let inherit extendModules; moduleType = type; }; + _module.class = class; _module.specialArgs = specialArgs; }; }; merged = let collected = collectModules - (specialArgs.class or null) + class (specialArgs.modulesPath or "") (regularModules ++ [ internalModule ]) ({ inherit lib options config specialArgs; } // specialArgs); @@ -310,13 +321,14 @@ let prefix ? [], }: evalModules (evalModulesArgs // { + inherit class; modules = regularModules ++ modules; specialArgs = evalModulesArgs.specialArgs or {} // specialArgs; prefix = extendArgs.prefix or evalModulesArgs.prefix or []; }); type = lib.types.submoduleWith { - inherit modules specialArgs; + inherit modules specialArgs class; }; result = withWarnings { diff --git a/lib/tests/modules/class-check.nix b/lib/tests/modules/class-check.nix index f492c844abfb..02d1431cc88b 100644 --- a/lib/tests/modules/class-check.nix +++ b/lib/tests/modules/class-check.nix @@ -3,7 +3,7 @@ _module.freeformType = lib.types.anything; ok = lib.evalModules { - specialArgs.class = "nixos"; + class = "nixos"; modules = [ ./module-class-is-nixos.nix ]; @@ -11,7 +11,7 @@ fail = lib.evalModules { - specialArgs.class = "nixos"; + class = "nixos"; modules = [ ./module-class-is-nixos.nix ./module-class-is-darwin.nix @@ -20,7 +20,7 @@ fail-anon = lib.evalModules { - specialArgs.class = "nixos"; + class = "nixos"; modules = [ ./module-class-is-nixos.nix { _file = "foo.nix#darwinModules.default"; diff --git a/lib/types.nix b/lib/types.nix index 666e6502d161..e0da18a2febb 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -696,6 +696,7 @@ rec { , specialArgs ? {} , shorthandOnlyDefinesConfig ? false , description ? null + , class ? null }@attrs: let inherit (lib.modules) evalModules; @@ -707,7 +708,7 @@ rec { ) defs; base = evalModules { - inherit specialArgs; + inherit class specialArgs; modules = [{ # This is a work-around for the fact that some sub-modules, # such as the one included in an attribute set, expects an "args" @@ -762,9 +763,14 @@ rec { functor = defaultFunctor name // { type = types.submoduleWith; payload = { - inherit modules specialArgs shorthandOnlyDefinesConfig description; + inherit modules class specialArgs shorthandOnlyDefinesConfig description; }; binOp = lhs: rhs: { + class = + if lhs.class == null then rhs.class + else if rhs.class == null then lhs.class + else if lhs.class == rhs.class then lhs.class + else throw "A submoduleWith option is declared multiple times with conflicting class values \"${toString lhs.class}\" and \"${toString rhs.class}\"."; modules = lhs.modules ++ rhs.modules; specialArgs = let intersecting = builtins.intersectAttrs lhs.specialArgs rhs.specialArgs; diff --git a/nixos/lib/eval-config-minimal.nix b/nixos/lib/eval-config-minimal.nix index 7e28f4305127..036389121973 100644 --- a/nixos/lib/eval-config-minimal.nix +++ b/nixos/lib/eval-config-minimal.nix @@ -38,11 +38,10 @@ let # is experimental. lib.evalModules { inherit prefix modules; + class = "nixos"; specialArgs = { modulesPath = builtins.toString ../modules; - } // specialArgs // { - class = "nixos"; - }; + } // specialArgs; }; in diff --git a/nixos/lib/testing/default.nix b/nixos/lib/testing/default.nix index 1bd6278ce684..a89f734b1e64 100644 --- a/nixos/lib/testing/default.nix +++ b/nixos/lib/testing/default.nix @@ -3,7 +3,7 @@ let evalTest = module: lib.evalModules { modules = testModules ++ [ module ]; - specialArgs.class = "nixosTest"; + class = "nixosTest"; }; runTest = module: (evalTest ({ config, ... }: { imports = [ module ]; result = config.test; })).config.result; diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index 1821dd866cb1..31486a2216ad 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -38,8 +38,8 @@ let modules = [ { _module.check = false; } ] ++ docModules.eager; + class = "nixos"; specialArgs = specialArgs // { - class = "nixos"; pkgs = scrubDerivations "pkgs" pkgs; # allow access to arbitrary options for eager modules, eg for getting # option types from lazy modules diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index f54ce84aedad..ba00e78ce2e6 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -82,7 +82,7 @@ in let config = config1; }) ]; - specialArgs.class = "nixpkgsConfig"; + class = "nixpkgsConfig"; }; # take all the rest as-is