[ty] Add support for PEP 800 (#20084)

This commit is contained in:
Alex Waygood
2025-08-25 19:39:05 +01:00
committed by GitHub
parent 33c5f6f4f8
commit ecf3c4ca11
9 changed files with 275 additions and 271 deletions

View File

@@ -103,7 +103,7 @@ class E( # error: [instance-layout-conflict]
): ...
```
## A single "solid base"
## A single "disjoint base"
```py
class A:
@@ -152,14 +152,15 @@ class Baz(Foo, Bar): ... # fine
<!-- snapshot-diagnostics -->
Certain classes implemented in C extensions also have an extended instance memory layout, in the
same way as classes that define non-empty `__slots__`. (CPython internally calls all such classes
with a unique instance memory layout "solid bases", and we also borrow this term.) There is
currently no generalized way for ty to detect such a C-extension class, as there is currently no way
of expressing the fact that a class is a solid base in a stub file. However, ty special-cases
certain builtin classes in order to detect that attempting to combine them in a single MRO would
fail:
same way as classes that define non-empty `__slots__`. CPython internally calls all such classes
with a unique instance memory layout "solid bases", but [PEP 800](https://peps.python.org/pep-0800/)
calls these classes "disjoint bases", and this is the term we generally use. The `@disjoint_base`
decorator introduced by this PEP provides a generalised way for type checkers to identify such
classes.
```py
from typing_extensions import disjoint_base
# fmt: off
class A( # error: [instance-layout-conflict]
@@ -183,6 +184,17 @@ class E( # error: [instance-layout-conflict]
class F(int, str, bytes, bytearray): ... # error: [instance-layout-conflict]
@disjoint_base
class G: ...
@disjoint_base
class H: ...
class I( # error: [instance-layout-conflict]
G,
H
): ...
# fmt: on
```
@@ -193,9 +205,9 @@ We avoid emitting an `instance-layout-conflict` diagnostic for this class defini
class Foo(range, str): ... # error: [subclass-of-final-class]
```
## Multiple "solid bases" where one is a subclass of the other
## Multiple "disjoint bases" where one is a subclass of the other
A class is permitted to multiple-inherit from multiple solid bases if one is a subclass of the
A class is permitted to multiple-inherit from multiple disjoint bases if one is a subclass of the
other:
```py