Skip to content

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

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

[ty] Ban legacy TypeVar bounds or constraints from containing type variables#22949
AlexWaygood merged 2 commits intomainfrom
alex/generic-tvar-bounds

Conversation

@AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Jan 29, 2026

Summary

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

Test Plan

mdtests updated

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Jan 29, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 29, 2026

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
Copy link

astral-sh-bot bot commented Jan 29, 2026

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
Member

Note that #21984 is already open.

@AlexWaygood
Copy link
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
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
Copy link
Collaborator

mtshiba commented Jan 30, 2026

@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
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments