[ty] Detect inconsistent generic base class specializations#23615
[ty] Detect inconsistent generic base class specializations#23615AlexWaygood merged 8 commits intomainfrom
Conversation
Detect when a class explicitly inherits from a generic base class that also appears elsewhere in the MRO with a different specialization. For example: ```python class Grandparent(Generic[T1, T2]): ... class Parent(Grandparent[T1, T2]): ... class BadChild(Parent[T1, T2], Grandparent[T2, T1]): ... # Error ``` This reuses the existing `invalid-generic-class` diagnostic. The check is scoped to explicit generic bases to avoid false positives from deep MRO conflicts in built-in type hierarchies. https://claude.ai/code/session_01JRJvzA93sDTLreubgphoMu
Typing conformance results improved 🎉The percentage of diagnostics emitted that were expected errors increased from 85.39% to 85.41%. The percentage of expected errors that received a diagnostic increased from 76.01% to 76.10%. Summary
True positives addedDetails
|
|
Memory usage reportMemory usage unchanged ✅ |
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-generic-class |
2 | 0 | 0 |
| Total | 2 | 0 | 0 |
2b90ce8 to
6c834f8
Compare
1a14764 to
dd1b1f3
Compare
…n check Rework the inconsistent generic specialization check to detect conflicts even when neither conflicting ancestor is a direct explicit base (the diamond case). Uses a map to track all generic ancestors from all explicit bases and detect when the same class appears with different specializations from different base paths. Also fixes mdtest assertion format for multiple errors on the same line by using preceding-line comments. https://claude.ai/code/session_01JRJvzA93sDTLreubgphoMu
dd1b1f3 to
c595f22
Compare
| .types(self.db()), | ||
| ) | ||
| .any(|(t1, t2)| { | ||
| !t1.is_dynamic() && !t2.is_dynamic() && t1 != t2 |
There was a problem hiding this comment.
If we have three bases all inheriting G, and the first one we see is G[Any], and then we see G[int] and then G[str], we won't error about G[int] vs G[str], and it'll be order-dependent. (Because we'll put G[Any] in the map and then never consider it to conflict with anything.)
There was a problem hiding this comment.
Hmm, that doesn't seem to be the case? I've added some tests and they pass; pushing them now
There was a problem hiding this comment.
I think that's because Parent (implicitly specialized) is actually handled quite differently from Parent[Any, Any]. The former is just a ClassLiteral and we never put it in the map at all. The latter is a GenericAlias, and we do. So my comment was accurate but it really does require explicit specialization with Any, not implicit specialization (which actually is no specialization at all -- we do this lazily, not eagerly).
c1d0375 to
f887513
Compare
* main: [ty] Move binary expression logic out of `builder.rs` (#23649) [ty] Limit recursion depth when displaying self-referential function types (#23647) [ty] Move comparison logic out of `builder.rs` (#23646) Avoid inserting redundant `None` elements in UP045 (#23459) [ty] Add more ParamSpec validation for `P.args` and `P.kwargs` (#23640) [ty] Sync vendored typeshed stubs (#23642) [ty] Fix inference of `t.__mro__` if `t` is an instance of `type[Any]` (#23632) [ty] Detect inconsistent generic base class specializations (#23615) [ty] Validate type variable defaults don't reference later type parameters or type parameters out of scope (#23623) [ty] Ban nested `Required`/`NotRequired`, and ban them both outside of `TypedDict` fields (#23627) [ty] Reject generic metaclasses parameterized by type variables (#23628) Update default Python version examples (#23605) fix binops with NewType of float and Unknown (#23620) [ty] Reject functions with PEP-695 type parameters that shadow type parameters from enclosing scopes (#23619) [ty] Reject ellipsis literals in odd places in type/annotation expressions (#23611) [ty] hash-cons `UseDefMap` fields (#23283)
Summary
Add validation to detect when a class explicitly inherits from a generic base class with inconsistent type argument ordering compared to other paths in the MRO. This catches errors like:
Test Plan
mdtests and snapshots