ruff/crates/ty_ide/src
Carl Meyer 8248193ed9
[ty] defer inference of legacy TypeVar bound/constraints/defaults (#20598)
## Summary

This allows us to handle self-referential bounds/constraints/defaults
without panicking.

Handles more cases from https://github.com/astral-sh/ty/issues/256

This also changes the way we infer the types of legacy TypeVars. Rather
than understanding a constructor call to `typing[_extension].TypeVar`
inside of any (arbitrarily nested) expression, and having to use a
special `assigned_to` field of the semantic index to try to best-effort
figure out what name the typevar was assigned to, we instead understand
the creation of a legacy `TypeVar` only in the supported syntactic
position (RHS of a simple un-annotated assignment with one target). In
any other position, we just infer it as creating an opaque instance of
`typing.TypeVar`. (This behavior matches all other type checkers.)

So we now special-case TypeVar creation in `TypeInferenceBuilder`, as a
special case of an assignment definition, rather than deeper inside call
binding. This does mean we re-implement slightly more of
argument-parsing, but in practice this is minimal and easy to handle
correctly.

This is easier to implement if we also make the RHS of a simple (no
unpacking) one-target assignment statement no longer a standalone
expression. Which is fine to do, because simple one-target assignments
don't need to infer the RHS more than once. This is a bonus performance
(0-3% across various projects) and significant memory-usage win, since
most assignment statements are simple one-target assignment statements,
meaning we now create many fewer standalone-expression salsa
ingredients.

This change does mean that inference of manually-constructed
`TypeAliasType` instances can no longer find its Definition in
`assigned_to`, which regresses go-to-definition for these aliases. In a
future PR, `TypeAliasType` will receive the same treatment that
`TypeVar` did in this PR (moving its special-case inference into
`TypeInferenceBuilder` and supporting it only in the correct syntactic
position, and lazily inferring its value type to support recursion),
which will also fix the go-to-definition regression. (I decided a
temporary edge-case regression is better in this case than doubling the
size of this PR.)

This PR also tightens up and fixes various aspects of the validation of
`TypeVar` creation, as seen in the tests.

We still (for now) treat all typevars as instances of `typing.TypeVar`,
even if they were created using `typing_extensions.TypeVar`. This means
we'll wrongly error on e.g. `T.__default__` on Python 3.11, even if `T`
is a `typing_extensions.TypeVar` instance at runtime. We share this
wrong behavior with both mypy and pyrefly. It will be easier to fix
after we pull in https://github.com/python/typeshed/pull/14840.

There are some issues that showed up here with typevar identity and
`MarkTypeVarsInferable`; the fix here (using the new `original` field
and `is_identical_to` methods on `BoundTypeVarInstance` and
`TypeVarInstance`) is a bit kludgy, but it can go away when we eliminate
`MarkTypeVarsInferable`.

## Test Plan

Added and updated mdtests.

### Conformance suite impact

The impact here is all positive:

* We now correctly error on a legacy TypeVar with exactly one constraint
type given.
* We now correctly error on a legacy TypeVar with both an upper bound
and constraints specified.

### Ecosystem impact

Basically none; in the setuptools case we just issue slightly different
errors on an invalid TypeVar definition, due to the modified validation
code.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-10-09 21:08:37 +00:00
..
all_symbols.rs [ty] Add module to result returned by "all symbols" API 2025-09-17 13:59:28 -04:00
completion.rs [ty] Use 3.14 as the default version (#20759) 2025-10-08 11:38:47 +02:00
doc_highlights.rs [ty] Added support for "document highlights" language server feature. (#19515) 2025-07-24 13:06:25 -07:00
docstring.rs [ty] render docstrings in hover (#19882) 2025-08-13 14:59:20 +00:00
document_symbols.rs [ty] Rejigger workspace symbols for more efficient caching 2025-08-23 12:53:41 -04:00
find_node.rs [ty] fix GotoTargets for keyword args in nested function calls (#20013) 2025-08-21 20:19:52 +00:00
goto.rs [ty] Do not re-export `ide_support` attributes from `types` (#20769) 2025-10-08 17:45:28 +02:00
goto_declaration.rs [ty] Make initializer calls GotoTargets (#20014) 2025-09-02 14:49:14 -04:00
goto_definition.rs [ty] Make initializer calls GotoTargets (#20014) 2025-09-02 14:49:14 -04:00
goto_references.rs [ty] Use `dedent` in cursor tests (#20019) 2025-08-21 10:31:54 +02:00
goto_type_definition.rs [ty] defer inference of legacy TypeVar bound/constraints/defaults (#20598) 2025-10-09 21:08:37 +00:00
hover.rs [ty] Add support for generic PEP695 type aliases (#20219) 2025-09-08 13:26:21 -07:00
importer.rs [`ruff`] Fix minor typos in doc comments (#20623) 2025-09-29 08:56:23 +02:00
inlay_hints.rs [ty] Do not re-export `ide_support` attributes from `types` (#20769) 2025-10-08 17:45:28 +02:00
lib.rs [ty] Add a new abstraction for adding imports to a module 2025-09-17 13:59:28 -04:00
markup.rs Update Rust toolchain to 1.89 (#19807) 2025-08-07 18:21:50 +02:00
references.rs [ty] render docstrings in hover (#19882) 2025-08-13 14:59:20 +00:00
rename.rs [ty] render docstrings in hover (#19882) 2025-08-13 14:59:20 +00:00
selection_range.rs [ty] fix GotoTargets for keyword args in nested function calls (#20013) 2025-08-21 20:19:52 +00:00
semantic_tokens.rs [ty] Do not re-export `ide_support` attributes from `types` (#20769) 2025-10-08 17:45:28 +02:00
signature_help.rs [ty] Do not re-export `ide_support` attributes from `types` (#20769) 2025-10-08 17:45:28 +02:00
stub_mapping.rs [ty] Implement non-stdlib stub mapping for classes and functions (#19471) 2025-07-22 12:42:55 +00:00
symbols.rs [ty] Move `CompletionKind` to `ty_ide` 2025-09-17 13:59:28 -04:00
workspace_symbols.rs [ty] Rejigger workspace symbols for more efficient caching 2025-08-23 12:53:41 -04:00