[ty] Reject legacy TypeVars in PEP 695 class bases#25975
Conversation
Typing conformance results improved 🎉The percentage of diagnostics emitted that were expected errors increased from 94.36% to 94.36%. The percentage of expected errors that received a diagnostic increased from 88.82% to 88.91%. The number of fully passing files held steady at 93/134. SummaryHow are test cases classified?Each test case represents one expected error annotation or a group of annotations sharing a tag. Counts are per test case, not per diagnostic — multiple diagnostics on the same line count as one. Required annotations (
Test file breakdown1 file altered
True positives added (1)1 diagnostic
|
Memory usage reportMemory usage unchanged ✅ |
|
## Summary
A function with its own PEP 695 type parameter list cannot also
introduce a traditional `TypeVar` or `ParamSpec`. Prior to this change,
we discovered the legacy generic context while building the signature
but discarded it when merging with the PEP 695 context without reporting
an error:
```python
from typing import TypeVar
K = TypeVar("K")
def method[M](value: M, other: K) -> M | K:
raise NotImplementedError
```
With #25975, we now pass the `generics_syntax_compatibility` test in the
conformance suite.
Summary
PEP 695 requires classes that use the new type parameter syntax not to introduce traditional type variables through their base classes. Prior to this change, we prioritized the PEP 695 generic context and silently discarded a legacy context inherited from another generic base:
This reports
invalid-generic-classwhen a PEP 695 class inherits a supported legacy generic context. A PEP 695 parameter with the same name continues to shadow the global TypeVar, and ordinary methods can still use the traditional implicit generic-function mechanism.Generic base types are normalized before this validation runs, so for those cases, we just leave them as a TODO for now.