Skip to content

Commit c518a97

Browse files
committed
fix default and add tests for recursive protocols that are supertypes of object
1 parent 5be6b60 commit c518a97

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

crates/ty_python_semantic/resources/mdtest/protocols.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,6 +2610,48 @@ class E[T: B](Protocol): ...
26102610
x: E[D]
26112611
```
26122612

2613+
### Recursive supertypes of `object`
2614+
2615+
A recursive protocol can be a supertype of `object` (though it is hard to create such a protocol
2616+
without violating the Liskov Substitution Principle, since all protocols are also subtypes of
2617+
`object`):
2618+
2619+
```py
2620+
from typing import Protocol
2621+
from ty_extensions import static_assert, is_subtype_of, is_equivalent_to, is_disjoint_from
2622+
2623+
class HasRepr(Protocol):
2624+
# TODO: we should emit a diagnostic here complaining about a Liskov violation
2625+
# (it incompatibly overrides `__repr__` from `object`, a supertype of `HasRepr`)
2626+
def __repr__(self) -> object: ...
2627+
2628+
class HasReprRecursive(Protocol):
2629+
# TODO: we should emit a diagnostic here complaining about a Liskov violation
2630+
# (it incompatibly overrides `__repr__` from `object`, a supertype of `HasReprRecursive`)
2631+
def __repr__(self) -> "HasReprRecursive": ...
2632+
2633+
class HasReprRecursiveAndFoo(Protocol):
2634+
# TODO: we should emit a diagnostic here complaining about a Liskov violation
2635+
# (it incompatibly overrides `__repr__` from `object`, a supertype of `HasReprRecursiveAndFoo`)
2636+
def __repr__(self) -> "HasReprRecursiveAndFoo": ...
2637+
foo: int
2638+
2639+
static_assert(is_subtype_of(object, HasRepr))
2640+
static_assert(is_subtype_of(HasRepr, object))
2641+
static_assert(is_equivalent_to(object, HasRepr))
2642+
static_assert(not is_disjoint_from(HasRepr, object))
2643+
2644+
static_assert(is_subtype_of(object, HasReprRecursive))
2645+
static_assert(is_subtype_of(HasReprRecursive, object))
2646+
static_assert(is_equivalent_to(object, HasReprRecursive))
2647+
static_assert(not is_disjoint_from(HasReprRecursive, object))
2648+
2649+
static_assert(not is_subtype_of(object, HasReprRecursiveAndFoo))
2650+
static_assert(is_subtype_of(HasReprRecursiveAndFoo, object))
2651+
static_assert(not is_equivalent_to(object, HasReprRecursiveAndFoo))
2652+
static_assert(not is_disjoint_from(HasReprRecursiveAndFoo, object))
2653+
```
2654+
26132655
## Meta-protocols
26142656

26152657
Where `P` is a protocol type, a class object `N` can be said to inhabit the type `type[P]` if:

crates/ty_python_semantic/src/types/instance.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ impl<'db> ProtocolInstanceType<'db> {
513513
}
514514

515515
fn initial<'db>(_db: &'db dyn Db, _value: ProtocolInstanceType<'db>, _: ()) -> bool {
516-
false
516+
true
517517
}
518518

519519
inner(db, self, ())

0 commit comments

Comments
 (0)