Repository navigation
Conversation
…ded constructors Summary: Stack context: Make a restriction violation under a gradual expected type reject the overload that caused it. - Add two bug-marked tests for constructor calls that violate a restriction under a gradual expected type. With overloads, `Series(NA(), dtype="Int64")` under a bare `-> Series` reports `bad-specialization`, but the unhinted call picks the `NA` overload and reports nothing. Without overloads, the hinted call hides a bad argument that the unhinted call reports. - The first test is the pattern that `pd.Series(pd.NA, dtype="Int64")` hits with pandas-stubs since D115555748. The next diff fixes both tests. ___ landed-with-radar-review Differential Revision: D125293976
…ed type (facebook#5240) Summary: Stack context: Make a restriction violation under a gradual expected type reject the overload that caused it. - Problem: a constructor call with a gradual expected type, such as `return pd.Series(pd.NA, dtype="Int64")` under a bare `-> pd.Series`, reports `bad-specialization`. The same call without the annotation type checks clean. The trigger is an overloaded `__new__` or `__init__` where an earlier overload accepts the argument only through the class type parameter (`data: S1 | ...`), and a later overload accepts it directly (`data: NAType`). - Cause: since D115555748, the expected type solves `S1` to `Any`, and argument matching records a restriction violation on that answer. The constructor reports the violation only when it finishes, so overload selection does not see it. The earlier overload matches, and the call reports the violation instead of choosing the later overload. - Fix: each call that matches arguments against a restricted answer now takes the violations that it caused into its own specialization errors. Overload selection rejects the overload and continues, as it does without the expected type. - Side effect: for a constructor without overloads, the violation is now a hard error of the hinted attempt, so `construct_with_hint` discards the expected type. The call then reports the same errors as the unhinted call. This matches the intent of D115555748: an `Any` from the expected type says nothing, and argument matching checks the call normally. Reviewed By: rchen152 Differential Revision: D125293977
Summary: Stack context: Pick the first matching overload when an overloaded method satisfies a protocol whose return type wraps a call var in an invariant class. - Add a `bug`-marked test that shows the current behavior: `call(a, 1)` gives `int | float | complex` and `call_box(a, 1)` gives `Overloaded[Box[int], Box[float], Box[complex]]`. The first matching overload gives `int` and `Box[int]`. - This shape comes from pandas-stubs (`Index.__sub__` with `self: Supports_ProtoSub[T_contra, S2]`), where `assert_type(Index[bool] - int, Index[int])` fails with `assert-type-unspellable-subtype` since D124719502. Differential Revision: D125300481
Summary: Stack context: Pick the first matching overload when an overloaded method satisfies a protocol whose return type wraps a call var in an invariant class. When an overloaded method satisfies a protocol such as `SupportsF[T, R]`, and the protocol method returns `R` inside an invariant class (`def f(self, other: T) -> Box[R]`), Pyrefly keeps every overload that accepts the argument instead of the first one. For pandas-stubs, `Index[bool] - int` gives `Overloaded[Index[int], Index[float], Index[complex]]` instead of `Index[int]`, and `assert_type(..., Index[int])` fails with `assert-type-unspellable-subtype`. mypy, pyright and Pyrefly 1.3.2 give `Index[int]`. The regression comes from D124719502, which defers the overload choice to the end of the call. - The first matching overload eliminates later overloads only when the types passed to its parameters are known. The check treated each captured var with an upper bound as a var in the parameters. The invariant `Box[R]` gives `R` an upper bound too, so the check never passed. - The capture step now records which captured vars appear in the parameters of the protocol method, and the elimination check reads only those vars. A var that only receives the return type cannot change which overload applies. Reviewed By: rchen152 Differential Revision: D125300482
Contributor
|
@kinto0 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D125300482. |
rchen152
approved these changes
Oct 14, 2026
rchen152
left a comment
Contributor
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
|
Diff from mypy_primer, showing the effect of this PR on open source code: ============================================================
SUMMARY
============================================================
Total: +15 new errors, -75 fixed errors
By preset: +15/-73 (default), +15/-73 (strict)
Projects with changes (6):
steam.py: +1 -1
spark: +0 -14
pandas-stubs: +0 -45
pandas: +1 -0
meson: +13 -13
xarray: +0 -2
============================================================
FULL DIFF DETAILS
------------------------------------------------------------
steam.py (https://github.com/Gobot1234/steam.py)
- ERROR steam/abc.py:552:30-561:10: `PartialApp | tuple[str, int]` is not assignable to upper bound `PartialApp` of type variable `AppT` [bad-specialization]
+ ERROR steam/abc.py:552:30-561:10: `PartialApp[None] | tuple[str, int]` is not assignable to upper bound `PartialApp` of type variable `AppT` [bad-specialization]
spark (https://github.com/apache/spark)
- ERROR python/pyspark/eval_handlers/_pandas.py:812:47-56: `Unknown | None` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:99:44-72: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:100:44-79: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:101:51-84: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:102:43-74: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:103:43-96: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pandas/test_pandas_series_astype.py:104:41-86: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:165:54-94: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:171:47-75: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:242:47-67: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:243:54-245:10: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:246:48-101: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:359:57-361:10: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR python/pyspark/tests/upstream/pyarrow/test_pyarrow_array_from_pandas_default.py:362:57-364:10: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
- ERROR tests/indexes/bool/test_sub.py:31:22-49: assert_type(Overloaded[Index[int], Index[float], Index[complex]], Index[int]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:32:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:37:22-49: assert_type(Overloaded[Index[int], Index[float], Index[complex]], Index[int]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:38:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:48:22-49: assert_type(Overloaded[Index[int], Index[float], Index[complex]], Index[int]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:49:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:54:22-49: assert_type(Overloaded[Index[int], Index[float], Index[complex]], Index[int]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_sub.py:55:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:31:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:32:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:38:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:39:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:50:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:51:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:57:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/indexes/bool/test_truediv.py:58:22-51: assert_type(Overloaded[Index[float], Index[complex]], Index[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:31:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:32:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:38:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:39:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:45:22-59: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:46:22-59: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:56:22-55: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:57:22-55: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:63:22-60: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:64:22-60: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:74:22-56: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:75:22-56: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:88:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:89:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:95:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:96:22-52: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:99:22-59: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:100:22-59: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:101:22-59: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:108:22-55: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:109:22-55: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:110:22-55: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:113:22-60: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:114:22-60: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:115:22-60: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:122:22-56: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:123:22-56: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/series/bool/test_truediv.py:124:22-56: assert_type(Overloaded[Series[float], Series[complex]], Series[float]) failed [assert-type-unspellable-subtype]
- ERROR tests/test_resampler.py:306:22-27: `DatetimeIndexResampler[Series]` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
pandas (https://github.com/pandas-dev/pandas)
+ ERROR pandas/core/arrays/interval.py:699:35-40: Argument `DatetimeArray | NaTType | Period | Timedelta | TimedeltaArray | Timestamp | ndarray` is not assignable to parameter `right` with type `NaTType | Period | Timedelta | Timestamp` in function `pandas._libs.interval.Interval.__init__` [bad-argument-type]
meson (https://github.com/mesonbuild/meson)
+ ERROR mesonbuild/mparser.py:859:36-88: `+` is not supported between `str` and `None` [unsupported-operation]
- ERROR mesonbuild/mparser.py:859:27-32: The type of attribute `value` is unknown; it is inferred as an implicit `Any` [unknown-attribute-access]
- ERROR mesonbuild/mparser.py:859:83-88: The type of attribute `value` is unknown; it is inferred as an implicit `Any` [unknown-attribute-access]
- ERROR unittests/versiontests.py:302:43-63: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:303:43-64: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:307:43-84: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:310:44-65: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:311:44-64: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:314:45-65: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:315:45-65: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:318:45-66: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:319:45-67: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:322:49-69: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
- ERROR unittests/versiontests.py:327:44-64: `int` is not assignable to upper bound `Comparable` of type variable `_V` [bad-specialization]
+ ERROR unittests/versiontests.py:302:48-49: Argument `Literal[3]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:303:48-50: Argument `Literal[12]` is not assignable to parameter `max` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:307:48-49: Argument `Literal[5]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:307:68-70: Argument `Literal[10]` is not assignable to parameter `max` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:310:49-51: Argument `Literal[11]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:311:49-50: Argument `Literal[4]` is not assignable to parameter `max` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:314:50-51: Argument `Literal[7]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:315:50-51: Argument `Literal[8]` is not assignable to parameter `max` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:318:50-51: Argument `Literal[5]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:319:50-52: Argument `Literal[10]` is not assignable to parameter `max` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:322:54-55: Argument `Literal[5]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
+ ERROR unittests/versiontests.py:327:49-50: Argument `Literal[5]` is not assignable to parameter `min` with type `@_ | None` in function `mesonbuild.utils.universal.Range.__init__` [bad-argument-type]
xarray (https://github.com/pydata/xarray)
- ERROR xarray/tests/test_pandas_to_xarray.py:56:20-70: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization]
- ERROR xarray/tests/test_pandas_to_xarray.py:73:25-58: `object` is not assignable to upper bound `BaseOffset | CategoricalDtype | ExtensionDtype | Interval | Period | bool | bytes | complex | date | datetime | dtype | float | int | list[str] | str | time | timedelta | type[bool | complex | object | str]` of type variable `S1` [bad-specialization] |
Contributor
|
This pull request has been merged in e6294fc. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Stack context: Pick the first matching overload when an overloaded method satisfies a protocol whose return type wraps a call var in an invariant class.
When an overloaded method satisfies a protocol such as
SupportsF[T, R], and the protocol method returnsRinside an invariant class (def f(self, other: T) -> Box[R]), Pyrefly keeps every overload that accepts the argument instead of the first one. For pandas-stubs,Index[bool] - intgivesOverloaded[Index[int], Index[float], Index[complex]]instead ofIndex[int], andassert_type(..., Index[int])fails withassert-type-unspellable-subtype. mypy, pyright and Pyrefly 1.3.2 giveIndex[int]. The regression comes from D124719502, which defers the overload choice to the end of the call.Box[R]givesRan upper bound too, so the check never passed.Reviewed By: rchen152
Differential Revision: D125300482