The overloads on list.__add__ lead to divergent behavior between mypy and pyright when doing something as simple as a list concatenation
# Overloading looks unnecessary, but is needed to work around complex mypy problems@overloaddef__add__(self, value: list[_T], /) ->list[_T]: ...
@overloaddef__add__(self, value: list[_S], /) ->list[_S|_T]: ...
Code sample in pyright playground, https://mypy-play.net/?mypy=latest&python=3.12&gist=abf6a8834020af17a16bd8cfb44b2f10
fromtypingimportAny, overloadclassListA[T]: # emulates builtins list@overloaddef__add__(self, other: "ListA[T]", /) ->"ListA[T]": returnListA()
@overloaddef__add__[S](self, other: "ListA[S]", /) ->"ListA[T | S]": returnListA()
classListB[T]: # without overloadsdef__add__[S](self, other: "ListB[S]", /) ->"ListB[T | S]": returnListB()
# mypy | pyright reveal_type( list[str]() +list[str]() ) # list[str] | list[str] ✅️reveal_type( list[str]() +list[int]() ) # list[str | int] | list[str | int] ✅️reveal_type( list[str]() +list[Any]() ) # list[Any] | list[str] ❌️reveal_type( ListA[str]() +ListA[str]() ) # ListA[str] | ListA[str] ✅️reveal_type( ListA[str]() +ListA[int]() ) # ListA[str | int] | ListA[str | int] ✅️reveal_type( ListA[str]() +ListA[Any]() ) # ListA[Any] | ListA[str] ❌️reveal_type( ListB[str]() +ListB[str]() ) # ListB[str] | ListB[str] ✅️reveal_type( ListB[str]() +ListB[int]() ) # ListB[str | int] | ListB[str | int] ✅️reveal_type( ListB[str]() +ListB[Any]() ) # ListB[str | Any] | ListB[str | Any] ✅️
This ultimately causes some very annoying type errors when checking wrapper functions in pyright.
Details
Code sample in pyright playground
fromtypingimportMapping, Any# function with 2 optional argumentsdeffoo(arg: object, /, *, opt1: str= ..., opt2: int= ...) ->None: ...
# wrapper that forwards args via dictdeffoo_wrapper(arg: object, foo_kwargs: Mapping[str, Any]) ->None:
# apply new defaultsfoo_kwargs= {"opt1": "new_default"} |dict(foo_kwargs)
foo(arg, **foo_kwargs) # "str" cannot be assigned to parameter "opt2"PR #14282 and #14284 show mypy-primer results of simplifying the overloads away from list.__add__ and dict.__or__.
The overloads on
list.__add__lead to divergent behavior betweenmypyandpyrightwhen doing something as simple as a list concatenationCode sample in pyright playground, https://mypy-play.net/?mypy=latest&python=3.12&gist=abf6a8834020af17a16bd8cfb44b2f10
This ultimately causes some very annoying type errors when checking wrapper functions in
pyright.Details
Code sample in pyright playground
PR #14282 and #14284 show mypy-primer results of simplifying the overloads away from
list.__add__anddict.__or__.