-
Couldn't load subscription status.
- Fork 1.6k
[red-knot] Allow explicit specialization of generic classes #17023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 71 commits
3be8257
4c76cb5
8048604
fe76d56
4346e7d
2380ade
178ee89
feb1ea9
3c1ad79
59430b6
77ffa80
6f86720
cf81967
6615df1
b2f5a2a
590680c
e6b7d40
debd60a
aa391fd
e57e62e
3df79cc
5b08e93
82e810f
a3d7253
15682d5
9e07efe
fb63c22
3459056
71d425e
233e938
9785202
c86af50
aa00895
d99d1d7
58f0995
42fd54a
6bd69f1
1d6a917
37692f1
3869dc6
0c1745b
8bdd9e2
39244dd
5694b3d
123b920
9e1767f
23ac0b6
6b27947
669aa21
575998e
f02fefa
cc3a3df
18af8b6
af52fd1
d3fd822
aa64990
e41f889
7eb7c28
adb4aba
968e637
fd7914a
7ebda98
6257e89
78cd92a
530e2bc
637fd48
ec5a588
27cb208
ea12548
c376dad
311dc59
5fc8425
7aaeb47
43554e2
0d656db
7c3405a
6593d90
7ca6a60
dea493e
048bb8b
06859fa
d138405
0997eca
6ab1b90
bcb147f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,10 +196,14 @@ reveal_type(c.attr) # revealed: Unknown | |
|
|
||
| ## Behind the scenes | ||
|
|
||
| > TODO: This test is currently disabled pending | ||
| > [an upstream Salsa fix](https://github.com/salsa-rs/salsa/pull/741). Once that has been merged, | ||
| > re-enable this test by changing the language codes below back to `py`. | ||
|
Comment on lines
+199
to
+201
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This depends on salsa-rs/salsa#741 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to unblock this PR on the salsa fix, the other thing we can do is temporarily revert the change that makes mdtests reuse the same Salsa db, and live with slow mdtests until the Salsa fix lands. |
||
|
|
||
| In this section, we trace through some of the steps that make properties work. We start with a | ||
| simple class `C` and a property `attr`: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| class C: | ||
| def __init__(self): | ||
| self._attr: int = 0 | ||
|
|
@@ -216,7 +220,7 @@ class C: | |
| Next, we create an instance of `C`. As we have seen above, accessing `attr` on the instance will | ||
| return an `int`: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| c = C() | ||
|
|
||
| reveal_type(c.attr) # revealed: int | ||
|
|
@@ -226,7 +230,7 @@ Behind the scenes, when we write `c.attr`, the first thing that happens is that | |
| up the symbol `attr` on the meta-type of `c`, i.e. the class `C`. We can emulate this static lookup | ||
| using `inspect.getattr_static`, to see that `attr` is actually an instance of the `property` class: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| from inspect import getattr_static | ||
|
|
||
| attr_property = getattr_static(C, "attr") | ||
|
|
@@ -237,7 +241,7 @@ The `property` class has a `__get__` method, which makes it a descriptor. It als | |
| method, which means that it is a *data* descriptor (if there is no setter, `__set__` is still | ||
| available but yields an `AttributeError` at runtime). | ||
|
|
||
| ```py | ||
| ```ignore | ||
| reveal_type(type(attr_property).__get__) # revealed: <wrapper-descriptor `__get__` of `property` objects> | ||
| reveal_type(type(attr_property).__set__) # revealed: <wrapper-descriptor `__set__` of `property` objects> | ||
| ``` | ||
|
|
@@ -246,22 +250,22 @@ When we access `c.attr`, the `__get__` method of the `property` class is called, | |
| property object itself as the first argument, and the class instance `c` as the second argument. The | ||
| third argument is the "owner" which can be set to `None` or to `C` in this case: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| reveal_type(type(attr_property).__get__(attr_property, c, C)) # revealed: int | ||
| reveal_type(type(attr_property).__get__(attr_property, c, None)) # revealed: int | ||
| ``` | ||
|
|
||
| Alternatively, the above can also be written as a method call: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| reveal_type(attr_property.__get__(c, C)) # revealed: int | ||
| ``` | ||
|
|
||
| When we access `attr` on the class itself, the descriptor protocol is also invoked, but the instance | ||
| argument is set to `None`. When `instance` is `None`, the call to `property.__get__` returns the | ||
| property instance itself. So the following expressions are all equivalent | ||
|
|
||
| ```py | ||
| ```ignore | ||
| reveal_type(attr_property) # revealed: property | ||
| reveal_type(C.attr) # revealed: property | ||
| reveal_type(attr_property.__get__(None, C)) # revealed: property | ||
|
|
@@ -271,7 +275,7 @@ reveal_type(type(attr_property).__get__(attr_property, None, C)) # revealed: pr | |
| When we set the property using `c.attr = "a"`, the `__set__` method of the property class is called. | ||
| This attribute access desugars to | ||
|
|
||
| ```py | ||
| ```ignore | ||
| type(attr_property).__set__(attr_property, c, "a") | ||
|
|
||
| # error: [call-non-callable] "Call of wrapper descriptor `property.__set__` failed: calling the setter failed" | ||
|
|
@@ -280,7 +284,7 @@ type(attr_property).__set__(attr_property, c, 1) | |
|
|
||
| which is also equivalent to the following expressions: | ||
|
|
||
| ```py | ||
| ```ignore | ||
| attr_property.__set__(c, "a") | ||
| # error: [call-non-callable] | ||
| attr_property.__set__(c, 1) | ||
|
|
@@ -293,7 +297,7 @@ C.attr.__set__(c, 1) | |
| Properties also have `fget` and `fset` attributes that can be used to retrieve the original getter | ||
| and setter functions, respectively. | ||
|
|
||
| ```py | ||
| ```ignore | ||
| reveal_type(attr_property.fget) # revealed: Literal[attr] | ||
| reveal_type(attr_property.fget(c)) # revealed: int | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diagnostics look like this because I'm reusing the call binding mechanism to match parameters and check types. It would be nice for this diagnostic to talk about type parameters, but would prefer to do that as a follow-on.