-
Notifications
You must be signed in to change notification settings - Fork 239
fix Support constrained TypeVars #1422 #1963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes issue #1422 by correctly handling constrained TypeVars in return type checking and missing-return analysis. The key change is recognizing that a constrained TypeVar T = TypeVar("T", int, str) can be satisfied by any of its constraints (not all), and that isinstance chains covering all constraints constitute exhaustive checking.
- Updated subset checking to accept any matching constraint for constrained TypeVars
- Added exhaustive isinstance chain detection to suppress false missing-return errors when all constraints are covered
- Added regression test for constrained TypeVar with isinstance chain
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| pyrefly/lib/solver/subset.rs | Changed constrained TypeVar subtype checking from all to any to correctly handle constraint matching |
| pyrefly/lib/binding/function.rs | Added isinstance chain analysis for constrained TypeVars to detect exhaustive type checking patterns |
| pyrefly/lib/test/returns.rs | Added regression test for constrained TypeVar with exhaustive isinstance chain |
| pyrefly/lib/test/generic_restrictions.rs | Removed now-incorrect return type error expectation due to fixed constraint checking |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
2411c12 to
cf52028
Compare
This comment has been minimized.
This comment has been minimized.
|
Diff from mypy_primer, showing the effect of this PR on open source code: dulwich (https://github.com/dulwich/dulwich)
- ERROR dulwich/objects.py:243:16-22: Returned type `str` is not assignable to declared return type `PathT` [bad-return]
- ERROR dulwich/objects.py:254:16-24: Returned type `bytes` is not assignable to declared return type `PathT` [bad-return]
- ERROR dulwich/refs.py:1992:12-20: Returned type `dict[Ref, ObjectID | None]` is not assignable to declared return type `T` [bad-return]
hydpy (https://github.com/hydpy-dev/hydpy)
- ERROR hydpy/core/devicetools.py:2541:20-79: Returned type `tuple[(int & t) | (str & t) | None, (int & t) | (str & t) | None] | tuple[t | None, t | None] | t` is not assignable to declared return type `tuple[t | None, t | None]` [bad-return]
+ ERROR hydpy/core/devicetools.py:2541:20-79: Returned type `tuple[int | str | None, int | str | None] | tuple[t | None, t | None] | t` is not assignable to declared return type `tuple[t | None, t | None]` [bad-return]
- ERROR hydpy/core/devicetools.py:2724:20-79: Returned type `tuple[(int & t) | (str & t) | None, (int & t) | (str & t) | None] | tuple[t | None, t | None] | t` is not assignable to declared return type `tuple[t | None, t | None]` [bad-return]
+ ERROR hydpy/core/devicetools.py:2724:20-79: Returned type `tuple[int | str | None, int | str | None] | tuple[t | None, t | None] | t` is not assignable to declared return type `tuple[t | None, t | None]` [bad-return]
+ ERROR hydpy/core/importtools.py:796:32-65: No matching overload found for function `SubmodelAdder.update` called with arguments: (TM_contra, TI_contra, refresh=Literal[False]) [no-matching-overload]
+ ERROR hydpy/core/importtools.py:799:32-84: No matching overload found for function `SubmodelAdder.update` called with arguments: (TM_contra, TI_contra, position=int, refresh=Literal[False]) [no-matching-overload]
+ ERROR hydpy/core/importtools.py:949:29-31: No matching overload found for function `SubmodelAdder.get_wrapped` called with arguments: () [no-matching-overload]
+ ERROR hydpy/core/importtools.py:952:29-31: No matching overload found for function `SubmodelAdder.get_wrapped` called with arguments: () [no-matching-overload]
- ERROR hydpy/core/parametertools.py:1540:20-49: Returned type `float | ndarray[tuple[Any, ...], dtype[float64]]` is not assignable to declared return type `ArrayFloat` [bad-return]
- ERROR hydpy/core/parametertools.py:1542:20-49: Returned type `float | ndarray[tuple[Any, ...], dtype[float64]]` is not assignable to declared return type `ArrayFloat` [bad-return]
- ERROR hydpy/core/parametertools.py:1569:20-49: Returned type `float | ndarray[tuple[Any, ...], dtype[float64]]` is not assignable to declared return type `ArrayFloat` [bad-return]
- ERROR hydpy/core/parametertools.py:1571:20-49: Returned type `float | ndarray[tuple[Any, ...], dtype[float64]]` is not assignable to declared return type `ArrayFloat` [bad-return]
- ERROR hydpy/core/selectiontools.py:715:20-43: Returned type `Node` is not assignable to declared return type `TypeNodeElement` [bad-return]
- ERROR hydpy/core/selectiontools.py:717:20-46: Returned type `Element` is not assignable to declared return type `TypeNodeElement` [bad-return]
- ERROR hydpy/exe/xmltools.py:1868:45-53: Expected class object, got `type[ChangeItem & _TypeGetOrChangeItem]` [invalid-argument]
- ERROR hydpy/exe/xmltools.py:1868:45-53: Expected class object, got `type[GetItem & _TypeGetOrChangeItem]` [invalid-argument]
- ERROR hydpy/exe/xmltools.py:1869:34-38: Argument `ExchangeItem` is not assignable to parameter `object` with type `_TypeGetOrChangeItem` in function `list.append` [bad-argument-type]
- ERROR hydpy/exe/xmltools.py:1873:49-57: Expected class object, got `type[ChangeItem & _TypeGetOrChangeItem]` [invalid-argument]
- ERROR hydpy/exe/xmltools.py:1873:49-57: Expected class object, got `type[GetItem & _TypeGetOrChangeItem]` [invalid-argument]
- ERROR hydpy/exe/xmltools.py:1874:38-42: Argument `ExchangeItem` is not assignable to parameter `object` with type `_TypeGetOrChangeItem` in function `list.append` [bad-argument-type]
- ERROR hydpy/exe/xmltools.py:2373:20-2379:14: `SetItem` is not assignable to variable `item` with type `_TypeSetOrAddOrMultiplyItem` [bad-assignment]
discord.py (https://github.com/Rapptz/discord.py)
- ERROR discord/backoff.py:63:56-61: Default `Literal[False]` is not assignable to parameter `integral` with type `T` [bad-function-definition]
zulip (https://github.com/zulip/zulip)
- ERROR zerver/lib/queue.py:109:17-25: Argument `(ChannelT, Basic.Deliver, BasicProperties, bytes) -> None` is not assignable to parameter `on_message_callback` with type `(Channel, Basic.Deliver, BasicProperties, bytes) -> object` in function `pika.channel.Channel.basic_consume` [bad-argument-type]
koda-validate (https://github.com/keithasaurus/koda-validate)
- ERROR koda_validate/generic.py:321:16-27: Returned type `bytes | str` is not assignable to declared return type `StrOrBytes` [bad-return]
- ERROR koda_validate/generic.py:330:16-27: Returned type `bytes | str` is not assignable to declared return type `StrOrBytes` [bad-return]
- ERROR koda_validate/generic.py:336:16-27: Returned type `bytes | str` is not assignable to declared return type `StrOrBytes` [bad-return]
pyodide (https://github.com/pyodide/pyodide)
- ERROR src/tests/test_static_typing.py:56:20-25: Returned type `float | int | str` is not assignable to declared return type `T` [bad-return]
prefect (https://github.com/PrefectHQ/prefect)
- ERROR src/prefect/utilities/templating.py:199:36-68: `str` is not assignable to variable `template` with type `T` [bad-assignment]
- ERROR src/prefect/utilities/templating.py:201:32-72: `str` is not assignable to variable `template` with type `T` [bad-assignment]
- ERROR src/prefect/utilities/templating.py:323:16-328:10: Returned type `list[dict[str, Any] | Unknown]` is not assignable to declared return type `dict[str, Any] | T` [bad-return]
- ERROR src/prefect/utilities/templating.py:423:24-26: Returned type `Literal['']` is not assignable to declared return type `T` [bad-return]
- ERROR src/prefect/utilities/templating.py:432:36-68: `str` is not assignable to variable `template` with type `T` [bad-assignment]
- ERROR src/prefect/utilities/templating.py:434:36-85: `str` is not assignable to variable `template` with type `T` [bad-assignment]
- ERROR src/prefect/utilities/templating.py:437:16-440:10: Returned type `dict[Unknown, Unknown]` is not assignable to declared return type `T` [bad-return]
- ERROR src/prefect/utilities/templating.py:442:16-83: Returned type `list[Unknown]` is not assignable to declared return type `T` [bad-return]
pandas (https://github.com/pandas-dev/pandas)
- ERROR pandas/core/dtypes/cast.py:409:16-36: Returned type `Index | ndarray[tuple[Any, ...], dtype[signedinteger[_64Bit]]] | NumpyIndexT` is not assignable to declared return type `NumpyIndexT` [bad-return]
- ERROR pandas/core/dtypes/cast.py:411:16-37: Returned type `Index | ndarray[tuple[Any, ...], dtype[unsignedinteger[_64Bit]]] | NumpyIndexT` is not assignable to declared return type `NumpyIndexT` [bad-return]
- ERROR pandas/core/dtypes/cast.py:413:16-38: Returned type `Index | ndarray[tuple[Any, ...], dtype[float64]] | NumpyIndexT` is not assignable to declared return type `NumpyIndexT` [bad-return]
- ERROR pandas/core/resample.py:3143:12-21: Returned type `DatetimeIndex | PeriodIndex | TimedeltaIndex` is not assignable to declared return type `FreqIndexT` [bad-return]
- ERROR pandas/io/stata.py:2253:16-53: Returned type `bytes` is not assignable to declared return type `AnyStr` [bad-return]
- ERROR pandas/io/stata.py:2254:12-48: Returned type `bytes | str` is not assignable to declared return type `AnyStr` [bad-return]
static-frame (https://github.com/static-frame/static-frame)
- ERROR static_frame/core/node_values.py:147:24-155:18: Returned type `Frame[Any, Any, *tuple[Any, ...]]` is not assignable to declared return type `TVContainer_co` [bad-return]
- ERROR static_frame/core/node_values.py:176:20-181:14: Returned type `Series[Any, Any]` is not assignable to declared return type `TVContainer_co` [bad-return]
- ERROR static_frame/core/node_values.py:275:20-284:14: Returned type `Frame[Any, Any, *tuple[Any, ...]] | Index[Any] | IndexHierarchy[*tuple[Any, ...]] | Series[Any, Any]` is not assignable to declared return type `TVContainer_co` [bad-return]
scrapy (https://github.com/scrapy/scrapy)
- ERROR scrapy/utils/datatypes.py:76:16-27: Returned type `bytes | str` is not assignable to declared return type `AnyStr` [bad-return]
|
Summary
Fixes #1422
Adjusted constrained TypeVar handling so return checks accept any constraint and missing-return is suppressed when an isinstance chain covers all constraints, then added a regression test and updated expectations.
Updated constrained TypeVar subtyping to accept any matching constraint.
Added a conservative exhaustive-isinstance check for constrained TypeVar parameters to avoid false missing-return errors.
Test Plan
Added a new return regression test and removed the now-obsolete return-type error expectation.