lib/deprecation: add transitionType

Based on `types.coerceTo`, which is like `types.either` but coerces the
left-hand type into the right-hand type.

`transitionType` only shows the right-hand type in its description and
also prints a warning when the left-hand type is used.

Co-authored-by: Silvan Mosberger <contact@infinisil.com>
This commit is contained in:
Matt Sturgeon 2024-07-07 16:01:10 +01:00
parent 6674dea840
commit c12694f4ba
No known key found for this signature in database
GPG key ID: 4F91844CED1A8299

View file

@ -46,4 +46,38 @@ rec {
'';
};
# A clone of types.coercedTo, but it prints a warning when oldType is used.
transitionType =
oldType: coerceFn: newType:
assert lib.assertMsg (
oldType.getSubModules == null
) "transitionType: oldType must not have submodules (its a ${oldType.description})";
lib.mkOptionType rec {
name = "transitionType";
inherit (newType) description;
check = x: (oldType.check x && newType.check (coerceFn x)) || newType.check x;
merge =
opt: defs:
let
coerceVal =
val:
if oldType.check val then
lib.warn ''
Passing a ${oldType.description} for `${lib.showOption opt}' is deprecated, use ${newType.description} instead. Definitions: ${lib.options.showDefs defs}
'' (coerceFn val)
else
val;
in
newType.merge opt (map (def: def // { value = coerceVal def.value; }) defs);
inherit (newType) emptyValue;
inherit (newType) getSubOptions;
inherit (newType) getSubModules;
substSubModules = m: transitionType oldType coerceFn (newType.substSubModules m);
typeMerge = t1: t2: null;
functor = (lib.types.defaultFunctor name) // {
wrapped = newType;
};
nestedTypes.coercedType = oldType;
nestedTypes.finalType = newType;
};
}