Skip to content

Handle overloaded method ambiguity caused by self-types - #22011

Open
ilevkivskyi wants to merge 2 commits into
python:masterfrom
ilevkivskyi:overload-self-amb
Open

ilevkivskyi wants to merge 2 commits into
python:masterfrom
ilevkivskyi:overload-self-amb

Conversation

@ilevkivskyi

Copy link
Copy Markdown
Member

Fixes #11347
Closes #17239

I think we should handle this consistently with overloaded functions, essentially foo.meth(x) should behave the same as Foo.meth(foo, x). Although this is a relatively niche situation, it seems to be important for some numerical libraries.

It looks like there are no simple way to implement this properly. The only way I see requires a new attribute on Overloaded and a lot of plumbing (form binging site to the call site). I tried to apply various optimizations to reduce possible performance impact.

cc @JukkaL @hauntsaninja

@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

colour (https://github.com/colour-science/colour)
- colour/models/rgb/transfer_functions/log.py:240: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]]", variable has type "ndarray[tuple[Any, ...], dtype[float64]]")  [assignment]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "floating" matches argument type "Buffer"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note: Possible overload variants:
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, int | floating[_16Bit] | unsignedinteger[_8Bit] | signedinteger[_8Bit] | numpy.bool[builtins.bool], /) -> floating[_16Bit]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, integer[Any] | floating[Any], /) -> floating[Any]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, float, /) -> floating[_16Bit]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, complex, /) -> complexfloating[Any, Any]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "floating" matches argument type "_SupportsArray[dtype[Any]]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "floating" matches argument type "_NestedSequence[_SupportsArray[dtype[Any]]]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "floating" matches argument type "str"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "floating" matches argument type "_NestedSequence[complex | bytes | str]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, int | floating[_16Bit] | unsignedinteger[_8Bit] | signedinteger[_8Bit] | numpy.bool[builtins.bool] | floating[_32Bit], /) -> floating[_32Bit]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, float, /) -> floating[_32Bit]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "float64" matches argument type "Buffer"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, float | floating[_64Bit] | floating[_32Bit] | floating[_16Bit] | integer[Any] | numpy.bool[builtins.bool], /) -> float64
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, complexfloating[_64Bit, _64Bit], /) -> complex128
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def [NBitT: NBitBase] __mul__(self, complexfloating[NBitT, NBitT], /) -> complexfloating[NBitT | _64Bit, NBitT | _64Bit]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note:     def __mul__(self, complex, /) -> float64 | complex128
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "float64" matches argument type "_SupportsArray[dtype[Any]]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "float64" matches argument type "_NestedSequence[_SupportsArray[dtype[Any]]]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "float64" matches argument type "str"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: error: No overload variant of "__mul__" of "float64" matches argument type "_NestedSequence[complex | bytes | str]"  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:375: note: Both left and right operands are unions
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: error: Unsupported operand types for / ("Buffer" and "float")  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: error: Unsupported operand types for / ("_SupportsArray[dtype[Any]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: error: Unsupported operand types for / ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: error: Unsupported operand types for / ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: error: Unsupported operand types for / ("_NestedSequence[complex | bytes | str]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/rimm_romm_rgb.py:379: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/io/image.py:350: error: Incompatible return value type (got "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]", expected "ndarray[tuple[Any, ...], dtype[signedinteger[_8Bit] | signedinteger[_16Bit] | signedinteger[_32Bit] | signedinteger[_64Bit] | unsignedinteger[_8Bit] | unsignedinteger[_16Bit] | unsignedinteger[_32Bit] | unsignedinteger[_64Bit] | floating[_16Bit] | floating[_32Bit] | float64]]")  [return-value]
+ colour/appearance/llab.py:411: error: Argument "a" to "CAM_Specification_LLAB" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/llab.py:412: error: Argument "b" to "CAM_Specification_LLAB" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:305: error: Argument "A_1" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:306: error: Argument "T_1" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:307: error: Argument "D_1" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:308: error: Argument "A_2" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:309: error: Argument "T_2" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/appearance/atd95.py:310: error: Argument "D_2" to "CAM_Specification_ATD95" has incompatible type "floating[_16Bit] | floating[_32Bit] | float64"; expected "float | ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]] | None"  [arg-type]
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for <= ("int" and "Buffer")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for <= ("int" and "_SupportsArray[dtype[Any]]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for <= ("int" and "_NestedSequence[_SupportsArray[dtype[Any]]]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for <= ("int" and "complex")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for <= ("int" and "_NestedSequence[complex | bytes | str]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:128: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:128: error: Unsupported operand types for >= ("str" and "int")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:129: error: Unsupported operand types for + ("Buffer" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:129: error: Unsupported operand types for + ("_SupportsArray[dtype[Any]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:129: error: Unsupported operand types for + ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:129: error: Unsupported operand types for + ("_NestedSequence[complex | bytes | str]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:129: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:129: error: Unsupported operand types for + ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: error: Unsupported operand types for * ("Buffer" and "int")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: error: Unsupported operand types for * ("_SupportsArray[dtype[Any]]" and "int")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: error: Unsupported operand types for * ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "int")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: error: Unsupported operand types for * ("_NestedSequence[complex | bytes | str]" and "int")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:130: error: Unsupported operand types for + ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:130: note: Left operand is of type "int | complex | str"
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for <= ("float" and "Buffer")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for <= ("float" and "_SupportsArray[dtype[Any]]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for <= ("float" and "_NestedSequence[_SupportsArray[dtype[Any]]]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for <= ("float" and "complex")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for <= ("float" and "_NestedSequence[complex | bytes | str]")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:407: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:407: error: Unsupported operand types for >= ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:408: error: Unsupported operand types for + ("Buffer" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:408: error: Unsupported operand types for + ("_SupportsArray[dtype[Any]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:408: error: Unsupported operand types for + ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:408: error: Unsupported operand types for + ("_NestedSequence[complex | bytes | str]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:408: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:408: error: Unsupported operand types for + ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:409: error: Unsupported operand types for * ("Buffer" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:409: error: Unsupported operand types for * ("_SupportsArray[dtype[Any]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:409: error: Unsupported operand types for * ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:409: error: Unsupported operand types for * ("_NestedSequence[complex | bytes | str]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/sony.py:409: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/sony.py:409: error: Unsupported operand types for * ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for > ("float" and "Buffer")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for > ("float" and "_SupportsArray[dtype[Any]]")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for > ("float" and "_NestedSequence[_SupportsArray[dtype[Any]]]")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for > ("float" and "complex")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for > ("float" and "_NestedSequence[complex | bytes | str]")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: note: Left operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str]"
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for < ("bytes" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for < ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("Buffer" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("_SupportsArray[dtype[Any]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("_NestedSequence[_SupportsArray[dtype[Any]]]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("_NestedSequence[complex | bytes | str]" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("bytes" and "float")  [operator]
+ colour/models/rgb/transfer_functions/red.py:540: error: Unsupported operand types for * ("str" and "float")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: error: Unsupported operand types for * ("float" and "Buffer")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: error: Unsupported operand types for * ("float" and "_SupportsArray[dtype[Any]]")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: error: Unsupported operand types for * ("float" and "_NestedSequence[_SupportsArray[dtype[Any]]]")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: error: Unsupported operand types for * ("float" and "str")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: error: Unsupported operand types for * ("float" and "_NestedSequence[complex | bytes | str]")  [operator]
+ colour/models/rgb/transfer_functions/panasonic_v_log.py:137: note: Right operand is of type "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str]"

... (truncated 141 lines) ...

zulip (https://github.com/zulip/zulip)
- zerver/lib/attachments.py:182: error: "Message" has no attribute "recipient_id"  [attr-defined]
- zerver/actions/user_groups.py:130: error: Argument 1 to "list" has incompatible type "QuerySet[UserProfile, dict[str, Any]]"; expected "Iterable[MemberGroupUserDict]"  [arg-type]
- zerver/actions/user_groups.py:135: error: Argument 1 to "list" has incompatible type "QuerySet[UserProfile, dict[str, Any]]"; expected "Iterable[MemberGroupUserDict]"  [arg-type]
- zerver/actions/user_groups.py:141: error: Argument 1 to "list" has incompatible type "QuerySet[UserProfile, dict[str, Any]]"; expected "Iterable[MemberGroupUserDict]"  [arg-type]
- zerver/actions/user_groups.py:144: error: Argument 1 to "list" has incompatible type "QuerySet[UserProfile, dict[str, Any]]"; expected "Iterable[MemberGroupUserDict]"  [arg-type]

scipy (https://github.com/scipy/scipy)
+ scipy/stats/_qmc.py:1067: error: Item "Buffer" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]
+ scipy/stats/_qmc.py:1067: error: Item "_SupportsArray[dtype[Any]]" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]
+ scipy/stats/_qmc.py:1067: error: Item "_NestedSequence[_SupportsArray[dtype[Any]]]" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]
+ scipy/stats/_qmc.py:1067: error: Item "complex" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]
+ scipy/stats/_qmc.py:1067: error: Item "str" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]
+ scipy/stats/_qmc.py:1067: error: Item "_NestedSequence[complex | bytes | str]" of "Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | str | _NestedSequence[complex | bytes | str] | Any" has no attribute "dtype"  [union-attr]

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/test_windowing.py:48: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/test_resampler.py:39: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/test_groupby.py:60: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/series/test_truediv.py:149: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_truediv.py:152: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_truediv.py:155: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:195: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:205: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:241: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:261: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_truediv.py:272: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_sub.py:263: error: Expression is of type "Any", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_mul.py:80: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_mul.py:81: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_mul.py:82: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_mul.py:83: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_floordiv.py:64: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_floordiv.py:124: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_floordiv.py:125: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_floordiv.py:126: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_floordiv.py:135: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:171: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:180: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_floordiv.py:203: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:211: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_floordiv.py:221: error: Expression is of type "Any", not "Never"  [assert-type]
+ tests/series/test_floordiv.py:230: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_floordiv.py:277: error: Expression is of type "Series[Any]", not "Series[Timedelta]"  [assert-type]
+ tests/series/test_agg.py:20: error: Expression is of type "Any", not "float"  [assert-type]
+ tests/series/test_agg.py:25: error: Expression is of type "Any", not "float"  [assert-type]
+ tests/series/test_agg.py:30: error: Expression is of type "Any", not "float"  [assert-type]
+ tests/series/test_agg.py:35: error: Expression is of type "Any", not "float"  [assert-type]
+ tests/series/test_add.py:87: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_add.py:88: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_add.py:89: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_add.py:90: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/indexes/test_truediv.py:61: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_sub.py:27: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_sub.py:32: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_sub.py:42: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_sub.py:47: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_mul.py:60: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_mul.py:62: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_mul.py:63: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_floordiv.py:84: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_floordiv.py:85: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_floordiv.py:86: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_add.py:60: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_add.py:61: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_add.py:62: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/indexes/test_add.py:63: error: Expression is of type "Any", not "Index[Any]"  [assert-type]
+ tests/test_timefuncs.py:1824: error: Expression is of type "Series[Any]", not "Series[Timestamp]"  [assert-type]
+ tests/test_pandas.py:1702: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/test_pandas.py:2017: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/frame/test_groupby.py:640: error: Returning Any from function declared to return "float"  [no-any-return]
+ tests/frame/test_frame.py:1148: error: Expression is of type "Any", not "ndarray[tuple[int], dtype[Any]]"  [assert-type]
+ tests/series/test_series.py:682: error: Expression is of type "Any", not "floating[Any]"  [assert-type]
+ tests/series/test_series.py:2168: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[Any]]"  [assert-type]
+ tests/series/test_series.py:3598: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_series.py:3608: error: Expression is of type "Any", not "Series[Any]"  [assert-type]
+ tests/series/test_series.py:3617: error: Expression is of type "Any", not "Series[Any]"  [assert-type]

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/util/hashing.py:408: error: Unused "type: ignore" comment  [unused-ignore]
+ pandas/io/formats/format.py:1606: error: Item "Sequence[float]" of "ndarray[tuple[Any, ...], dtype[Any]] | Sequence[float]" has no attribute "round"  [union-attr]
+ pandas/io/formats/format.py:1617: error: Item "float" of "ndarray[tuple[Any, ...], dtype[Any]] | Any | float" has no attribute "round"  [union-attr]
+ pandas/io/formats/format.py:1617: error: Invalid index type "ndarray[tuple[Any, ...], dtype[numpy.bool[builtins.bool]]] | Any" for "Sequence[float]"; expected type "int"  [index]
+ pandas/io/formats/format.py:1619: error: Item "float" of "ndarray[tuple[Any, ...], dtype[Any]] | Any | float" has no attribute "round"  [union-attr]
+ pandas/io/formats/format.py:1619: error: Invalid index type "ndarray[tuple[Any, ...], dtype[numpy.bool[builtins.bool]]] | Any" for "Sequence[float]"; expected type "int"  [index]

xarray (https://github.com/pydata/xarray)
+ xarray/tests/test_typed_ops.py:28: error: Unused "type: ignore" comment  [unused-ignore]
+ xarray/tests/test_typed_ops.py:79: error: Unused "type: ignore" comment  [unused-ignore]

freqtrade (https://github.com/freqtrade/freqtrade)
- freqtrade/optimize/optimize_reports/optimize_reports.py:357: error: "float" has no attribute "round"  [attr-defined]
- freqtrade/optimize/backtesting.py:1606: error: List comprehension has incompatible type List[list[Any]]; expected List[tuple[Any, ...]]  [misc]

rclip (https://github.com/yurijmikhalevich/rclip)
+ rclip/utils/preprocess.py:44: error: Incompatible return value type (got "ndarray[tuple[Any, ...], dtype[float64]]", expected "ndarray[tuple[Any, ...], dtype[floating[_32Bit]]]")  [return-value]

static-frame (https://github.com/static-frame/static-frame)
+ static_frame/core/rank.py:166: error: Unused "type: ignore" comment  [unused-ignore]

scipy-stubs (https://github.com/scipy/scipy-stubs)
+ tests/spatial/test__rotation.pyi:115: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:121: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:127: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:133: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:139: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:151: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rotation.pyi:157: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:56: error: Expression is of type "RigidTransform[Any]", not "RigidTransform[tuple[Any, ...]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:141: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:146: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:151: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:156: error: Expression is of type "tuple[Any, ...]", not "tuple[ndarray[tuple[Any, ...], dtype[float64]], Rotation[tuple[Any, ...]]]"  [assert-type]
+ tests/spatial/test__rigid_transform.pyi:167: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/interpolate/test_interpolate.pyi:43: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[float64]]"  [assert-type]
+ tests/interpolate/test_cubic.pyi:75: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:248: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:252: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:273: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:277: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:530: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:555: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]
+ tests/stats/test_multivariate.pyi:624: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int, int, *tuple[Any, ...]], dtype[float64]]"  [assert-type]
+ tests/sparse/test_csr.pyi:224: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[Any]]"  [assert-type]
+ tests/sparse/test_csr.pyi:238: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[Any]]"  [assert-type]

@ilevkivskyi

Copy link
Copy Markdown
Member Author

The fallout in colour is likely because this uncovers some other bug. Normally inferring more Anys should never cause problems. I will take a look at this later.

What is more concerning, is all the test failure in pandas-stubs and scipy-stubs. @jorenham You mentioned in #18343 (comment) that #11347 negatively affects some numerical libraries, but from what I see, it may be not what you actually want. Looking at some test failures and corresponding definitions this PR behaves as expected. For example:

tests/spatial/test__rotation.pyi:115: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[Any, ...], dtype[float64]]"  [assert-type]

Relevant line

assert_type(_rot_nd.as_quat(), onp.ArrayND[np.float64])

relevant definition

    @overload
    def as_quat(
        self: Rotation[_JustAnyShape], /, canonical: bool = False, *, scalar_first: bool = False
    ) -> onp.ArrayND[np.float64]: ...
    @overload
    def as_quat(
        self: Rotation[tuple[()]], /, canonical: bool = False, *, scalar_first: bool = False
    ) -> onp.Array1D[np.float64]: ...
    @overload
    def as_quat(
        self: Rotation[tuple[int]], /, canonical: bool = False, *, scalar_first: bool = False
    ) -> onp.Array2D[np.float64]: ...
    @overload
    def as_quat(self, /, canonical: bool = False, *, scalar_first: bool = False) -> onp.ArrayND[np.float64]: ...

and

_rot_nd: Rotation

So Rotation is the same as Rotation[tuple[Any, ...]] (due to type variable default). Then since Rotation[tuple[Any, ...]] is a subtype of several self-types here (Rotation is covariant and tuple[Any, ...] is a subtype of tuple[int] etc). Therefore multiple overloads match. Therefore now (with this PR) we identify this as "ambiguous overload match caused by Any", and correctly use erased return type.

@jorenham Could you please comment on which overload(s) you expect to match here and why?

@jorenham

jorenham commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

The first overload with Rotation[_JustAnyShape] is just a workaround for pyright, which eagerly selects the first overload in case of unknown shape-type. The last overload is the fallback overload, which intentionally has the same gradual-shape-typed result type as the first. This last overload returns onp.ArrayND[np.float64], which is assignable to all of the other overloads' return types. So according to the typing spec, using onp.ArrayND[np.float64] as return type for Rotation[tuple[Any, ...]] would be sound, and would match my intention.

You might also be interested in a recent similar discussion for Pyrefly: facebook/pyrefly#4910 (comment)

@ilevkivskyi

Copy link
Copy Markdown
Member Author

@jorenham Specific fallback type may be more precise, this is true. Mypy already infers ndarray[Any, Any] instead of plain Any, but better fallback logic may be (very) hard to specify in general.

Anyway, my question is different: you mentioned that the bug I am fixing here (where bug == mypy randomly selecting first overload in case if Any-ambiguity is caused by self-types) causes problems form numerical libraries. But from what I see, this PR only makes things worse (at least at first glance), so my question is do you actually want/need this?

@jorenham

Copy link
Copy Markdown
Contributor

But from what I see, this PR only makes things worse (at least at first glance), so my question is do you actually want/need this?

Well, in the meantime I've worked around most of these cases where possible in NumPy's bundled stubs and in scipy-stubs (e.g. using the tuple[Never, Never, ...] trick in numpy/numpy#29218).

But it looks like this solution results in many Anys to be inferred, more than necessary (typing-spec-wise, see my previous comment). Maybe that's worth it, but that's hard to tell because the primer diff doesn't show the cases where my workarounds can now be removed, and at this point I'm not sure if those new Any inferences can be worked around yet.

The number of new primer errors for scipy-stubs isn't all too bad, so I can live with it. But the diff for colour looks a bit more worrying, and I can't speak for its maintainers. I'm kinda suprised that numpy isn't in the primer diff though, but I guess that's good sign? The new unused-ignore and red diff lines show that this is at least doing something right, so at the very least you're on the right track with this.

Anyway, don't consider scipy-stubs a blocker for this. I've seen those ndarray[Any, Any] before in other contexts in numpy and scipy-stubs, so improving those (i.e. maning them more precise and less Any-ish) is probably another topic altogether I'm guessing.

@ilevkivskyi

ilevkivskyi commented Sep 20, 2026

Copy link
Copy Markdown
Member Author

@jorenham
About color: after a brief look at the relevant code there I think I know what is going to on. Mypy has a special case in narrowing logic: it never narrows an annotated variable to a plain Any. So now that we infer more plain Anys, some cases that previously worked, will stop working. For the record I didn't like this special case (I still think mypy should follow SSA as close as possible), but caved to the peer pressure. cc @cdce8p and @JukkaL who said that not having this special case will cause too many false negatives.

Now back to the main topic

Anyway, don't consider scipy-stubs a blocker for this.

Note pandas-stubs also has a lot of new errors. In general it seems to me we may first need to find a way to find better fallback type in case of ambiguity. For example, one may check if one of the return types is both subtype and supertype of all other return types, like onp.ArrayND[np.float64] in the example we discussed. Such logic is however quadratic in number of matches, so we may need to put some arbitrary limit (which is not something new for overloads btw, several things related to overloads are quadratic and need artificial cut-offs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Overload ambiguity is ignored in self-annotated methods

2 participants