Visitar URL original
[ty] Ban legacy `TypeVar` bounds or constraints from containing type variables by AlexWaygood · Pull Request #22949 · astral-sh/ruff · GitHub
Skip to content

[ty] Ban legacy TypeVar bounds or constraints from containing type variables - #22949

Merged
AlexWaygood merged 2 commits into
mainfrom
alex/generic-tvar-bounds
Jan 30, 2026
Merged

AlexWaygood merged 2 commits into
mainfrom
alex/generic-tvar-bounds

Conversation

@AlexWaygood

@AlexWaygood AlexWaygood commented Jan 29, 2026 •

Copy link
Copy Markdown
Member

Summary

The conformance suite mandates that type checkers should ban such constructs.

Test Plan

mdtests updated

@AlexWaygood AlexWaygood added the ty The ty type checker label Jan 29, 2026
@astral-sh-bot

astral-sh-bot Bot commented Jan 29, 2026 •

Copy link
Copy Markdown

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 80.00% to 80.04%. The percentage of expected errors that received a diagnostic increased from 71.42% to 71.60%.

Summary

Metric Old New Diff Outcome
True Positives 772 774 +2 ⏫ (✅)
False Positives 193 193 +0
False Negatives 309 307 -2 ⏬ (✅)
Total Diagnostics 965 967 +2 ⏫
Precision 80.00% 80.04% +0.04% ⏫ (✅)
Recall 71.42% 71.60% +0.19% ⏫ (✅)

True positives added

Details
Location Name Message
generics_basic.py:55:53 invalid-type-variable-constraints TypeVar constraint cannot be generic
generics_upper_bound.py:24:32 invalid-type-variable-bound TypeVar upper bound cannot be generic

@AlexWaygood
AlexWaygood force-pushed the alex/generic-tvar-bounds branch from bfae86a to 5219d09 Compare January 29, 2026 17:55
@astral-sh-bot

astral-sh-bot Bot commented Jan 29, 2026 •

Copy link
Copy Markdown

mypy_primer results

Changes were detected when running on open source projects
websockets (https://github.com/aaugustin/websockets)
+ src/websockets/sync/client.py:553:18: error[invalid-type-variable-bound] TypeVar upper bound cannot be generic
- Found 34 diagnostics
+ Found 35 diagnostics

pandera (https://github.com/pandera-dev/pandera)
- pandera/typing/common.py:72:69: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- Found 1639 diagnostics
+ Found 1638 diagnostics

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
+ src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 46 diagnostics
+ Found 47 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:94:28: error[invalid-assignment] Object of type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:99:28: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:86:21: error[invalid-assignment] Object of type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:87:21: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
- src/prefect/deployments/runner.py:997:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | (((...) -> Any) & ((*args: object, **kwargs: object) -> object))`
+ src/prefect/deployments/runner.py:997:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | ((...) -> Any)`
+ src/prefect/deployments/steps/core.py:137:38: error[invalid-argument-type] Argument is incorrect: Argument type `dict[str, Any] | int | dict[Any, Any] | ... omitted 4 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/flow_engine.py:989:32: error[invalid-await] `Unknown | R@FlowRunEngine | Coroutine[Any, Any, R@FlowRunEngine]` is not awaitable
+ src/prefect/flow_engine.py:1580:24: error[invalid-await] `Unknown | R@AsyncFlowRunEngine | Coroutine[Any, Any, R@AsyncFlowRunEngine]` is not awaitable
+ src/prefect/flow_engine.py:1661:43: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Unknown | R@run_generator_flow_sync`
+ src/prefect/flow_engine.py:1669:21: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_sync`
+ src/prefect/flow_engine.py:1703:44: warning[possibly-missing-attribute] Attribute `__anext__` may be missing on object of type `Unknown | R@run_generator_flow_async`
+ src/prefect/flow_engine.py:1710:25: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_async`
- src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
+ src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
- src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
+ src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
- src/prefect/flows.py:1877:53: warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ src/prefect/flows.py:1937:21: error[no-matching-overload] No overload of function `run_coro_as_sync` matches arguments
- src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `Unknown | dict[str, Any]` on object of type `dict[str, Any]`
+ src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `dict[str, Any] | int | Unknown | ... omitted 4 union elements` on object of type `dict[str, Any]`
- src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | dict[str, Any]]`
+ src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | dict[str, Any] | int | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown]`
+ src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown]`
+ src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `str | dict[str, Any]` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `dict[str, Any] | int | str | ... omitted 3 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:234:20: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `int | Unknown | float | ... omitted 4 union elements`
- Found 5362 diagnostics
+ Found 5374 diagnostics

ibis (https://github.com/ibis-project/ibis)
+ ibis/util.py:35:18: error[invalid-type-variable-bound] TypeVar upper bound cannot be generic
- Found 4761 diagnostics
+ Found 4762 diagnostics

static-frame (https://github.com/static-frame/static-frame)
- static_frame/core/bus.py:671:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[Bus[Any], object_]`, found `InterGetItemLocReduces[Bottom[Bus[Any]] | IndexHierarchy | TypeBlocks | ... omitted 6 union elements, object_]`
- static_frame/core/bus.py:675:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Bus[Any], object_]`, found `InterGetItemILocReduces[Bottom[Bus[Any]] | IndexHierarchy | TypeBlocks | ... omitted 7 union elements, Self@iloc]`
+ static_frame/core/bus.py:675:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Bus[Any], object_]`, found `InterGetItemILocReduces[Self@iloc, Self@iloc]`
+ static_frame/core/node_selector.py:92:5: error[invalid-type-variable-bound] TypeVar upper bound cannot be generic
+ static_frame/core/node_selector.py:96:5: error[invalid-type-variable-bound] TypeVar upper bound cannot be generic
- static_frame/core/series.py:772:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Series[Any, Any], TVDtype@Series]`, found `InterGetItemILocReduces[Bottom[Series[Any, Any]] | IndexHierarchy | TypeBlocks | ... omitted 7 union elements, TVDtype@Series]`
- static_frame/core/series.py:4072:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[SeriesHE[Any, Any], TVDtype@SeriesHE]`, found `InterGetItemILocReduces[Bottom[Series[Any, Any]] | Bottom[Index[Any]] | TypeBlocks | ... omitted 7 union elements, TVDtype@SeriesHE]`
- static_frame/core/yarn.py:418:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Yarn[Any], object_]`, found `InterGetItemILocReduces[Bottom[Yarn[Any]] | Bottom[Index[Any]] | Bottom[Series[Any, Any]] | ... omitted 7 union elements, object_]`
- Found 1829 diagnostics
+ Found 1827 diagnostics

No memory usage changes detected ✅

@ibraheemdev

Copy link
Copy Markdown
Member

Note that #21984 is already open.

@AlexWaygood

Copy link
Copy Markdown
Member Author

Note that #21984 is already open.

Ugh, I completely forgot. Thank you.

The typing conformance diff for that PR looks wholly different to the one here, though, so I think my version is more comprehensive when it comes to legacy type variables

@AlexWaygood AlexWaygood changed the title [ty] Ban TypeVar bounds or constraints from containing type variables [ty] Ban legacy TypeVar bounds or constraints from containing type variables Jan 29, 2026
Co-authored-by: Shunsuke Shibayama <sbym1346@gmail.com>
@AlexWaygood
AlexWaygood force-pushed the alex/generic-tvar-bounds branch from 9da532d to 1a7caef Compare January 29, 2026 18:26
@AlexWaygood

Copy link
Copy Markdown
Member Author

@mtshiba -- it looks like I accidentally recreated part of your PR. I've listed you as a co-author here; I hope that's okay. I think there were some parts I did slightly better and some parts you did slightly better, so I've tried to combine the work we both did here :-)

@AlexWaygood
AlexWaygood marked this pull request as ready for review January 29, 2026 18:27
@AlexWaygood
AlexWaygood merged commit 24522f9 into main Jan 30, 2026
49 checks passed
@AlexWaygood
AlexWaygood deleted the alex/generic-tvar-bounds branch January 30, 2026 00:01
carljm added a commit that referenced this pull request Jan 30, 2026
* main: (76 commits)
  [ty] Improve the check for `NewType`s with generic bases (#22961)
  [ty] Ban legacy `TypeVar` bounds or constraints from containing type variables (#22949)
  Bump the typing conformance suite pin (#22960)
  [ty] Emit an error if a TypeVarTuple is used to subscript `Generic` or `Protocol` without being unpacked (#22952)
  [ty] Reduce false positives when subscripting classes generic over `TypeVarTuple`s (#22950)
  [ty] Detect invalid attempts to subclass `Protocol[]` and `Generic[]` simultaneously (#22948)
  Fix suppression indentation matching (#22903)
  Remove hidden `--output-format` warning (#22944)
  [ty] Validate signatures of dataclass `__post_init__` methods (#22730)
  [ty] extend special-cased `numbers` diagnostic to `invalid-argument-type` errors (#22938)
  [ty] Avoid false positive for `not-iterable` with no-positive intersection types (#22089)
  [ty] Preserve pure negation types in descriptor protocol (#22907)
  [ty] add special-case diagnostic for `numbers` module (#22931)
  [ty] Move the location of more `invalid-overload` diagnostics (#22933)
  [ty] Fix unary and comparison operators for TypeVars with union bounds (#22925)
  [ty] Rule Selection: ignore/warn/select all rules (unless subsequently overriden) (#22832)
  [ty] Fix TypedDict construction from existing TypedDict values (#22904)
  [ty] fix bug in string annotations and clean up diagnostics (#22913)
  [ty] Improve support for goto-type, goto-declaration, hover, and highlighting of string annotations (#22878)
  [ty] Rename old typing imports to new on `unresolved-reference`. (#22827)
  ...
@mtshiba

mtshiba commented Jan 30, 2026

Copy link
Copy Markdown
Collaborator

@mtshiba -- it looks like I accidentally recreated part of your PR. I've listed you as a co-author here; I hope that's okay. I think there were some parts I did slightly better and some parts you did slightly better, so I've tried to combine the work we both did here :-)

Ah, I forgot about #21984.
This PR only implements the diagnotics about legacy typevars, right?
So, I will recreate a PR based on #21984 for PEP-695 typevars.

@AlexWaygood

Copy link
Copy Markdown
Member Author

That would be great, thanks!

ibraheemdev added a commit that referenced this pull request Feb 11, 2026
…traints (#22982)

## Summary

This is a revival of #21984.
Legacy typevar checks were already supported in
#22949.
This PR addresses PEP-695 typevars.

## Test Plan

mdtest updated

---------

Co-authored-by: Ibraheem Ahmed <ibraheem@ibraheem.ca>
KotlinIsland pushed a commit to KotlinIsland/basedpython that referenced this pull request May 1, 2026
…traints (#22982)

## Summary

This is a revival of astral-sh/ruff#21984.
Legacy typevar checks were already supported in
astral-sh/ruff#22949.
This PR addresses PEP-695 typevars.

## Test Plan

mdtest updated

---------

Co-authored-by: Ibraheem Ahmed <ibraheem@ibraheem.ca>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty The ty type checker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants