From 64a1c1da3ef8cec88bcecefc3dfcf1ea9fbc8bc9 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 17 Feb 2025 15:59:53 +0100 Subject: [PATCH 1/2] lib.types: Make functor.wrapped deprecation work in unprocessed types Otherwise nested types such as `attrsOf (attrsOf int)` won't have a backwards compatible `type.nestedTypes.elemType.functor.wrapped`. Follow-up work to https://github.com/NixOS/nixpkgs/pull/366015 --- lib/types.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/types.nix b/lib/types.nix index 069d7b1703273..cda048fd10cac 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -86,7 +86,7 @@ let else { elemType = merged; }; wrappedDeprecationMessage = { loc }: lib.warn '' - The deprecated `type.functor.wrapped` attribute of the option `${showOption loc}` is accessed, use `type.nestedTypes.elemType` instead. + The deprecated `${lib.optionalString (loc != null) "type."}functor.wrapped` attribute ${lib.optionalString (loc != null) "of the option `${showOption loc}` "}is accessed, use `${lib.optionalString (loc != null) "type."}nestedTypes.elemType` instead. '' payload.elemType; }; @@ -227,7 +227,16 @@ rec { { _type = "option-type"; inherit name check merge emptyValue getSubOptions getSubModules substSubModules - typeMerge functor deprecationMessage nestedTypes descriptionClass; + typeMerge deprecationMessage nestedTypes descriptionClass; + functor = + if functor ? wrappedDeprecationMessage then + functor // { + wrapped = functor.wrappedDeprecationMessage { + loc = null; + }; + } + else + functor; description = if description == null then name else description; }; From fb79705bcaa2de42cf3f1cc29660333838d0f0d0 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Wed, 19 Feb 2025 16:49:58 +0700 Subject: [PATCH 2/2] lib.types: improve tests for deprecation warning on all migrated types --- lib/tests/modules.sh | 20 +++++++++-- lib/tests/modules/deprecated-wrapped.nix | 44 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 lib/tests/modules/deprecated-wrapped.nix diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index d6614822ea003..1505782547f53 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -398,9 +398,23 @@ checkConfigError 'infinite recursion encountered' config.nonLazyResult ./lazy-at checkConfigOutput '^"mergedName..nested"$' config.result ./name-merge-attrsWith-1.nix checkConfigError 'The option .mergedName. in .*\.nix. is already declared in .*\.nix' config.mergedName ./name-merge-attrsWith-2.nix -# Test the attrsOf functor.wrapped warning -# shellcheck disable=2016 -NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `type.functor.wrapped` attribute of the option `mergedLazyLazy` is accessed, use `type.nestedTypes.elemType` instead.' options.mergedLazyLazy.type.functor.wrapped ./lazy-attrsWith.nix +# Test type.functor.wrapped deprecation warning +# should emit the warning on: +# - merged types +# - non-merged types +# - nestedTypes elemType +# attrsWith +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.attrsWith.type.functor.wrapped ./deprecated-wrapped.nix +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedAttrsWith.type.functor.wrapped ./deprecated-wrapped.nix + +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.attrsWith.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedAttrsWith.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix +# listOf +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.listOf.type.functor.wrapped ./deprecated-wrapped.nix +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedListOf.type.functor.wrapped ./deprecated-wrapped.nix + +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.listOf.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix +NIX_ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedListOf.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix # Even with multiple assignments, a type error should be thrown if any of them aren't valid checkConfigError 'A definition for option .* is not of type .*' \ diff --git a/lib/tests/modules/deprecated-wrapped.nix b/lib/tests/modules/deprecated-wrapped.nix new file mode 100644 index 0000000000000..8d363a2ad3443 --- /dev/null +++ b/lib/tests/modules/deprecated-wrapped.nix @@ -0,0 +1,44 @@ +{ lib, ... }: +let + inherit (lib) types mkOption; + + inherit (types) + # attrsOf uses attrsWith internally + attrsOf + listOf + ; +in +{ + imports = [ + # Module A + ( + { ... }: + { + options.attrsWith = mkOption { + type = attrsOf (listOf types.str); + }; + options.mergedAttrsWith = mkOption { + type = attrsOf (listOf types.str); + }; + options.listOf = mkOption { + type = listOf (listOf types.str); + }; + options.mergedListOf = mkOption { + type = listOf (listOf types.str); + }; + } + ) + # Module B + ( + { ... }: + { + options.mergedAttrsWith = mkOption { + type = attrsOf (listOf types.str); + }; + options.mergedListOf = mkOption { + type = listOf (listOf types.str); + }; + } + ) + ]; +}