-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[red-knot] Implement disjointness for Instance types where the underl…
…ying class is `@final` (#15539) ## Summary Closes #15508 For any two instance types `T` and `S`, we know they are disjoint if either `T` is final and `T` is not a subclass of `S` or `S` is final and `S` is not a subclass of `T`. Correspondingly, for any two types `type[T]` and `S` where `S` is an instance type, `type[T]` can be said to be disjoint from `S` if `S` is disjoint from `U`, where `U` is the type that represents all instances of `T`'s metaclass. And a heterogeneous tuple type can be said to be disjoint from an instance type if the instance type is disjoint from `tuple` (a type representing all instances of the `tuple` class at runtime). ## Test Plan - A new mdtest added. Most of our `is_disjoint_from()` tests are not written as mdtests just yet, but it's pretty hard to test some of these edge cases from a Rust unit test! - Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p red_knot_python_semantic -- --ignored types::property_tests::stable` --------- Co-authored-by: Carl Meyer <carl@astral.sh>
- Loading branch information
1 parent
e84c824
commit 3950b00
Showing
3 changed files
with
63 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...s/red_knot_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Tests for disjointness | ||
|
||
If two types can be disjoint, it means that it is known that no possible runtime object could ever | ||
inhabit both types simultaneously. | ||
|
||
TODO: Most of our disjointness tests are still Rust tests; they should be moved to this file. | ||
|
||
## Instance types versus `type[T]` types | ||
|
||
An instance type is disjoint from a `type[T]` type if the instance type is `@final` and the class of | ||
the instance type is not a subclass of `T`'s metaclass. | ||
|
||
```py | ||
from typing import final | ||
from knot_extensions import is_disjoint_from, static_assert | ||
|
||
@final | ||
class Foo: ... | ||
|
||
static_assert(is_disjoint_from(Foo, type[int])) | ||
static_assert(is_disjoint_from(type[object], Foo)) | ||
static_assert(is_disjoint_from(type[dict], Foo)) | ||
|
||
# Instance types can be disjoint from `type[]` types | ||
# even if the instance type is a subtype of `type` | ||
|
||
@final | ||
class Meta1(type): ... | ||
|
||
class UsesMeta1(metaclass=Meta1): ... | ||
|
||
static_assert(not is_disjoint_from(Meta1, type[UsesMeta1])) | ||
|
||
class Meta2(type): ... | ||
class UsesMeta2(metaclass=Meta2): ... | ||
|
||
static_assert(not is_disjoint_from(Meta2, type[UsesMeta2])) | ||
static_assert(is_disjoint_from(Meta1, type[UsesMeta2])) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters