Repository navigation
Recognize quoted types in typing.TypeForm - #28507
Merged
Merged
Conversation
Summary -- `typing.TypeForm` was introduced in Python 3.15 and [PEP 747](https://peps.python.org/pep-0747/) as a way to annotate the passing of type objects like `int | str`, `list[int]`, or `MyTypeAlias`. It can be used either as a subscripted generic, as in this example from the PEP: ```py from typing import TypeForm def trycast[T](typx: TypeForm[T], value: object) -> T | None: ... ``` or as a callable, which returns its argument unchanged: ```py from typing import TypeForm TypeForm("list[int]") ``` This PR recognizes `typing.TypeForm` as a standard-library generic and as a known `typing` callable and visits its argument or subscript as a type definition. While I was reading the [typing docs], I realized that a couple of nearby types were also not listed, so I've attempted to sneak them in here but could split them off if needed. We already had coverage for `typing.TypeGuard` but not `typing_extensions.TypeGuard` (added in 3.10), and we were missing both variants of `TypeIs` (added in 3.13). These are only valid in the subscript form, so they don't need new `Callable` entries. [typing docs]: https://docs.python.org/3.15/library/typing.html#typing.TypeForm Test Plan -- New mdtests, using `unused-import` (`F401`) to demonstrate that visiting these arguments as type definitions marks them as used.
|
ntBre
marked this pull request as ready for review
September 10, 2026 21:01
|
MichaReiser
self-requested a review
September 11, 2026 06:09
MichaReiser
approved these changes
Sep 11, 2026
| | "Type" | ||
| | "TypeForm" | ||
| | "TypeGuard" | ||
| | "TypeIs" |
Member
There was a problem hiding this comment.
Should we also add some tests for the other newly added generic types?
ntBre
enabled auto-merge (squash)
September 11, 2026 14:05
carljm
added a commit
that referenced
this pull request
Sep 11, 2026
…aliases * origin/main: (30 commits) [ty] Respect instance dictionary storage for slotted classes (#27749) Add a GitHub repository threat model for Ruff (#28395) [ty] Preserve wrapped signatures in nominal descriptor checks (#28466) [ty] Avoid rebinding extracted method calls (#28469) Recognize quoted types in `typing.TypeForm` (#28507) Support conditional assignment to `__lazy_modules__` (#28491) Add support for `__lazy_modules__` (#28459) [`pyupgrade`] Stop recommending deprecated `ByteString` aliases (`UP035`) (#28498) [ty] Anchor default exclude patterns at the project root (#28463) [ty] Add playground command to toggle inlay hints (#28517) [ty] Ignore divergent markers when detecting descriptors (#28514) [ty] Reuse rendered union elements when displaying types (#28494) [ty] Fix assignability of bounded typevars to intersection types (#28479) [ty] Retain package listings between resolution steps (#28278) Add accessors for comparison expressions (#28485) [ty] Refactor module resolution to use a `ModuleDirectory` abstraction. (#28418) [ty] Reduce retained AST memory by shrinking expressions (#28335) Bump version to 0.16.7 (#28496) Install rustfmt before linting releases (#28495) ensure prepare release changes pass prek (#28488) ... # Conflicts: # crates/ty_python_semantic/src/types/bool.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
typing.TypeFormwas introduced in Python 3.15 and PEP 747 asa way to annotate the passing of type objects like
int | str,list[int], orMyTypeAlias. Itcan be used either as a subscripted generic, as in this example from the PEP:
or as a callable, which returns its argument unchanged:
This PR recognizes
typing.TypeFormas a standard-library generic and as a knowntypingcallableand visits its argument or subscript as a type definition.
While I was reading the typing docs, I realized that a couple of nearby types were also not
listed, so I've attempted to sneak them in here but could split them off if needed. We already had
coverage for
typing.TypeGuardbut nottyping_extensions.TypeGuard(added in 3.10), and we weremissing both variants of
TypeIs(added in 3.13). These are only valid in the subscript form, sothey don't need new
Callableentries.Test Plan
New mdtests, using
unused-import(F401) to demonstrate that visiting these arguments as typedefinitions marks them as used, but other rules will be affected as well.