-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[red-knot] Use the right scope when considering class bases (#13766)
Summary --------- PEP 695 Generics introduce a scope inside a class statement's arguments and keywords. ``` class C[T](A[T]): # the T in A[T] is not from the global scope but from a type-param-specfic scope ... ``` When doing inference on the class bases, we currently have been doing base class expression lookups in the global scope. Not an issue without generics (since a scope is only created when generics are present). This change instead makes sure to stop the global scope inference from going into expressions within this sub-scope. Since there is a separate scope, `check_file` and friends will trigger inference on these expressions still. Another change as a part of this is making sure that `ClassType` looks up its bases in the right scope. Test Plan ---------- `cargo test --package red_knot_python_semantic generics` will run the markdown test that previously would panic due to scope lookup issues --------- Co-authored-by: Micha Reiser <[email protected]> Co-authored-by: Carl Meyer <[email protected]>
- Loading branch information
1 parent
e2a30b7
commit 3d0bdb4
Showing
4 changed files
with
89 additions
and
14 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
crates/red_knot_python_semantic/resources/mdtest/generics.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,57 @@ | ||
# PEP 695 Generics | ||
|
||
## Class Declarations | ||
|
||
Basic PEP 695 generics | ||
|
||
```py | ||
class MyBox[T]: | ||
data: T | ||
box_model_number = 695 | ||
def __init__(self, data: T): | ||
self.data = data | ||
|
||
# TODO not error (should be subscriptable) | ||
box: MyBox[int] = MyBox(5) # error: [non-subscriptable] | ||
# TODO error differently (str and int don't unify) | ||
wrong_innards: MyBox[int] = MyBox("five") # error: [non-subscriptable] | ||
# TODO reveal int | ||
reveal_type(box.data) # revealed: @Todo | ||
|
||
reveal_type(MyBox.box_model_number) # revealed: Literal[695] | ||
``` | ||
|
||
## Subclassing | ||
|
||
```py | ||
class MyBox[T]: | ||
data: T | ||
|
||
def __init__(self, data: T): | ||
self.data = data | ||
|
||
# TODO not error on the subscripting | ||
class MySecureBox[T](MyBox[T]): # error: [non-subscriptable] | ||
pass | ||
|
||
secure_box: MySecureBox[int] = MySecureBox(5) | ||
reveal_type(secure_box) # revealed: MySecureBox | ||
# TODO reveal int | ||
reveal_type(secure_box.data) # revealed: @Todo | ||
``` | ||
|
||
## Cyclical class definition | ||
|
||
In type stubs, classes can reference themselves in their base class definitions. For example, in `typeshed`, we have `class str(Sequence[str]): ...`. | ||
|
||
This should hold true even with generics at play. | ||
|
||
```py path=a.pyi | ||
class Seq[T]: | ||
pass | ||
|
||
# TODO not error on the subscripting | ||
class S[T](Seq[S]): # error: [non-subscriptable] | ||
pass | ||
reveal_type(S) # revealed: Literal[S] | ||
``` |
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
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
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