Skip to content

Conversation

@dcreager
Copy link
Member

@dcreager dcreager commented Mar 6, 2025

We are currently representing type variables using a KnownInstance variant, which wraps a TypeVarInstance that contains the information about the typevar (name, bounds, constraints, default type). We were previously only constructing that type for PEP 695 typevars. This PR constructs that type for legacy typevars as well.

It also detects functions that are generic because they use legacy typevars in their parameter list. With the existing logic for inferring specializations of function calls (#17301), that means that we are correctly detecting that the definition of reveal_type in the typeshed is generic, and inferring the correct specialization of _T for each call site.

This does not yet handle legacy generic classes; that will come in a follow-on PR.

@dcreager
Copy link
Member Author

dcreager commented Mar 6, 2025

Leaving this as draft for now; there's one mdtest regression (an incorrect unresolved-reference error) that I still have to track down.

@dcreager dcreager force-pushed the dcreager/legacy-typevar-instance branch 2 times, most recently from 7ce5df6 to 316ab63 Compare March 6, 2025 16:31
@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Mar 6, 2025
@dcreager dcreager changed the base branch from main to dcreager/two-phase-binding March 20, 2025 15:12
@github-actions
Copy link
Contributor

github-actions bot commented Mar 20, 2025

mypy_primer results

Changes were detected when running on open source projects
packaging (https://github.com/pypa/packaging)
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:195:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:198:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:201:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:231:22: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:234:26: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_manylinux.py:235:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_musllinux.py:30:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/packaging/_parser.py:83:12: No overload of bound method `__init__` matches arguments
- warning[lint:unused-ignore-comment] src/packaging/metadata.py:439:65: Unused blanket `type: ignore` directive
+ warning[lint:possibly-unbound-attribute] src/packaging/metadata.py:576:13: Attribute `params` on type `str | @Todo(Support for `typing.TypeAlias`)` is possibly unbound
+ warning[lint:possibly-unbound-attribute] src/packaging/metadata.py:576:13: Attribute `params` on type `str | @Todo(Support for `typing.TypeAlias`)` is possibly unbound
+ warning[lint:possibly-unbound-attribute] src/packaging/metadata.py:576:13: Attribute `params` on type `str | @Todo(Support for `typing.TypeAlias`)` is possibly unbound
+ error[lint:no-matching-overload] src/packaging/version.py:205:25: No overload of bound method `__init__` matches arguments
- Found 22 diagnostics
+ Found 33 diagnostics

nionutils (https://github.com/nion-software/nionutils)
+ error[lint:invalid-argument-type] nion/utils/test/ListModel_test.py:510:33: Argument to this function is incorrect: Argument type `FlattenedListModel` does not satisfy upper bound of type variable `_SupportsCloseT`
- Found 33 diagnostics
+ Found 34 diagnostics

bidict (https://github.com/jab/bidict)
+ error[lint:no-matching-overload] bidict/_dup.py:57:34: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] bidict/_dup.py:59:32: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] bidict/_dup.py:61:35: No overload of bound method `__init__` matches arguments
- Found 4 diagnostics
+ Found 7 diagnostics

paroxython (https://github.com/laowantong/paroxython)
+ error[lint:no-matching-overload] paroxython/derived_labels_db.py:189:38: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/label_programs.py:49:37: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/list_programs.py:89:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:76:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:284:22: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:289:77: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:316:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:333:31: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/parse_program.py:366:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] paroxython/preprocess_source.py:455:40: No overload of bound method `__init__` matches arguments
- Found 34 diagnostics
+ Found 44 diagnostics

parso (https://github.com/davidhalter/parso)
+ error[lint:invalid-argument-type] parso/__init__.py:57:28: Argument to this function is incorrect: Expected `str`, found `None`
+ error[lint:no-matching-overload] parso/python/diff.py:495:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/diff.py:508:31: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:228:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:289:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:381:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:385:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:429:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:445:31: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:508:31: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:518:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:528:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:538:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:546:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:554:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:564:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:594:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:597:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:621:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:624:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:631:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:644:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:645:11: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/python/tokenize.py:650:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/utils.py:132:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] parso/utils.py:180:12: No overload of bound method `__init__` matches arguments
- Found 80 diagnostics
+ Found 106 diagnostics

pegen (https://github.com/we-like-parsers/pegen)
- error[lint:unresolved-attribute] src/pegen/parser.py:85:19: Type `(@Todo(Support for `typing.TypeVar` instances in type expressions), /) -> @Todo(Support for `typing.TypeVar` instances in type expressions) | None` has no attribute `__name__`
+ error[lint:unresolved-attribute] src/pegen/parser.py:28:19: Type `F` has no attribute `__name__`
+ error[lint:call-non-callable] src/pegen/parser.py:32:20: Object of type `F` is not callable
+ error[lint:call-non-callable] src/pegen/parser.py:37:16: Object of type `F` is not callable
+ error[lint:unresolved-attribute] src/pegen/parser.py:48:19: Type `F` has no attribute `__name__`
+ error[lint:call-non-callable] src/pegen/parser.py:66:20: Object of type `F` is not callable
+ error[lint:unresolved-attribute] src/pegen/parser.py:85:19: Type `(P, /) -> T | None` has no attribute `__name__`
+ error[lint:invalid-argument-type] src/pegen/parser.py:332:45: Argument to this function is incorrect: Expected `() -> str`, found `(bound method TextIO.readline(limit: int = Literal[-1], /) -> AnyStr) | @Todo(Support for `typing.TypeAlias`)`
- Found 52 diagnostics
+ Found 58 diagnostics

attrs (https://github.com/python-attrs/attrs)
+ error[lint:no-matching-overload] src/attr/_make.py:480:12: No overload of bound method `__init__` matches arguments
- info[revealed-type] tests/dataclass_transform_example.py:21:1: Revealed type: `(with_converter: int = @Todo(Support for `typing.TypeVar` instances in type expressions)) -> None`
+ info[revealed-type] tests/dataclass_transform_example.py:21:1: Revealed type: `(with_converter: int = Unknown) -> None`
+ error[lint:invalid-argument-type] tests/test_annotations.py:123:28: Argument to this function is incorrect: Argument type `Literal[C]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:416:28: Argument to this function is incorrect: Argument type `Literal[C]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:518:28: Argument to this function is incorrect: Argument type `Literal[C]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:540:28: Argument to this function is incorrect: Argument type `Literal[C]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:548:28: Argument to this function is incorrect: Argument type `Literal[D]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:565:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:599:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:619:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:620:28: Argument to this function is incorrect: Argument type `Literal[B]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:667:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:668:28: Argument to this function is incorrect: Argument type `Literal[B]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:683:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_annotations.py:687:28: Argument to this function is incorrect: Argument type `Literal[A]` does not satisfy upper bound of type variable `_A`
+ error[lint:no-matching-overload] tests/test_funcs.py:251:22: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/test_funcs.py:253:27: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/test_funcs.py:455:22: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/test_funcs.py:457:17: No overload of bound method `__init__` matches arguments
+ error[lint:unresolved-attribute] tests/test_make.py:144:14: Type `Literal[42]` has no attribute `default`
+ error[lint:no-matching-overload] tests/test_make.py:204:16: No overload of bound method `__init__` matches arguments
+ error[lint:invalid-argument-type] tests/test_make.py:1242:32: Argument to this function is incorrect: Argument type `type` does not satisfy upper bound of type variable `_A`
+ error[lint:invalid-argument-type] tests/test_make.py:1253:32: Argument to this function is incorrect: Argument type `type` does not satisfy upper bound of type variable `_A`
- error[lint:invalid-argument-type] tests/test_validators.py:228:32: Argument to this function is incorrect: Expected `((@Todo(Support for `typing.TypeVar` instances in type expressions), @Todo(Support for `typing.TypeVar` instances in type expressions), int, /) -> @Todo(specialized non-generic class) | None) | None`, found `() -> Unknown`
+ error[lint:invalid-argument-type] tests/test_validators.py:228:32: Argument to this function is incorrect: Expected `((Literal["a"], Literal["a"], int, /) -> @Todo(specialized non-generic class) | None) | None`, found `() -> Unknown`
+ error[lint:invalid-argument-type] tests/typing_example.py:490:28: Argument to this function is incorrect: Argument type `type` does not satisfy upper bound of type variable `_A`
- Found 674 diagnostics
+ Found 697 diagnostics

more-itertools (https://github.com/more-itertools/more-itertools)
- error[lint:invalid-argument-type] more_itertools/more.py:2441:38: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Unknown | Literal[bool]`
+ error[lint:invalid-argument-type] more_itertools/more.py:2441:38: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Unknown | Literal[bool]`
- error[lint:invalid-argument-type] more_itertools/more.py:2997:44: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[repeat]`
+ error[lint:invalid-argument-type] more_itertools/more.py:2997:44: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[repeat]`
- error[lint:invalid-argument-type] more_itertools/recipes.py:98:27: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[zip]`
+ error[lint:invalid-argument-type] more_itertools/recipes.py:98:27: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[zip]`
- error[lint:invalid-argument-type] more_itertools/recipes.py:897:22: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[slice]`
+ error[lint:invalid-argument-type] more_itertools/recipes.py:897:22: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[slice]`

pytest-robotframework (https://github.com/detachhead/pytest-robotframework)
+ error[lint:no-matching-overload] pytest_robotframework/__init__.py:502:12: No overload of function `keyword` matches arguments
+ error[lint:no-matching-overload] pytest_robotframework/__init__.py:569:9: No overload of function `keyword` matches arguments
- error[lint:missing-argument] pytest_robotframework/__init__.py:502:12: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:503:9: Argument `name` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:503:20: Argument `tags` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:503:31: Argument `module` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:503:46: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] pytest_robotframework/__init__.py:569:9: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:569:17: Argument `name` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:569:28: Argument `tags` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:569:39: Argument `module` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] pytest_robotframework/__init__.py:569:54: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_doesnt_suppress.py:14:2: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_doesnt_suppress.py:14:10: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_raises_in_body_and_exit.py:14:2: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_raises_in_body_and_exit.py:14:10: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_raises_in_exit.py:14:2: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_context_manager_that_raises_in_exit.py:14:10: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/fixtures/test_python/test_keyword_decorator_custom_name_and_tags.py:6:2: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_custom_name_and_tags.py:6:10: Argument `name` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_custom_name_and_tags.py:6:26: Argument `tags` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/fixtures/test_python/test_keyword_decorator_returns_context_manager_that_isnt_used.py:14:2: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/fixtures/test_python/test_keyword_decorator_returns_context_manager_that_isnt_used.py:14:10: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/type_tests.py:18:6: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:18:14: Argument `name` does not match any known parameter of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:18:30: Argument `tags` does not match any known parameter of function `keyword`
- error[lint:type-assertion-failure] tests/type_tests.py:21:9: Actual type `Unknown` is not the same as asserted type `() -> None`
+ error[lint:type-assertion-failure] tests/type_tests.py:21:9: Actual type `Never` is not the same as asserted type `() -> None`
- error[lint:missing-argument] tests/type_tests.py:36:6: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:36:14: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:type-assertion-failure] tests/type_tests.py:41:9: Actual type `Unknown` is not the same as asserted type `() -> @Todo(specialized non-generic class)`
+ error[lint:type-assertion-failure] tests/type_tests.py:41:9: Actual type `(...) -> Unknown` is not the same as asserted type `() -> @Todo(specialized non-generic class)`
- error[lint:missing-argument] tests/type_tests.py:44:6: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:44:14: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:type-assertion-failure] tests/type_tests.py:49:9: Actual type `Unknown` is not the same as asserted type `() -> @Todo(specialized non-generic class)`
+ error[lint:type-assertion-failure] tests/type_tests.py:49:9: Actual type `(...) -> Unknown` is not the same as asserted type `() -> @Todo(specialized non-generic class)`
- error[lint:missing-argument] tests/type_tests.py:61:6: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:61:14: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- error[lint:missing-argument] tests/type_tests.py:66:6: No argument provided for required parameter `fn` of function `keyword`
- error[lint:unknown-argument] tests/type_tests.py:66:14: Argument `wrap_context_manager` does not match any known parameter of function `keyword`
- Found 352 diagnostics
+ Found 322 diagnostics

anyio (https://github.com/agronholm/anyio)
- error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[DatagramProtocol]`
+ error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> Unknown`, found `Literal[DatagramProtocol]`
- error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[DatagramProtocol]`
+ error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> Unknown`, found `Literal[DatagramProtocol]`
- error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[DatagramProtocol]`
+ error[lint:invalid-argument-type] src/anyio/_backends/_asyncio.py:2634:13: Argument to this function is incorrect: Expected `() -> Unknown`, found `Literal[DatagramProtocol]`
+ error[lint:invalid-argument-type] src/anyio/_core/_tempfile.py:299:21: Argument to this function is incorrect: Argument type `BytesIO` does not satisfy upper bound of type variable `_BufferT_co`
+ error[lint:invalid-argument-type] src/anyio/_core/_tempfile.py:299:21: Argument to this function is incorrect: Expected `_WrappedBuffer`, found `BytesIO`
- warning[lint:redundant-cast] src/anyio/from_thread.py:290:16: Value is already of type `Unknown`
+ error[lint:no-matching-overload] src/anyio/streams/memory.py:62:16: No overload of bound method `__init__` matches arguments
+ error[lint:invalid-return-type] src/anyio/streams/memory.py:124:24: Return type does not match returned value: Expected `T_co`, found `T_Item`
- Found 137 diagnostics
+ Found 140 diagnostics

starlette (https://github.com/encode/starlette)
+ error[lint:no-matching-overload] starlette/requests.py:154:20: No overload of bound method `__init__` matches arguments
- warning[lint:possibly-unbound-attribute] starlette/requests.py:114:20: Attribute `endswith` on type `@Todo(Support for `typing.TypeVar` instances in type expressions) | None` is possibly unbound
- error[lint:unsupported-operator] starlette/requests.py:115:17: Operator `+=` is unsupported between objects of type `None` and `Literal["/"]`
+ error[lint:no-matching-overload] starlette/schemas.py:60:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] starlette/schemas.py:77:43: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] starlette/schemas.py:84:43: No overload of bound method `__init__` matches arguments
- error[lint:invalid-argument-type] tests/conftest.py:20:9: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[TestClient]`
+ error[lint:invalid-argument-type] tests/conftest.py:20:9: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[TestClient]`
- error[lint:type-assertion-failure] tests/test_config.py:23:5: Actual type `Unknown` is not the same as asserted type `str | None`
+ error[lint:type-assertion-failure] tests/test_config.py:23:5: Actual type `None` is not the same as asserted type `str | None`
- error[lint:type-assertion-failure] tests/test_config.py:24:5: Actual type `Unknown` is not the same as asserted type `str`
+ error[lint:type-assertion-failure] tests/test_config.py:24:5: Actual type `Literal[""]` is not the same as asserted type `str`
- error[lint:type-assertion-failure] tests/test_config.py:27:5: Actual type `Unknown` is not the same as asserted type `bool`
+ error[lint:type-assertion-failure] tests/test_config.py:27:5: Actual type `Literal[False]` is not the same as asserted type `bool`
- error[lint:type-assertion-failure] tests/test_config.py:28:5: Actual type `Unknown` is not the same as asserted type `bool | None`
+ error[lint:type-assertion-failure] tests/test_config.py:28:5: Actual type `None` is not the same as asserted type `bool | None`
- Found 197 diagnostics
+ Found 199 diagnostics

kornia (https://github.com/kornia/kornia)
+ error[lint:no-matching-overload] kornia/augmentation/container/ops.py:138:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/augmentation/container/patch.py:268:26: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:131:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:132:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:133:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:134:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:141:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:142:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:143:21: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kornia/contrib/models/rt_detr/architecture/hgnetv2.py:144:21: No overload of bound method `__init__` matches arguments
- error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:336:26: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[NestedTensorBlock]`
+ error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:336:26: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[NestedTensorBlock]`
- error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:350:26: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[NestedTensorBlock]`
+ error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:350:26: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[NestedTensorBlock]`
- error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:364:26: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[NestedTensorBlock]`
+ error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:364:26: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[NestedTensorBlock]`
- error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:378:26: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[NestedTensorBlock]`
+ error[lint:invalid-argument-type] kornia/feature/dedode/transformer/dinov2.py:378:26: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[NestedTensorBlock]`
+ error[lint:no-matching-overload] kornia/feature/sold2/backbones.py:59:23: No overload of bound method `__init__` matches arguments
- error[lint:call-non-callable] kornia/filters/kernels_geometry.py:172:17: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
+ error[lint:call-non-callable] kornia/filters/kernels_geometry.py:172:17: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
- error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:31: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
+ error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:31: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
- error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:44: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
+ error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:44: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
- error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:57: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
+ error[lint:call-non-callable] kornia/filters/kernels_geometry.py:203:57: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int | float, int | float, int | float]`
- error[lint:call-non-callable] kornia/geometry/boxes.py:349:21: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
- error[lint:call-non-callable] kornia/geometry/boxes.py:352:21: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
- error[lint:call-non-callable] kornia/geometry/boxes.py:355:22: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
- error[lint:call-non-callable] kornia/geometry/boxes.py:358:22: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
+ error[lint:call-non-callable] kornia/geometry/boxes.py:349:21: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
+ error[lint:call-non-callable] kornia/geometry/boxes.py:352:21: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
+ error[lint:call-non-callable] kornia/geometry/boxes.py:355:22: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
+ error[lint:call-non-callable] kornia/geometry/boxes.py:358:22: Method `__getitem__` of type `Unknown | (Overload[(key: SupportsIndex, /) -> _T_co, (key: slice, /) -> @Todo(full tuple[...] support)])` is not callable on object of type `Unknown | tuple[int, int] | None`
- Found 1003 diagnostics
+ Found 1014 diagnostics

aioredis (https://github.com/aio-libs/aioredis)
+ error[lint:no-matching-overload] aioredis/client.py:337:25: No overload of function `__new__` matches arguments
+ error[lint:no-matching-overload] aioredis/client.py:462:38: No overload of function `__new__` matches arguments
- Found 29 diagnostics
+ Found 31 diagnostics

porcupine (https://github.com/Akuli/porcupine)
+ error[lint:invalid-return-type] porcupine/actions.py:127:12: Return type does not match returned value: Expected `(FileTab, /) -> bool`, found `partial`
+ error[lint:invalid-argument-type] porcupine/plugins/autocomplete.py:544:43: Argument to this function is incorrect: Expected `(EventWithData, /) -> str | None`, found `partial`
+ error[lint:no-matching-overload] porcupine/plugins/filemanager.py:242:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] porcupine/plugins/filemanager.py:247:19: No overload of bound method `__init__` matches arguments
- error[lint:invalid-return-type] porcupine/plugins/pastebin.py:192:16: Return type does not match returned value: Expected `str`, found `@Todo(Support for `typing.TypeVar` instances in type expressions) | None`
+ error[lint:invalid-return-type] porcupine/plugins/pastebin.py:192:16: Return type does not match returned value: Expected `str`, found `Unknown | None`
+ error[lint:invalid-argument-type] porcupine/plugins/pastebin.py:385:48: Argument to this function is incorrect: Expected `(bool, str | Unknown, /) -> None`, found `partial`
+ error[lint:invalid-argument-type] porcupine/plugins/python_tools.py:69:9: Argument to this function is incorrect: Expected `(FileTab, /) -> None`, found `partial`
+ error[lint:invalid-argument-type] porcupine/plugins/python_tools.py:76:9: Argument to this function is incorrect: Expected `(FileTab, /) -> None`, found `partial`
+ error[lint:invalid-return-type] porcupine/plugins/run/no_terminal.py:421:16: Return type does not match returned value: Expected `(() -> None) | None`, found `partial`
+ error[lint:invalid-argument-type] porcupine/plugins/urls.py:84:64: Argument to this function is incorrect: Expected `() -> None`, found `partial`
+ error[lint:no-matching-overload] porcupine/tabs.py:999:16: No overload of bound method `__init__` matches arguments
+ error[lint:invalid-argument-type] porcupine/utils.py:796:38: Argument to this function is incorrect: Expected `str | _T`, found `str | None`
- Found 157 diagnostics
+ Found 168 diagnostics

pylox (https://github.com/sco1/pylox)
+ error[lint:no-matching-overload] pylox/preprocessor.py:90:32: No overload of bound method `__init__` matches arguments
- error[lint:invalid-argument-type] tests/scanning/test_identifiers.py:18:25: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[Token]`
+ error[lint:invalid-argument-type] tests/scanning/test_identifiers.py:18:25: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[Token]`
- error[lint:invalid-argument-type] tests/scanning/test_keywords.py:17:25: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[Token]`
+ error[lint:invalid-argument-type] tests/scanning/test_keywords.py:17:25: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[Token]`
- error[lint:invalid-argument-type] tests/scanning/test_punctuators.py:17:25: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[Token]`
+ error[lint:invalid-argument-type] tests/scanning/test_punctuators.py:17:25: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[Token]`
- Found 41 diagnostics
+ Found 42 diagnostics

sockeye (https://github.com/awslabs/sockeye)
- error[lint:invalid-argument-type] sockeye/inference.py:350:50: Argument to this function is incorrect: Expected `Sized`, found `(@Todo(Support for `typing.TypeVar` instances in type expressions) & ~list) | None | @Todo(list comprehension type)`
+ error[lint:invalid-argument-type] sockeye/inference.py:350:50: Argument to this function is incorrect: Expected `Sized`, found `(Unknown & ~list) | None | @Todo(list comprehension type)`
- error[lint:invalid-argument-type] sockeye/inference.py:352:34: Argument to this function is incorrect: Expected `Sized`, found `(@Todo(Support for `typing.TypeVar` instances in type expressions) & ~list) | None | @Todo(list comprehension type)`
+ error[lint:invalid-argument-type] sockeye/inference.py:352:34: Argument to this function is incorrect: Expected `Sized`, found `(Unknown & ~list) | None | @Todo(list comprehension type)`
- error[lint:invalid-argument-type] sockeye/test_utils.py:224:34: Argument to this function is incorrect: Expected `list`, found `None | @Todo(Support for `typing.TypeVar` instances in type expressions)`
+ error[lint:invalid-argument-type] sockeye/test_utils.py:224:34: Argument to this function is incorrect: Expected `list`, found `None | Unknown`

check-jsonschema (https://github.com/python-jsonschema/check-jsonschema)
+ error[lint:invalid-argument-type] src/check_jsonschema/schema_loader/resolver.py:62:45: Argument to this function is incorrect: Argument type `Unknown | str | None` does not satisfy constraints of type variable `AnyStr`
+ error[lint:invalid-argument-type] src/check_jsonschema/schema_loader/resolver.py:62:45: Argument to this function is incorrect: Expected `str`, found `Unknown | str | None`
- Found 60 diagnostics
+ Found 62 diagnostics

ppb-vector (https://github.com/ppb/ppb-vector)
+ error[lint:unsupported-operator] ppb_vector/__init__.py:472:25: Operator `*` is unsupported between objects of type `SupportsFloat` and `Unknown | int | float`
- Found 150 diagnostics
+ Found 151 diagnostics

python-chess (https://github.com/niklasf/python-chess)
- error[lint:call-non-callable] chess/__init__.py:880:20: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
+ error[lint:call-non-callable] chess/__init__.py:880:20: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
- error[lint:call-non-callable] chess/__init__.py:1437:44: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/__init__.py:1437:44: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/__init__.py:1557:27: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/__init__.py:1557:27: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/__init__.py:1558:27: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/__init__.py:1558:27: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/__init__.py:1577:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/__init__.py:1577:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/__init__.py:1578:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/__init__.py:1578:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:unsupported-operator] chess/engine.py:1634:29: Operator `+=` is unsupported between objects of type `None` and `(int & ~AlwaysFalsy) | float`
+ error[lint:unsupported-operator] chess/engine.py:1638:29: Operator `+=` is unsupported between objects of type `None` and `(int & ~AlwaysFalsy) | float`
+ error[lint:unsupported-operator] chess/engine.py:1642:29: Operator `-=` is unsupported between objects of type `None` and `Literal[1]`
- error[lint:call-non-callable] chess/gaviota.py:1551:46: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1551:46: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1553:46: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1553:46: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1899:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/gaviota.py:1910:52: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/polyglot.py:256:44: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
+ error[lint:call-non-callable] chess/polyglot.py:256:44: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
- error[lint:call-non-callable] chess/polyglot.py:258:42: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
+ error[lint:call-non-callable] chess/polyglot.py:258:42: Method `__getitem__` of type `Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)]` is not callable on object of type `list`
+ error[lint:no-matching-overload] chess/polyglot.py:378:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] chess/polyglot.py:425:25: No overload of bound method `__init__` matches arguments
- error[lint:invalid-argument-type] chess/svg.py:170:19: Argument to this function is incorrect: Expected `str`, found `@Todo(Support for `typing.TypeVar` instances in type expressions) | None`
+ error[lint:invalid-argument-type] chess/svg.py:170:19: Argument to this function is incorrect: Expected `str`, found `Unknown | None`
- error[lint:call-non-callable] chess/syzygy.py:446:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/syzygy.py:446:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/syzygy.py:447:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/syzygy.py:447:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:682:35: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:682:35: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:683:35: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:683:35: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:686:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:686:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:687:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:687:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:829:26: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:829:26: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:830:26: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:830:26: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:833:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:833:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- error[lint:call-non-callable] chess/variant.py:834:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> @Todo(Support for `typing.TypeVar` instances in type expressions), (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
+ error[lint:call-non-callable] chess/variant.py:834:9: Method `__getitem__` of type `Unknown | (Overload[(i: SupportsIndex, /) -> _T, (s: slice, /) -> @Todo(specialized non-generic class)])` is not callable on object of type `Unknown | list`
- Found 78 diagnostics
+ Found 83 diagnostics

kopf (https://github.com/nolar/kopf)
+ error[lint:invalid-assignment] kopf/_cogs/aiokits/aioenums.py:54:9: Object of type `FlagReasonT | Unknown` is not assignable to `FlagReasonT | None`
+ error[lint:no-matching-overload] kopf/_cogs/aiokits/aiotasks.py:344:43: No overload of bound method `__init__` matches arguments
+ error[lint:call-non-callable] kopf/_cogs/clients/auth.py:41:30: Object of type `_F` is not callable
+ error[lint:call-non-callable] kopf/_cogs/clients/auth.py:51:34: Object of type `_F` is not callable
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:74:29: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:119:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:124:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:170:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:172:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_cogs/structs/diffs.py:183:15: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/actions/application.py:142:13: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/actions/progression.py:279:22: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/actions/progression.py:298:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/engines/posting.py:67:13: No overload of bound method `__init__` matches arguments
+ error[lint:call-non-callable] kopf/_core/intents/callbacks.py:254:20: Object of type `_FnT` is not callable
+ error[lint:invalid-argument-type] kopf/_core/intents/handlers.py:35:45: Argument to this function is incorrect: Argument type `CauseT & ChangingCause` does not satisfy upper bound of type variable `_DataclassT`
+ error[lint:no-matching-overload] kopf/_core/reactor/orchestration.py:198:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/reactor/orchestration.py:245:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] kopf/_core/reactor/queueing.py:204:32: No overload of bound method `__init__` matches arguments
+ error[lint:call-non-callable] kopf/_kits/webhacks.py:86:24: Object of type `_ServerFn` is not callable
+ error[lint:invalid-argument-type] kopf/_kits/webhooks.py:228:33: Argument to this function is incorrect: Argument type `socket` does not satisfy upper bound of type variable `_SupportsCloseT`
- Found 136 diagnostics
+ Found 157 diagnostics

strawberry (https://github.com/strawberry-graphql/strawberry)
- warning[lint:unused-ignore-comment] strawberry/aiohttp/views.py:210:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/asgi/__init__.py:192:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/chalice/views.py:114:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/channels/handlers/http_handler.py:271:12: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/channels/handlers/http_handler.py:345:12: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/channels/handlers/ws_handler.py:157:12: Unused blanket `type: ignore` directive
- error[lint:invalid-argument-type] strawberry/codegen/query_codegen.py:356:17: Argument to this function is incorrect: Expected `(...) -> @Todo(Support for `typing.TypeVar` instances in type expressions)`, found `Literal[GraphQLFragmentType]`
+ error[lint:invalid-argument-type] strawberry/codegen/query_codegen.py:356:17: Argument to this function is incorrect: Expected `(...) -> Unknown`, found `Literal[GraphQLFragmentType]`
+ error[lint:no-matching-overload] strawberry/directive.py:75:19: No overload of bound method `__init__` matches arguments
- error[lint:unresolved-attribute] strawberry/directive.py:134:25: Type `(...) -> Unknown` has no attribute `__name__`
+ error[lint:unresolved-attribute] strawberry/directive.py:134:25: Type `(...) -> T` has no attribute `__name__`
- warning[lint:unused-ignore-comment] strawberry/django/views.py:223:77: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/django/views.py:283:77: Unused blanket `type: ignore` directive
+ error[lint:no-matching-overload] strawberry/experimental/pydantic/object_type.py:105:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/experimental/pydantic/object_type.py:202:13: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:89:24: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:97:24: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:129:20: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:141:16: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:155:20: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/extensions/context.py:162:16: No overload of bound method `__init__` matches arguments
- warning[lint:unused-ignore-comment] strawberry/federation/object_type.py:89:24: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/flask/views.py:111:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/flask/views.py:174:60: Unused blanket `type: ignore` directive
- warning[lint:redundant-cast] strawberry/http/async_base_view.py:309:19: Value is already of type `Unknown`
- warning[lint:unused-ignore-comment] strawberry/quart/views.py:92:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/sanic/views.py:152:60: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/types/enum.py:150:45: Unused blanket `type: ignore` directive
+ error[lint:no-matching-overload] strawberry/types/fields/resolver.py:137:25: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] strawberry/types/fields/resolver.py:166:20: No overload of bound method `__init__` matches arguments
- warning[lint:unused-ignore-comment] strawberry/types/object_type.py:144:66: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/types/object_type.py:160:41: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/types/object_type.py:379:19: Unused blanket `type: ignore` directive
- warning[lint:unused-ignore-comment] strawberry/types/object_type.py:452:19: Unused blanket `type: ignore` directive
- Found 590 diagnostics
+ Found 582 diagnostics

flake8 (https://github.com/pycqa/flake8)
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:139:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:163:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:169:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:173:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:210:23: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:224:18: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:225:19: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:299:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:344:12: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/plugins/finder.py:345:18: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] src/flake8/style_guide.py:409:17: No overload of bound method `__init__` matches arguments
+ error[lint:invalid-argument-type] src/flake8/utils.py:193:33: Argument to this function is incorrect: Argument type `BytesIO` does not satisfy upper bound of type variable `_BufferT_co`
+ error[lint:invalid-argument-type] src/flake8/utils.py:193:33: Argument to this function is incorrect: Expected `_WrappedBuffer`, found `BytesIO`
+ error[lint:no-matching-overload] tests/integration/test_checker.py:85:9: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/integration/test_checker.py:88:13: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/integration/test_checker.py:273:44: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/integration/test_checker.py:338:17: No overload of bound method `__init__` matches arguments
+ error[lint:no-matching-overload] tests/unit/plugins/finder_test.p...*[Comment body truncated]*

@dcreager
Copy link
Member Author

The mypy_primer changes are because we're now interpreting the legacy TypeVars in the typeshed.

Base automatically changed from dcreager/two-phase-binding to main March 21, 2025 13:38
@dcreager dcreager force-pushed the dcreager/legacy-typevar-instance branch from d8d5f20 to f8d0350 Compare March 21, 2025 13:48
dcreager added 9 commits April 8, 2025 09:39
* main: (222 commits)
  [playground] New default program (#17277)
  [red-knot] Add `--python-platform` CLI option (#17284)
  [red-knot] Allow ellipsis default params in stub functions (#17243)
  [red-knot] Fix stale syntax errors in playground (#17280)
  Update Rust crate clap to v4.5.35 (#17273)
  Fix RUF100 to detect unused file-level noqa directives with specific codes (#17042) (#17061)
  [ci] Fix pattern for code changes (#17275)
  [`airflow`] Update oudated `AIR301`, `AIR302` rules (#17123)
  [docs] fix formatting of "See Style Guide" link (#17272)
  [red-knot] Support stub packages (#17204)
  ruff_annotate_snippets: address unused code warnings
  [red-knot] Add a couple more tests for `*` imports (#17270)
  [red-knot] Add 'Format document' to playground (#17217)
  Update actions/setup-node action to v4.3.0 (#17259)
  Update actions/upload-artifact action to v4.6.2 (#17261)
  Update actions/download-artifact action to v4.2.1 (#17258)
  Update actions/setup-python action to v5.5.0 (#17260)
  Update actions/cache action to v4.2.3 (#17256)
  Update Swatinem/rust-cache action to v2.7.8 (#17255)
  Update actions/checkout action to v4.2.2 (#17257)
  ...
* main: (123 commits)
  [red-knot] Handle explicit class specialization in type expressions (#17434)
  [red-knot] allow assignment expression in call compare narrowing (#17461)
  [red-knot] fix building unions with literals and AlwaysTruthy/AlwaysFalsy (#17451)
  [red-knot] Type narrowing for assertions (take 2) (#17345)
  [red-knot] class bases are not affected by __future__.annotations (#17456)
  [red-knot] Add support for overloaded functions (#17366)
  [`pyupgrade`] Add fix safety section to docs (`UP036`) (#17444)
  [red-knot] more type-narrowing in match statements (#17302)
  [red-knot] Add some narrowing for assignment expressions (#17448)
  [red-knot] Understand `typing.Protocol` and `typing_extensions.Protocol` as equivalent (#17446)
  Server: Use `min` instead of `max` to limit the number of threads (#17421)
  [red-knot] Detect version-related syntax errors (#16379)
  [`pyflakes`] Add fix safety section (`F841`) (#17410)
  [red-knot] Add `KnownFunction` variants for `is_protocol`, `get_protocol_members` and `runtime_checkable` (#17450)
  Bump 0.11.6 (#17449)
  Auto generate `visit_source_order` (#17180)
  [red-knot] Initial tests for protocols (#17436)
  [red-knot] Dataclasses: synthesize `__init__` with proper signature (#17428)
  [red-knot] Dataclasses: support `order=True` (#17406)
  [red-knot] Super-basic generic inference at call sites (#17301)
  ...
@codspeed-hq
Copy link

codspeed-hq bot commented Apr 18, 2025

CodSpeed Performance Report

Merging #16538 will not alter performance

Comparing dcreager/legacy-typevar-instance (30f116f) with main (5096824)

Summary

✅ 33 untouched benchmarks

* main: (27 commits)
  [red-knot] Add new property tests for subtyping with "bottom" callable (#17635)
  [red-knot] Create generic context for generic classes lazily (#17617)
  ruff_db: add tests for annotations with no ranges
  [`airflow`] Extend `AIR301` rule (#17598)
  [`airflow`] update existing `AIR302` rules with better suggestions (#17542)
  red_knot_project: sort diagnostics from checking files
  [red-knot] fix detecting a metaclass on a not-explicitly-specialized generic base (#17621)
  [red-knot] fix inheritance-cycle detection for generic classes (#17620)
  [`pylint`] Detect `global` declarations in module scope (`PLE0118`) (#17411)
  Add Semantic Error Test for LateFutureImport (#17612)
  [red-knot] change TypeVarInstance to be interned, not tracked (#17616)
  [red-knot] Special case `@final`, `@override` (#17608)
  [red-knot] add TODO comment in specialization code (#17615)
  [`semantic-syntax-errors`] test for `LoadBeforeGlobalDeclaration` - ruff linter (#17592)
  [syntax-errors] `nonlocal` declaration at module level (#17559)
  [`airflow`] Apply auto fix to cases where name has been changed in Airflow 3 (`AIR311`) (#17571)
  [syntax-errors] Make `async-comprehension-in-sync-comprehension` more specific (#17460)
  Bump 0.11.7 (#17613)
  [red-knot] Use iterative approach to collect overloads (#17607)
  red_knot_python_semantic: avoid Rust's screaming snake case convention in mdtest
  ...
/// to the target, and so have `None` for this field.)
#[no_eq]
#[tracked]
pub(crate) assigned_to: Option<AstNodeRef<ast::StmtAssign>>,
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't love how this is so specialized to StmtAssign. We're not currently creating a standalone expression for annotated assignments, which means we currently raise a false positive for

T: TypeVar = TypeVar("T")

Are there any concerns with adding a standalone expression for annotated assignments too? Then I could make this ast::Stmt (or maybe a separate enum that only allows StmtAssign and StmtAnnAssign)

Copy link
Member

Choose a reason for hiding this comment

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

I would be happy with disallowing T: TypeVar = TypeVar("T")! I don't think it really makes sense to add the annotation there: it will be ignored by us anyway. It indicates to me that the user is confused about how TypeVars work, and perhaps doesn't realise that a simple T = TypeVar("T") assignment will also be considered a declaration by us. Mypy disallows an annotation in this situation: https://mypy-play.net/?mypy=latest&python=3.12&gist=4dad759b00a84071f89fbe9b5e041dcb

I'm also okay with allowing it, though. No strong opinion, as long as we don't emit a confusing error message if somebody does this 😄

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be preferable not to add a standalone expression for every annotated assignment; the more standalone expressions, the more memos, and the slower incremental re-validation gets. If we really need to, we probably can, but I don't think T: TypeVar = TypeVar("T") is a sufficiently motivating use case. As Alex says, I think it would be fine to just error on that; T = TypeVar("T") is effectively a syntactic special form.

Copy link
Member Author

Choose a reason for hiding this comment

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

As Alex says, I think it would be fine to just error on that;
...
No strong opinion, as long as we don't emit a confusing error message if somebody does this 😄

The main issue with this is that customizing the error message will require the same extra plumbing as allowing it, since we'd need to detect that the TypeVar call occurs in an annotated assignment. Otherwise we'll have the default error message A legacy `typing.TypeVar` must be immediately assigned to a variable.

Copy link
Member Author

Choose a reason for hiding this comment

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

Otherwise we'll have the default error message A legacy `typing.TypeVar` must be immediately assigned to a variable.

Which, to be clear, I'm okay with, certainly for now

@MichaReiser
Copy link
Member

MichaReiser commented Apr 26, 2025

Congrats on fixing the performance regression!

@sharkdp
Copy link
Contributor

sharkdp commented Apr 28, 2025

There are 20,064 new diagnostics on this PR (an overall increase in diagnostics of 27%). 19,038 of these are of the form "No overload of bound method __init__ matches arguments", and the majority (all?) seem to be related to NamedTuple construction. We should probably work on silencing them somehow after this PR has been merged.

That still leaves 1,026 new diagnostics on this branch that have various other causes. I understand that this PR increases our coverage a lot, so it's entirely possible that all new diagnostics are unrelated to the changes here. But it might be worth studying this a bit more? (unless you already did, @dcreager)

I uploaded an experimental new diff view of the ecosystem changes. I filtered out the 19k invalid-overload diagnostics mentioned above, to make this easier to scan.

Some things that stand out to me:

  • lot's of call-new-callable diagnostics related to pytest decorators which seem strange:
    [error] call-non-callable - tests/utilities/test_strip_ignored_characters_fuzz.py:79:5 - Object of type `Literal[10]` is not callable
    
  • A lot of errors related to assignability of partial instances, which I hoped had been fixed here.
  • Some invalid-legacy-type-variable errors in vendored typing_extensions

@dcreager
Copy link
Member Author

There are 20,064 new diagnostics on this PR (an overall increase in diagnostics of 27%). 19,038 of these are of the form "No overload of bound method __init__ matches arguments", and the majority (all?) seem to be related to NamedTuple construction. We should probably work on silencing them somehow after this PR has been merged.

Yep, those are because of the NamedTuple.__init__ overloads in typeshed: #16538 (comment)

* main: (37 commits)
  [red-knot] Revert blanket `clippy::too_many_arguments` allow (#17688)
  Add config option to disable `typing_extensions` imports  (#17611)
  ruff_db: render file paths in diagnostics as relative paths if possible
  Bump mypy_primer pin (#17685)
  red_knot_python_semantic: improve `not-iterable` diagnostic
  [red-knot] Allow all callables to be assignable to @Todo-signatures (#17680)
  [`refurb`] Mark fix as safe for `readlines-in-for` (`FURB129`) (#17644)
  Collect preview lint behaviors in separate module (#17646)
  Upgrade Salsa to a more recent commit (#17678)
  [red-knot] TypedDict: No errors for introspection dunder attributes (#17677)
  [`flake8-pyi`] Ensure `Literal[None,] | Literal[None,]` is not autofixed to `None | None` (`PYI061`) (#17659)
  [red-knot] No errors for definitions of `TypedDict`s (#17674)
  Update actions/download-artifact digest to d3f86a1 (#17664)
  [red-knot] Use 101 exit code when there's at least one diagnostic with severity 'fatal' (#17640)
  [`pycodestyle`] Fix duplicated diagnostic in `E712` (#17651)
  [airflow] fix typos `AIR312` (#17673)
  [red-knot] Don't ignore hidden files by default (#17655)
  Update pre-commit hook astral-sh/ruff-pre-commit to v0.11.7 (#17670)
  Update docker/build-push-action digest to 14487ce (#17665)
  Update taiki-e/install-action digest to ab3728c (#17666)
  ...
@dhruvmanila
Copy link
Member

dhruvmanila commented Apr 28, 2025

I'm interested in trying to put this PR on top of #17618 to see what effect it has on the diagnostics that this PR adds. I'm going to try it locally and see. This shouldn't block this PR from merging.

@dcreager
Copy link
Member Author

lot's of call-new-callable diagnostics related to pytest decorators which seem strange:

This looks to be coming from here:

    @overload
    def __call__(self, arg: Markable) -> Markable:  # type: ignore[overload-overlap]
        pass

    @overload
    def __call__(self, *args: object, **kwargs: object) -> MarkDecorator:
        pass

    def __call__(self, *args: object, **kwargs: object):

where Markable is a legacy typevar with a Callable bound. I'm also interested in @dhruvmanila's experiment to test this with intersection overloads — it seems like we should fall through to the (*args, **kwargs) overload if the first overload doesn't match (because of the argument, say Literal[10], not being callable)

@sharkdp
Copy link
Contributor

sharkdp commented Apr 28, 2025

where Markable is a legacy typevar with a Callable bound

Minor additional comment: the bound is Union[Callable[..., object], type], if that changes anything (I don't see why it would; still not compatible with Literal[10])

@carljm
Copy link
Contributor

carljm commented Apr 28, 2025

Out of curiosity, I looked into the pytest decorator call-non-callable diagnostics. In pytest.mark.whatever, the "whatever" is actually arbitrary: pytest.mark is an object with a __getattr__ implementation returning an instance of _pytest.mark.MarkDecorator. MarkDecorator then has this overloaded __call__ method, where Markable is a bound TypeVar. So I think what is happening is that we don't yet respect typevar bounds when inferring types in a generic function, so we wrongly pick the first overload even when the argument in e.g. pytest.mark.timeout(10) is not assignable to the upper bound of Markable, which means we should pick the second overload.

None of that is to say it needs fixing in this PR, it can be a follow-up.

@dhruvmanila
Copy link
Member

I'm interested in trying to put this PR on top of #17618 to see what effect it has on the diagnostics that this PR adds. I'm going to try it locally and see. This shouldn't block this PR from merging.

It does seem to be reducing the number of overall diagnostics but not by much compared to what already exists. Ref #17690. I haven't looked closely to the diagnostics that it's removing, I can do that a bit later if it'd be useful.

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.

This looks good to me! Obviously it would be good to follow up with some attention to the new false positives.

/// to the target, and so have `None` for this field.)
#[no_eq]
#[tracked]
pub(crate) assigned_to: Option<AstNodeRef<ast::StmtAssign>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be preferable not to add a standalone expression for every annotated assignment; the more standalone expressions, the more memos, and the slower incremental re-validation gets. If we really need to, we probably can, but I don't think T: TypeVar = TypeVar("T") is a sufficiently motivating use case. As Alex says, I think it would be fine to just error on that; T = TypeVar("T") is effectively a syntactic special form.

@carljm
Copy link
Contributor

carljm commented Apr 28, 2025

Oh oops, looks like I was looking into the call-non-callable at the same time as others :)

@carljm
Copy link
Contributor

carljm commented Apr 28, 2025

it seems like we should fall through to the (*args, **kwargs) overload if the first overload doesn't match (because of the argument, say Literal[10], not being callable)

Isn't the issue here simply that we pay no attention to bounds, so the first overload always matches?

@dhruvmanila
Copy link
Member

dhruvmanila commented Apr 28, 2025

It does seem to be reducing the number of overall diagnostics but not by much compared to what already exists. Ref #17690. I haven't looked closely to the diagnostics that it's removing, I can do that a bit later if it'd be useful.

Most of the changes I'm seeing in #17690 are consistent with what I'm already seeing in #17618, but I've noticed that almost 1/3rd of call-non-callable diagnostics are removed:

  ┃ Diagnostic ID                      ┃ Severity ┃ Removed ┃ Added ┃ Net Change ┃
- │ lint:call-non-callable             │ error    │      98 │   497 │       +399 │
+ │ lint:call-non-callable             │ error    │     124 │   158 │        +34 │

@dcreager
Copy link
Member Author

Isn't the issue here simply that we pay no attention to bounds, so the first overload always matches?

Ah yes, you're right! I had thought it would be caught by the type-checking code, but if we infer this type mapping and then substitute that for the formal parameter annotation, it will pass. That's worth handling here, I think, and not in a follow-on PR.

* main:
  [`ruff`] add fix safety section (`RUF017`) (#17480)
  Add Python 3.14 to configuration options (#17647)
  [`airflow`] Apply auto fixes to cases where the names have changed in Airflow 3 (`AIR302`) (#17553)
@dcreager
Copy link
Member Author

Ah yes, you're right! I had thought it would be caught by the type-checking code, but if we infer this type mapping and then substitute that for the formal parameter annotation, it will pass. That's worth handling here, I think, and not in a follow-on PR.

We now check the bounds and constraints when inferring specializations, which removed all of the pytest-related call-non-callable errors.

@dcreager
Copy link
Member Author

I'm going to go ahead and merge so that I can proceed with legacy generic classes. My apologies to our poor ecosystem graphs... 😂

@dcreager dcreager merged commit ca4fdf4 into main Apr 29, 2025
34 checks passed
@dcreager dcreager deleted the dcreager/legacy-typevar-instance branch April 29, 2025 13:03
@sharkdp
Copy link
Contributor

sharkdp commented Apr 29, 2025

I'm going to look at those NamedTuple false positives.

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.

Nice!


reveal_type(f(1)) # revealed: Literal[1]
reveal_type(f(True)) # revealed: Literal[True]
# error: [invalid-argument-type] "Argument to this function is incorrect: Argument type `Literal["string"]` does not satisfy upper bound of type variable `T`"
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be worth also having similar tests for legacy typevars with bounds/constraints? Both to show we handle the bounds and constraints correctly, and that the full diagnostic highlights them correctly?

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.

7 participants