Handle overloaded method ambiguity caused by self-types - #22011
ilevkivskyi wants to merge 5 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
|
The fallout in What is more concerning, is all the test failure in 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: RotationSo @jorenham Could you please comment on which overload(s) you expect to match here and why? |
|
The first overload with You might also be interested in a recent similar discussion for Pyrefly: facebook/pyrefly#4910 (comment) |
|
@jorenham Specific fallback type may be more precise, this is true. Mypy already infers Anyway, my question is different: you mentioned that the bug I am fixing here (where bug == mypy randomly selecting first overload in case if |
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 But it looks like this solution results in many The number of new primer errors for scipy-stubs isn't all too bad, so I can live with it. But the diff for Anyway, don't consider scipy-stubs a blocker for this. I've seen those |
|
@jorenham Now back to the main topic
Note |
There is a bunch of special-casing for `Any` types in binder. The goal of this special-casing is to limit the spread of `Any` types from legacy code with missing/imprecise types. This special-casing is quite ad-hoc, and thus should be limited only to imprecise kinds of `Any`. Note this should help with #22011
This comment has been minimized.
This comment has been minimized.
|
OK, |
This comment has been minimized.
This comment has been minimized.
|
OK, primer now looks better. The |
It is a common pattern (especially in numeric libraries) to have a fallback overload that has a relatively precise return type (i.e. not just `Any` or `list[Any]`). We should try to find and use that overload if there is an ambiguity caused by an argument that contains `Any`. This will likely cause some new errors, but this should limit the fallout from #22011
This comment has been minimized.
This comment has been minimized.
|
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/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/hdr_ipt.py:145: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[float64]]", variable has type "float") [assignment]
- colour/models/hdr_ipt.py:147: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[float64]]", variable has type "float") [assignment]
- colour/models/hdr_ipt.py:149: error: Incompatible return value type (got "float", expected "ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]]") [return-value]
- colour/models/hdr_cie_lab.py:142: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[float64]]", variable has type "float") [assignment]
- colour/models/hdr_cie_lab.py:144: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[float64]]", variable has type "float") [assignment]
- colour/models/hdr_cie_lab.py:146: error: Incompatible return value type (got "float", expected "ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]]") [return-value]
- colour/colorimetry/illuminants.py:226: 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/colorimetry/illuminants.py:227: 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/notation/munsell/centore2014.py:434: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]]", variable has type "floating[_16Bit] | floating[_32Bit] | float64") [assignment]
+ colour/notation/munsell/centore2014.py:435: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[floating[_16Bit] | floating[_32Bit] | float64]]", variable has type "floating[_16Bit] | floating[_32Bit] | float64") [assignment]
- colour/notation/munsell/centore2014.py:714: error: Argument 1 to "hue_angle_to_hue" has incompatible type "ndarray[tuple[Any, ...], dtype[floating[Any]]]"; expected "float" [arg-type]
+ colour/notation/munsell/centore2014.py:714: error: Argument 1 to "hue_angle_to_hue" has incompatible type "ndarray[tuple[Any, ...], dtype[float64]]"; expected "float" [arg-type]
- colour/notation/munsell/centore2014.py:741: error: Argument 1 to "append" of "list" has incompatible type "ndarray[tuple[Any, ...], dtype[floating[Any]]]"; expected "float" [arg-type]
+ colour/notation/munsell/centore2014.py:741: error: Argument 1 to "append" of "list" has incompatible type "ndarray[tuple[Any, ...], dtype[float64]]"; expected "float" [arg-type]
- colour/notation/munsell/centore2014.py:742: error: Argument 1 to "append" of "list" has incompatible type "ndarray[tuple[Any, ...], dtype[floating[Any]]]"; expected "int" [arg-type]
+ colour/notation/munsell/centore2014.py:742: error: Argument 1 to "append" of "list" has incompatible type "ndarray[Any, dtype[Any]]"; expected "int" [arg-type]
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]
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:79: 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:21: error: Expression is of type "Any", not "float" [assert-type]
+ tests/series/test_agg.py:26: error: Expression is of type "Any", not "float" [assert-type]
+ tests/series/test_agg.py:31: error: Expression is of type "Any", not "float" [assert-type]
+ tests/series/test_agg.py:36: 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:1154: 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:2174: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int], dtype[Any]]" [assert-type]
+ tests/series/test_series.py:3604: error: Expression is of type "Any", not "Series[Any]" [assert-type]
+ tests/series/test_series.py:3614: error: Expression is of type "Any", not "Series[Any]" [assert-type]
+ tests/series/test_series.py:3623: error: Expression is of type "Any", not "Series[Any]" [assert-type]
scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/linear_model/tests/test_ransac.py:26: error: Argument 1 to "__iadd__" of "ndarray" has incompatible type "ndarray[tuple[Any, ...], dtype[float64]]"; expected "_SupportsArray[dtype[numpy.bool[builtins.bool] | integer[Any]]] | _NestedSequence[_SupportsArray[dtype[numpy.bool[builtins.bool] | integer[Any]]]] | int | _NestedSequence[int]" [arg-type]
- sklearn/linear_model/tests/test_ransac.py:28: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[number[Any, float]]]", variable has type "ndarray[tuple[int], dtype[signedinteger[_32Bit | _64Bit]]]") [assignment]
- sklearn/linear_model/tests/test_ransac.py:29: error: Incompatible types in assignment (expression has type "ndarray[tuple[Any, ...], dtype[number[Any, float]]]", variable has type "ndarray[tuple[Any, ...], dtype[floating[Any]]]") [assignment]
pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/util/hashing.py:411: error: Unused "type: ignore" comment [unused-ignore]
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]
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:151: error: Expression is of type "Any", not "float64 | 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:539: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:564: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:685: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:736: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int, int, *tuple[Any, ...]], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:746: error: Expression is of type "ndarray[Any, Any]", not "ndarray[tuple[int, int, *tuple[Any, ...]], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:843: error: Expression is of type "tuple[Any, ...]", not "tuple[float64, float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]" [assert-type]
+ tests/stats/test_multivariate.pyi:846: error: Expression is of type "tuple[Any, ...]", not "tuple[float64, float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]" [assert-type]
+ tests/stats/test_multivariate.pyi:850: error: Expression is of type "tuple[Any, ...]", not "tuple[float64, float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]" [assert-type]
+ tests/stats/test_multivariate.pyi:854: error: Expression is of type "tuple[Any, ...]", not "tuple[float64, float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]" [assert-type]
+ tests/stats/test_multivariate.pyi:893: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:907: error: Expression is of type "Any", not "float64 | ndarray[tuple[Any, ...], dtype[float64]]" [assert-type]
+ tests/stats/test_multivariate.pyi:923: error: Expression is of type "tuple[Any, ...]", not "tuple[float64, float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], float64] | tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]" [assert-type]
|
|
@jorenham After I merged #22060 situation with @Dr-Irv @cmp0xff There are still a lot of new the relevant lines are def test_mul_numpy_array(left_i: pd.Index) -> None:
"""Test pd.Index[Any] (int) * numpy arrays"""
b = np.array([True, False, True], np.bool_)
...
check(assert_type(left_i * b, pd.Index), pd.Index)I looked at the definition of Because of the |
Fixes #11347
Closes #17239
I think we should handle this consistently with overloaded functions, essentially
foo.meth(x)should behave the same asFoo.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
Overloadedand 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