lib/types: Add deprecation to attrsWith

Co-Authored-By: @infinisil
This commit is contained in:
Silvan Mosberger 2024-11-25 16:58:58 +01:00 committed by Johannes Kirschbauer
parent bd353d322c
commit e438d6b08d
No known key found for this signature in database
2 changed files with 50 additions and 17 deletions

View file

@ -751,9 +751,32 @@ let
t' = opt.options.type; t' = opt.options.type;
mergedType = t.typeMerge t'.functor; mergedType = t.typeMerge t'.functor;
typesMergeable = mergedType != null; typesMergeable = mergedType != null;
typeSet = if (bothHave "type") && typesMergeable
then { type = mergedType; } # TODO: Remove this when all downstream reliances of internals: 'functor.wrapped' are sufficiently migrated.
else {}; # A function that adds the deprecated wrapped message to a type.
addDeprecatedWrapped = t:
t // {
functor = t.functor // {
wrapped = t.functor.wrappedDeprecationMessage {
inherit loc;
};
};
};
mergedType' =
if mergedType ? functor.wrappedDeprecationMessage then
addDeprecatedWrapped mergedType
else
mergedType;
typeSet =
if (bothHave "type") && typesMergeable then
{ type = mergedType'; }
else if opt.options ? type && opt.options.type ? functor.wrappedDeprecationMessage then
{ type = addDeprecatedWrapped opt.options.type; }
else
{};
bothHave = k: opt.options ? ${k} && res ? ${k}; bothHave = k: opt.options ? ${k} && res ? ${k};
in in
if bothHave "default" || if bothHave "default" ||

View file

@ -83,11 +83,15 @@ rec {
# Default type merging function # Default type merging function
# takes two type functors and return the merged type # takes two type functors and return the merged type
defaultTypeMerge = f: f': defaultTypeMerge = f: f':
let mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor; let
mergedPayload = f.binOp f.payload f'.payload; 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; hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null;
hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null; hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null;
typeFromPayload = if mergedPayload == null then null else f.type mergedPayload;
typeFromWrapped = if mergedWrapped == null then null else f.type mergedWrapped;
in in
# Abort early: cannot merge different types # Abort early: cannot merge different types
if f.name != f'.name if f.name != f'.name
@ -95,23 +99,23 @@ rec {
else else
if hasPayload then if hasPayload then
if hasWrapped then # Just return the payload if returning wrapped is deprecated
if f ? wrappedDeprecationMessage then
typeFromPayload
else if hasWrapped then
# Has both wrapped and payload # Has both wrapped and payload
throw '' throw ''
Type ${f.name} defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported. 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. Use either `functor.payload` or `functor.wrapped` but not both.
If your code worked before remove `functor.payload` from the type definition. If your code worked before remove either `functor.wrapped` or `functor.payload` from the type definition.
'' ''
else else
# Has payload typeFromPayload
if mergedPayload == null then null else f.type mergedPayload
else else
if hasWrapped then if hasWrapped then
# Has wrapped typeFromWrapped
# TODO(@hsjobeki): This could also be a warning and removed in the future
if mergedWrapped == null then null else f.type mergedWrapped
else else
f.type; f.type;
@ -592,7 +596,8 @@ rec {
lazyAttrsOf = elemType: attrsWith { inherit elemType; lazy = true; }; lazyAttrsOf = elemType: attrsWith { inherit elemType; lazy = true; };
# base type for lazyAttrsOf and attrsOf # base type for lazyAttrsOf and attrsOf
attrsWith = { attrsWith =
{
elemType, elemType,
lazy ? false, lazy ? false,
}: }:
@ -630,8 +635,13 @@ rec {
getSubModules = elemType.getSubModules; getSubModules = elemType.getSubModules;
substSubModules = m: attrsWith { elemType = elemType.substSubModules m; inherit lazy; }; substSubModules = m: attrsWith { elemType = elemType.substSubModules m; inherit lazy; };
functor = defaultFunctor "attrsWith" // { functor = defaultFunctor "attrsWith" // {
# TODO: This breaks stuff wrappedDeprecationMessage = { loc }: lib.warn ''
# wrapped = elemType; Using 'functor.wrapped' on option types will be deprecated.
Use 'nestedTypes.elemType' instead.
option: '${showOption loc}'
'' elemType;
payload = { payload = {
# Important!: Add new function attributes here in case of future changes # Important!: Add new function attributes here in case of future changes
inherit elemType lazy; inherit elemType lazy;