ruff/crates/ty_python_semantic/resources/mdtest/diagnostics
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
..
attribute_assignment.md [ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492) 2025-09-23 14:26:55 +00:00
invalid_argument_type.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
invalid_await.md [ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492) 2025-09-23 14:26:55 +00:00
legacy_typevars.md [ty] defer inference of legacy TypeVar bound/constraints/defaults (#20598) 2025-10-09 21:08:37 +00:00
missing_argument.md [ty] Improve diagnostics for bad calls to functions (#20022) 2025-08-21 22:00:44 +01:00
no_matching_overload.md [ty] Improve invalid method calls for unmatched overloads (#18122) 2025-05-15 11:39:14 -04:00
same_names.md [ty] Improve assignability/subtyping between two protocol types (#20368) 2025-10-08 18:37:30 +00:00
semantic_syntax_errors.md [ty] simplify return type of place_from_declarations (#19884) 2025-08-13 14:17:08 +00:00
shadowing.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
single_matching_overload.md [ty] Surface matched overload diagnostic directly (#18452) 2025-06-20 08:36:49 +05:30
too_many_positionals.md [ty] Improve diagnostics for bad calls to functions (#20022) 2025-08-21 22:00:44 +01:00
union_call.md [ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492) 2025-09-23 14:26:55 +00:00
unknown_argument.md [ty] Improve diagnostics for bad calls to functions (#20022) 2025-08-21 22:00:44 +01:00
unpacking.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
unresolved_import.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
unresolved_reference.md [ty] Add a note to the diagnostic if a new builtin is used on an old Python version (#18068) 2025-05-13 10:08:04 -04:00
unsupported_bool_conversion.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
version_related_syntax_errors.md Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00