-
Notifications
You must be signed in to change notification settings - Fork 2.4k
[ty] Gradual isinstance narrowing for generic classes
#27308
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 28 commits
cdffb1d
a60d1af
fcd8fee
e885df8
16a8f4e
a894808
5af7d74
87178c7
b16cab1
be18ab1
a1c03cc
3a1e502
8ee95ec
877f14e
6443890
4a44769
f11919b
1d0df1d
ddc396e
cce6a54
4419b66
ba249b3
7db043c
6a471b9
98e6033
ee1801c
4575f6e
3de2e88
68d719c
0a16895
e7d1683
bdd2830
2578b89
6c4628c
885be27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,7 +54,15 @@ def f(x: object): | |
|
|
||
| ## Calling narrowed callables | ||
|
|
||
| The narrowed type `Top[Callable[..., object]]` represents the set of all possible callable types | ||
| ### Strict generic narrowing mode | ||
|
|
||
| ```toml | ||
| [analysis] | ||
| strict-generic-narrowing = true | ||
| ``` | ||
|
|
||
| In strict generic narrowing mode, an `isinstance(.., Callable)` check intersects the type with | ||
| `Top[Callable[..., object]]`. This type represents the set of all possible callable types | ||
| (including, e.g., functions that take no arguments and functions that require arguments). While such | ||
| objects *are* callable (they pass `callable()`), no specific set of arguments can be guaranteed to | ||
| be valid. | ||
|
|
@@ -80,6 +88,28 @@ def resolve(value: str): | |
| reveal_type(value()) # revealed: object | ||
| ``` | ||
|
|
||
| ### Gradual generic narrowing mode | ||
|
|
||
| ```toml | ||
| [analysis] | ||
| strict-generic-narrowing = false | ||
| ``` | ||
|
|
||
| In gradual generic narrowing mode, an `isinstance(.., Callable)` check narrows to a gradual | ||
| callable. Its parameters accept arbitrary arguments, and its return type is `Unknown`: | ||
|
|
||
| ```py | ||
| from typing import Callable | ||
|
|
||
| def call_with_args(y: object): | ||
| if isinstance(y, Callable): | ||
|
Contributor
Author
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. Note that this means that our default behavior here for
Contributor
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. I don't remember details of that discussion. I think this is probably acceptable for now, though I think ideally these would have the same semantics. I guess in order to do that we would need to special-case
Contributor
Author
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. Previous discussion here: #26797 (comment). I will open a ticket to address this as a follow-up.
Contributor
Author
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. |
||
| reveal_type(y) # revealed: (...) -> Unknown | ||
|
|
||
| reveal_type(y()) # revealed: Unknown | ||
| reveal_type(y(1, "foo")) # revealed: Unknown | ||
| reveal_type(y(1, "foo", keyword_arg="bar")) # revealed: Unknown | ||
| ``` | ||
|
|
||
| ## Narrowing with named expressions (walrus operator) | ||
|
|
||
| When `callable()` is used with a named expression, the target of the named expression should be | ||
|
|
@@ -139,9 +169,14 @@ import collections.abc | |
|
|
||
| def f(x: object): | ||
| if isinstance(x, typing.Callable): | ||
| reveal_type(x) # revealed: Top[(...) -> object] | ||
| reveal_type(x) # revealed: (...) -> Unknown | ||
| else: | ||
| reveal_type(x) # revealed: ~Top[(...) -> object] | ||
|
|
||
| if isinstance(x, collections.abc.Callable): | ||
| reveal_type(x) # revealed: Top[(...) -> object] | ||
| reveal_type(x) # revealed: (...) -> Unknown | ||
| else: | ||
| reveal_type(x) # revealed: ~Top[(...) -> object] | ||
| ``` | ||
|
|
||
| ## `Callable` special-form identity | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.