Skip to content

Comments

[ty] disallow type variables within PEP-695 type variable bounds/constraints#22982

Merged
ibraheemdev merged 2 commits intoastral-sh:mainfrom
mtshiba:ban-pep695-generic-bounds-or-constraints
Feb 11, 2026
Merged

[ty] disallow type variables within PEP-695 type variable bounds/constraints#22982
ibraheemdev merged 2 commits intoastral-sh:mainfrom
mtshiba:ban-pep695-generic-bounds-or-constraints

Conversation

@mtshiba
Copy link
Collaborator

@mtshiba mtshiba commented Jan 30, 2026

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

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

astral-sh-bot bot commented Jan 30, 2026

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 82.56% to 82.61%. The percentage of expected errors that received a diagnostic increased from 73.94% to 74.21%.

Summary

Metric Old New Diff Outcome
True Positives 800 803 +3 ⏫ (✅)
False Positives 169 169 +0
False Negatives 282 279 -3 ⏬ (✅)
Total Diagnostics 969 972 +3
Precision 82.56% 82.61% +0.05% ⏫ (✅)
Recall 73.94% 74.21% +0.28% ⏫ (✅)

True positives added

Details
Location Name Message
generics_syntax_declarations.py:44:21 invalid-type-variable-bound TypeVar upper bound cannot be generic
generics_syntax_scoping.py:14:20 invalid-type-variable-bound TypeVar upper bound cannot be generic
generics_syntax_scoping.py:18:17 invalid-type-variable-bound TypeVar upper bound cannot be generic

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

mypy_primer results

Changes were detected when running on open source projects
porcupine (https://github.com/Akuli/porcupine)
+ porcupine/pluginmanager.py:133:49: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[Never]`, found `Unknown | str`
- Found 24 diagnostics
+ Found 25 diagnostics

pydantic (https://github.com/pydantic/pydantic)
- pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | ((dict[str, int | float | str | ... omitted 3 union elements], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
+ pydantic/_internal/_core_metadata.py:87:54: error[invalid-assignment] Invalid assignment to key "pydantic_js_extra" with declared type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | ((dict[str, Divergent], type[Any], /) -> None)` on TypedDict `CoreMetadata`: value of type `dict[object, object]`
- pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:949:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:989:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:1032:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:1072:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:1115:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:1154:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
+ pydantic/fields.py:1194:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
- pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1573:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

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 50 diagnostics
+ Found 49 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `Unknown | Coroutine[Any, Any, Unknown]`
+ src/prefect/input/run_input.py:672:20: error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler] | Coroutine[Any, Any, T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]]`

static-frame (https://github.com/static-frame/static-frame)
- static_frame/core/batch.py:765:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 4 union elements) -> Batch` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/batch.py:766:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Batch` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/batch.py:767:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_getitem(key: Hashable) -> Batch` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/bus.py:657:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> Self@drop` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/bus.py:658:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/bus.py:659:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3717:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 4 union elements) -> Self@drop) | @Todo` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/frame.py:3718:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@drop._drop_loc(key: Hashable) -> Self@drop) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3719:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@drop._drop_getitem(key: Hashable) -> Self@drop) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3733:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@masked_array._extract_iloc_masked_array(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 4 union elements) -> MaskedArray[Any, Any]) | @Todo` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/frame.py:3734:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@masked_array._extract_loc_masked_array(key: Hashable) -> MaskedArray[Any, Any]) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3735:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@masked_array._extract_getitem_masked_array(key: Hashable) -> MaskedArray[Any, Any]) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3742:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@assign._extract_iloc_assign(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 4 union elements) -> FrameAssignILoc) | @Todo` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/frame.py:3743:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@assign._extract_loc_assign(key: Hashable) -> FrameAssignILoc) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/frame.py:3744:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `(bound method Self@assign._extract_getitem_assign(key: Hashable) -> FrameAssignILoc) | @Todo` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/index.py:715:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> Self@drop` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/index.py:716:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
+ static_frame/core/node_selector.py:452:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `((int | integer[Any], /) -> Any) | ((ndarray[Any, Any] | list[int] | slice[Any, Any, Any] | None, /) -> Unknown)`, found `Unknown | TILocSelectorFunc@__init__`
+ static_frame/core/node_selector.py:456:39: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(Hashable, /) -> Unknown`, found `Unknown | TLocSelectorFunc@__init__`
+ static_frame/core/node_selector.py:482:16: error[call-non-callable] Object of type `TLocSelectorFunc@__init__` is not callable
+ static_frame/core/node_selector.py:487:33: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `((int | integer[Any], /) -> Any) | ((ndarray[Any, Any] | list[int] | slice[Any, Any, Any] | None, /) -> Unknown)`, found `Unknown | TILocSelectorFunc@__init__`
+ static_frame/core/node_selector.py:492:32: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(Hashable, /) -> Unknown`, found `Unknown | TLocSelectorFunc@__init__`
+ static_frame/core/node_selector.py:521:16: error[call-non-callable] Object of type `TLocSelectorFunc@__init__` is not callable
+ static_frame/core/node_selector.py:531:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `((int | integer[Any], /) -> Any) | ((ndarray[Any, Any] | list[int] | slice[Any, Any, Any] | None, /) -> Unknown)`, found `Unknown | TILocSelectorFunc@__init__`
+ static_frame/core/node_selector.py:536:39: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(Hashable, /) -> Unknown`, found `Unknown | TLocSelectorFunc@__init__`
- static_frame/core/series.py:780:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> Self@drop` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/series.py:781:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:782:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:791:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@mask._extract_iloc_mask(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> Self@mask` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/series.py:792:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@mask._extract_loc_mask(key: Hashable) -> Self@mask` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:793:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@mask._extract_loc_mask(key: Hashable) -> Self@mask` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:802:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@masked_array._extract_iloc_masked_array(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> MaskedArray[Any, Any]` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/series.py:803:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@masked_array._extract_loc_masked_array(key: Hashable) -> MaskedArray[Any, Any]` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:804:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@masked_array._extract_loc_masked_array(key: Hashable) -> MaskedArray[Any, Any]` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:814:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@assign._extract_iloc_assign(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> SeriesAssign` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/series.py:815:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@assign._extract_loc_assign(key: Hashable) -> SeriesAssign` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/series.py:816:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@assign._extract_loc_assign(key: Hashable) -> SeriesAssign` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/yarn.py:426:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_iloc(key: int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements) -> Self@drop` does not satisfy upper bound `(int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements, /) -> TypeVar` of type variable `TILocSelectorFunc`
- static_frame/core/yarn.py:427:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- static_frame/core/yarn.py:428:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `bound method Self@drop._drop_loc(key: Hashable) -> Self@drop` does not satisfy upper bound `(Hashable, /) -> TypeVar` of type variable `TLocSelectorFunc`
- Found 1886 diagnostics
+ Found 1862 diagnostics

sympy (https://github.com/sympy/sympy)
+ sympy/algebras/tests/test_quaternion.py:422:33: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/codegen/tests/test_matrix_nodes.py:27:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/eigen.py:1202:37: error[unresolved-attribute] Object of type `T2'return@call_highest_priority | T1'return@call_highest_priority` has no attribute `pow`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:235:13: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:235:33: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:235:53: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_blockmatrix.py:459:12: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/expressions/tests/test_derivatives.py:551:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_matadd.py:36:12: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr`
+ sympy/matrices/expressions/tests/test_matpow.py:124:47: error[unsupported-operator] Operator `+` is not supported between two objects of type `ImmutableDenseMatrix`
+ sympy/matrices/inverse.py:385:11: error[unsupported-operator] Operator `-` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr | Unknown`
+ sympy/matrices/inverse.py:393:11: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase` and `MatrixBase | Expr | Unknown`
+ sympy/matrices/matrixbase.py:979:18: error[unsupported-operator] Operator `+` is not supported between two objects of type `Self@_eval_wilkinson`
+ sympy/matrices/matrixbase.py:2957:16: error[invalid-return-type] Return type does not match returned value: expected `Self@_eval_pow_by_cayley`, found `Self@_eval_pow_by_cayley | T2'return@call_highest_priority | T1'return@call_highest_priority`
+ sympy/matrices/matrixbase.py:3256:16: error[invalid-return-type] Return type does not match returned value: expected `MatrixBase`, found `T2'return@call_highest_priority | T1'return@call_highest_priority`
+ sympy/matrices/matrixbase.py:3256:29: error[invalid-argument-type] Argument is incorrect: Expected `T2'return@call_highest_priority | T1'return@call_highest_priority`, found `MatrixBase`
+ sympy/matrices/matrixbase.py:3310:16: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase`
+ sympy/matrices/matrixbase.py:3314:16: error[invalid-return-type] Return type does not match returned value: expected `Tmat@__sub__`, found `MatrixBase`
+ sympy/matrices/matrixbase.py:4386:16: error[unsupported-operator] Operator `+` is not supported between two objects of type `Self@add`
+ sympy/matrices/matrixbase.py:4923:16: error[invalid-return-type] Return type does not match returned value: expected `Self@analytic_func`, found `Self@analytic_func | T2'return@call_highest_priority | T1'return@call_highest_priority`
+ sympy/matrices/repmatrix.py:321:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `Self@_eval_is_symmetric`
+ sympy/matrices/tests/test_commonmatrix.py:1249:31: error[unsupported-operator] Operator `+` is not supported between objects of type `MutableDenseMatrix` and `ImmutableDenseNDimArray`
+ sympy/matrices/tests/test_eigen.py:406:20: error[invalid-argument-type] Argument to function `max` is incorrect: Expected `Iterable[Unknown]`, found `MatrixBase | Unknown`
+ sympy/matrices/tests/test_immutable.py:105:23: error[unsupported-operator] Operator `+` is not supported between two objects of type `ImmutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:121:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:123:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:141:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2179:22: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2207:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2908:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2921:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2936:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2937:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:2948:14: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:3471:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrices.py:3478:12: warning[possibly-missing-attribute] Attribute `rank` may be missing on object of type `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_matrices.py:3479:12: warning[possibly-missing-attribute] Attribute `rank` may be missing on object of type `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_matrixbase.py:491:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:493:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:544:12: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:823:31: error[unsupported-operator] Operator `+` is not supported between objects of type `MutableDenseMatrix` and `ImmutableDenseNDimArray`
+ sympy/matrices/tests/test_matrixbase.py:876:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:878:32: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:900:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:2931:22: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:2959:26: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3610:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3624:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3639:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3640:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_matrixbase.py:3652:14: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_reductions.py:377:21: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_reductions.py:384:12: warning[possibly-missing-attribute] Attribute `rank` may be missing on object of type `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_reductions.py:385:12: warning[possibly-missing-attribute] Attribute `rank` may be missing on object of type `MatrixBase | MatrixExpr | Unknown`
+ sympy/matrices/tests/test_solvers.py:68:13: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/matrices/tests/test_sparse.py:573:12: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/matrices/tests/test_sparse.py:577:52: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/matrices/tests/test_sparse.py:593:17: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableSparseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:13:6: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:38: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:84: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:16:131: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:44: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:90: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:21:137: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:37: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:83: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/parsing/autolev/test-examples/ruletest5.py:25:130: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
- sympy/parsing/mathematica.py:692:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[Never]`, found `Unknown | list[Unknown | str]`
+ sympy/physics/control/tests/test_lti.py:3733:31: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/control/tests/test_lti.py:3733:38: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/mechanics/lagrange.py:222:23: error[unsupported-operator] Operator `-` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/lagrange.py:346:17: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:217:28: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:229:29: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/linearize.py:241:29: error[unsupported-operator] Operator `+` is not supported between two objects of type `Unknown | MutableDenseMatrix`
+ sympy/physics/mechanics/tests/test_jointsmethod.py:247:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/mechanics/tests/test_jointsmethod.py:249:17: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/physics/quantum/tests/test_represent.py:89:17: error[unsupported-operator] Operator `+` is not supported between objects of type `MatrixBase | Expr` and `MatrixBase`
+ sympy/physics/quantum/tests/test_represent.py:91:24: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/physics/quantum/tests/test_represent.py:93:28: error[unsupported-operator] Operator `+` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/physics/vector/functions.py:380:21: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `Iterable[Unknown]`, found `MatrixBase | Unknown`
+ sympy/solvers/tests/test_numeric.py:137:11: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/solvers/tests/test_solvers.py:722:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:723:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:724:19: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/solvers/tests/test_solvers.py:724:30: error[unsupported-operator] Operator `-` is not supported between two objects of type `MatrixBase | Expr`
+ sympy/stats/tests/test_symbolic_multivariate.py:84:36: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/stats/tests/test_symbolic_multivariate.py:84:84: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/stats/tests/test_symbolic_multivariate.py:85:36: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/tensor/tests/test_tensor.py:1693:19: error[unsupported-operator] Operator `+` is not supported between two objects of type `MutableDenseMatrix`
+ sympy/tensor/tests/test_tensor.py:1694:23: error[unsupported-operator] Operator `-` is not supported between two objects of type `MutableDenseMatrix`
- Found 15830 diagnostics
+ Found 15920 diagnostics

@mtshiba mtshiba force-pushed the ban-pep695-generic-bounds-or-constraints branch from 76b2b5a to 8ba8c77 Compare January 30, 2026 16:36
@mtshiba mtshiba marked this pull request as ready for review January 30, 2026 16:59
any_over_type(db, self, &|ty| matches!(ty, Type::TypeVar(_)), false)
}

fn has_typevar_or_typevar_instance(self, db: &'db dyn Db) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could also use this new helper here:

let is_typevar = &|ty| {
matches!(
ty,
Type::KnownInstance(KnownInstanceType::TypeVar(_)) | Type::TypeVar(_)
)
};
if any_over_type(self.db(), inferred, &is_typevar, false) {
if let Some(builder) = self
.context
.report_lint(&INVALID_NEWTYPE, &arguments.args[1])
{
let mut diag = builder.into_diagnostic("invalid base for `typing.NewType`");
diag.set_primary_message("A `NewType` base cannot be generic");
}
return;
}

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Alex's comment applied, this looks good to me!

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As well as #22982 (comment), I think you can do this check with much less code by integrating it into infer_typevar_deferred() rather than adding the new check_pep695_typevars() method. All your added tests pass with this diff applied:

diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs
index c4da5b72cb..ec0534d7e6 100644
--- a/crates/ty_python_semantic/src/types/infer/builder.rs
+++ b/crates/ty_python_semantic/src/types/infer/builder.rs
@@ -657,7 +657,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
             self.check_static_class_definitions();
             self.check_overloaded_functions(node);
             self.check_type_guard_definitions();
-            self.check_pep695_typevars();
             self.check_legacy_positional_only_convention();
             self.check_final_without_value();
         }
@@ -2173,60 +2172,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
         }
     }
 
-    fn check_pep695_typevars(&mut self) {
-        let typevars = self.declarations.iter().filter_map(|(definition, ty)| {
-            if let DefinitionKind::TypeVar(typevar) = definition.kind(self.db()) {
-                Some((typevar.node(self.module()), ty.inner_type()))
-            } else {
-                None
-            }
-        });
-
-        // The current Python type specification is that the bounds and constraints of type variables must be concrete types,
-        // and an error must occur if type variables are included.
-        for (node, ty) in typevars {
-            let Type::KnownInstance(KnownInstanceType::TypeVar(typevar)) = ty else {
-                continue;
-            };
-            let Some(bound) = node.bound.as_deref() else {
-                continue;
-            };
-            match typevar.bound_or_constraints_unchecked(self.db()) {
-                Some(TypeVarBoundOrConstraints::UpperBound(bound_ty)) => {
-                    if bound_ty.has_typevar_or_typevar_instance(self.db())
-                        && let Some(builder) = self
-                            .context
-                            .report_lint(&INVALID_TYPE_VARIABLE_BOUND, bound)
-                    {
-                        builder.into_diagnostic("TypeVar upper bound cannot be generic");
-                    }
-                }
-                Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
-                    let ast::Expr::Tuple(tuple) = bound else {
-                        continue;
-                    };
-                    for constraint in constraints
-                        .elements(self.db())
-                        .iter()
-                        .enumerate()
-                        .filter_map(|(i, ty)| {
-                            ty.has_typevar_or_typevar_instance(self.db())
-                                .then_some(tuple.elts.get(i)?)
-                        })
-                    {
-                        if let Some(builder) = self
-                            .context
-                            .report_lint(&INVALID_TYPE_VARIABLE_CONSTRAINTS, constraint)
-                        {
-                            builder.into_diagnostic("TypeVar constraint cannot be generic");
-                        }
-                    }
-                }
-                None => {}
-            }
-        }
-    }
-
     fn infer_region_definition(&mut self, definition: Definition<'db>) {
         match definition.kind(self.db()) {
             DefinitionKind::Function(function) => {
@@ -4314,14 +4259,28 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
                 // Here, we interpret `bound` as a heterogeneous tuple and convert it to `TypeVarConstraints` in `TypeVarInstance::lazy_constraints`.
                 let tuple_ty = Type::heterogeneous_tuple(
                     self.db(),
-                    elts.iter()
-                        .map(|expr| self.infer_type_expression(expr))
-                        .collect::<Box<[_]>>(),
+                    elts.iter().map(|expr| {
+                        let constraint = self.infer_type_expression(expr);
+                        if constraint.has_typevar_or_typevar_instance(self.db())
+                            && let Some(builder) = self
+                                .context
+                                .report_lint(&INVALID_TYPE_VARIABLE_CONSTRAINTS, expr)
+                        {
+                            builder.into_diagnostic("TypeVar upper bound cannot be generic");
+                        }
+                        constraint
+                    }),
                 );
                 self.store_expression_type(expr, tuple_ty);
             }
             Some(expr) => {
-                self.infer_type_expression(expr);
+                let bound_ty = self.infer_type_expression(expr);
+                if bound_ty.has_typevar_or_typevar_instance(self.db())
+                    && let Some(builder) =
+                        self.context.report_lint(&INVALID_TYPE_VARIABLE_BOUND, expr)
+                {
+                    builder.into_diagnostic("TypeVar upper bound cannot be generic");
+                }
             }
             None => {}
         }

@ibraheemdev ibraheemdev force-pushed the ban-pep695-generic-bounds-or-constraints branch from ef7a6af to 8706ead Compare February 11, 2026 01:57
@astral-sh-bot
Copy link

astral-sh-bot bot commented Feb 11, 2026

Memory usage report

Memory usage unchanged ✅

@ibraheemdev
Copy link
Member

Thanks!

@ibraheemdev ibraheemdev enabled auto-merge (squash) February 11, 2026 02:09
@ibraheemdev ibraheemdev force-pushed the ban-pep695-generic-bounds-or-constraints branch from 8706ead to fd2ff51 Compare February 11, 2026 02:25
@ibraheemdev ibraheemdev dismissed AlexWaygood’s stale review February 11, 2026 02:37

Addressed comments.

@ibraheemdev ibraheemdev merged commit 7da7ae0 into astral-sh:main Feb 11, 2026
50 checks passed
@mtshiba mtshiba deleted the ban-pep695-generic-bounds-or-constraints branch February 11, 2026 04:24
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.

4 participants