[ty]: Consider a class with a dynamic element in its MRO assignable to any subtype of type (#18205)

This commit is contained in:
Felix Scherz 2025-05-19 21:30:30 +02:00 committed by GitHub
parent 4fad15805b
commit fb589730ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 54 additions and 0 deletions

View file

@ -62,6 +62,20 @@ def foo(
reveal_type(i) # revealed: BaseException
```
We do not emit an `invalid-exception-caught` if a class is caught that has `Any` or `Unknown` in its
MRO, as the dynamic element in the MRO could materialize to some subclass of `BaseException`:
```py
from compat import BASE_EXCEPTION_CLASS # error: [unresolved-import] "Cannot resolve imported module `compat`"
class Error(BASE_EXCEPTION_CLASS): ...
try:
...
except Error as err:
...
```
## Invalid exception handlers
```py

View file

@ -204,6 +204,34 @@ static_assert(is_assignable_to(type[AnyMeta], type[object]))
static_assert(is_assignable_to(type[AnyMeta], type[Any]))
```
## Class-literals that inherit from `Any`
Class-literal types that inherit from `Any` are assignable to any type `T` where `T` is assignable
to `type`:
```py
from typing import Any
from ty_extensions import is_assignable_to, static_assert, TypeOf
def test(x: Any):
class Foo(x): ...
class Bar(Any): ...
static_assert(is_assignable_to(TypeOf[Foo], Any))
static_assert(is_assignable_to(TypeOf[Foo], type))
static_assert(is_assignable_to(TypeOf[Foo], type[int]))
static_assert(is_assignable_to(TypeOf[Foo], type[Any]))
static_assert(is_assignable_to(TypeOf[Bar], Any))
static_assert(is_assignable_to(TypeOf[Bar], type))
static_assert(is_assignable_to(TypeOf[Bar], type[int]))
static_assert(is_assignable_to(TypeOf[Bar], type[Any]))
static_assert(not is_assignable_to(TypeOf[Foo], int))
static_assert(not is_assignable_to(TypeOf[Bar], int))
```
This is because the `Any` element in the MRO could materialize to any subtype of `type`.
## Heterogeneous tuple types
```py