From 0cb9aa055ccb82161567115eea65bc250a2a6bb0 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Thu, 16 Apr 2026 23:37:02 +0200 Subject: [PATCH] lib/types: remove functor.wrapped after deprecation phase of 2 full releases --- lib/modules.nix | 38 +++---------- lib/tests/modules.sh | 53 ------------------- lib/tests/modules/default-type-merge-both.nix | 28 ---------- lib/types.nix | 52 ++---------------- nixos/modules/services/misc/autorandr.nix | 11 ++-- 5 files changed, 19 insertions(+), 163 deletions(-) delete mode 100644 lib/tests/modules/default-type-merge-both.nix diff --git a/lib/modules.nix b/lib/modules.nix index 2820aa921bf2..c5c935144ea6 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1018,38 +1018,16 @@ let mergedType = t.typeMerge t'.functor; typesMergeable = mergedType != null; - # TODO: Remove this when all downstream reliances of internals: 'functor.wrapped' are sufficiently migrated. - # A function that adds the deprecated wrapped message to a type. - addDeprecatedWrapped = - t: - t - // { - functor = t.functor // { - wrapped = t.functor.wrappedDeprecationMessage { - inherit loc; - }; - }; - }; - typeSet = - if opt.options ? type then - if res ? type then - if typesMergeable then - { - type = - if mergedType ? functor.wrappedDeprecationMessage then - addDeprecatedWrapped mergedType - else - mergedType; - } - else - # Keep in sync with the same error below! - throw - "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}." - else if opt.options.type ? functor.wrappedDeprecationMessage then - { type = addDeprecatedWrapped opt.options.type; } + if opt.options ? type && res ? type then + if typesMergeable then + { + type = mergedType; + } else - { } + # Keep in sync with the same error below! + throw + "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}." else { }; diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 4eb86ddd4962..94aeea299e04 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -515,56 +515,6 @@ 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 type.functor.wrapped deprecation warning -# should emit the warning on: -# - merged types -# - non-merged types -# - nestedTypes elemType -# attrsWith -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.attrsWith.type.functor.wrapped ./deprecated-wrapped.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 - -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 -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 -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.listOf.type.functor.wrapped ./deprecated-wrapped.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 - -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 -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 -# unique / uniq -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.unique.type.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedUnique.type.functor.wrapped ./deprecated-wrapped.nix - -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.unique.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedUnique.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix -# nullOr -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.nullOr.type.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedNullOr.type.functor.wrapped ./deprecated-wrapped.nix - -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.nullOr.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedNullOr.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix -# functionTo -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.functionTo.type.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedFunctionTo.type.functor.wrapped ./deprecated-wrapped.nix - -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.functionTo.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedFunctionTo.type.nestedTypes.elemType.functor.wrapped ./deprecated-wrapped.nix - -# coercedTo -# Note: test 'nestedTypes.finalType' and 'nestedTypes.coercedType' -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.coercedTo.type.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.coercedTo.type.nestedTypes.finalType.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.coercedTo.type.nestedTypes.coercedType.functor.wrapped ./deprecated-wrapped.nix -# either -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.either.type.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedEither.type.functor.wrapped ./deprecated-wrapped.nix - -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.either.type.nestedTypes.left.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.either.type.nestedTypes.right.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedEither.type.nestedTypes.left.functor.wrapped ./deprecated-wrapped.nix -ABORT_ON_WARN=1 checkConfigError 'The deprecated `.*functor.wrapped` attribute .*is accessed, use `.*nestedTypes.elemType` instead.' options.mergedEither.type.nestedTypes.right.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 .*' \ config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix @@ -733,9 +683,6 @@ checkConfigError 'The option .theOption.nested. in .other.nix. is already declar # Test that types.optionType leaves types untouched as long as they don't need to be merged checkConfigOutput 'ok' config.freeformItems.foo.bar ./adhoc-freeformType-survives-type-merge.nix -# Test that specifying both functor.wrapped and functor.payload isn't allowed -checkConfigError 'Type foo defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported.' config.result ./default-type-merge-both.nix - # Test that not including functor.wrapped is allowed checkConfigOutput 'ok' config.result ./default-type-merge-payload.nix diff --git a/lib/tests/modules/default-type-merge-both.nix b/lib/tests/modules/default-type-merge-both.nix deleted file mode 100644 index 0b02b940f8b1..000000000000 --- a/lib/tests/modules/default-type-merge-both.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ lib, options, ... }: -let - foo = lib.mkOptionType { - name = "foo"; - functor = lib.types.defaultFunctor "foo" // { - wrapped = lib.types.int; - payload = 10; - }; - }; -in -{ - imports = [ - { - options.foo = lib.mkOption { - type = foo; - }; - } - { - options.foo = lib.mkOption { - type = foo; - }; - } - ]; - - options.result = lib.mkOption { - default = builtins.seq options.foo null; - }; -} diff --git a/lib/types.nix b/lib/types.nix index 3cb3c64baf05..f9ae3c82a172 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -99,7 +99,6 @@ let { elemType, ... }@payload: { inherit name payload; - wrappedDeprecationMessage = makeWrappedDeprecationMessage payload; type = types.${name}; binOp = a: b: @@ -108,14 +107,6 @@ let in if merged == null then null else { elemType = merged; }; }; - makeWrappedDeprecationMessage = - payload: - { loc }: - lib.warn '' - 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; checkDefsForError = check: loc: defs: @@ -168,21 +159,11 @@ rec { defaultTypeMerge = f: f': let - mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor; mergedPayload = f.binOp f.payload f'.payload; hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null; - hasWrapped = - let - hasWrappedNonNull = set: set ? "wrapped" && set.wrapped != null; - in - assert (hasWrappedNonNull f') == (hasWrappedNonNull f); - hasWrappedNonNull f; - - typeFromPayload = if mergedPayload == null then null else f.type mergedPayload; - typeFromWrapped = if mergedWrapped == null then null else f.type mergedWrapped; in # Abort early: cannot merge different types if f.name != f'.name then @@ -190,22 +171,7 @@ rec { else if hasPayload then - # Just return the payload if returning wrapped is deprecated - if f ? wrappedDeprecationMessage then - typeFromPayload - else if hasWrapped then - # Has both wrapped and payload - throw '' - Type ${f.name} defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported. - - Use either `functor.payload` or `functor.wrapped` but not both. - - If your code worked before remove either `functor.wrapped` or `functor.payload` from the type definition. - '' - else - typeFromPayload - else if hasWrapped then - typeFromWrapped + if mergedPayload == null then null else f.type mergedPayload else f.type; @@ -213,7 +179,6 @@ rec { defaultFunctor = name: { inherit name; type = lib.types.${name} or null; - wrapped = null; payload = null; binOp = a: b: null; }; @@ -309,17 +274,8 @@ rec { deprecationMessage nestedTypes descriptionClass + functor ; - functor = - if functor ? wrappedDeprecationMessage then - functor - // { - wrapped = functor.wrappedDeprecationMessage { - loc = null; - }; - } - else - functor; description = if description == null then name else description; }; @@ -1834,9 +1790,7 @@ rec { getSubModules = finalType.getSubModules; substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m); typeMerge = t: null; - functor = (defaultFunctor name) // { - wrappedDeprecationMessage = makeWrappedDeprecationMessage { elemType = finalType; }; - }; + functor = defaultFunctor name; nestedTypes.coercedType = coercedType; nestedTypes.finalType = finalType; }; diff --git a/nixos/modules/services/misc/autorandr.nix b/nixos/modules/services/misc/autorandr.nix index 35a610305b04..fb23e2442b12 100644 --- a/nixos/modules/services/misc/autorandr.nix +++ b/nixos/modules/services/misc/autorandr.nix @@ -32,9 +32,14 @@ let ); getSubModules = elemType.getSubModules; substSubModules = mod: matrixOf n m (elemType.substSubModules mod); - functor = (lib.defaultFunctor name) // { - wrapped = elemType; - }; + functor = ( + lib.types.elemTypeFunctor "attrsWith" { + inherit + elemType + name + ; + } + ); }; profileModule = lib.types.submodule {