lib/types: remove functor.wrapped after deprecation phase (#510713)

This commit is contained in:
Johannes Kirschbauer
2026-06-10 19:40:39 +00:00
committed by GitHub
5 changed files with 19 additions and 163 deletions
+8 -30
View File
@@ -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
{ };
-53
View File
@@ -515,56 +515,6 @@ checkConfigError 'infinite recursion encountered' config.nonLazyResult ./lazy-at
checkConfigOutput '^"mergedName.<id>.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
@@ -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;
};
}
+3 -49
View File
@@ -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;
};
+8 -3
View File
@@ -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 {