-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Polymorphic inference: support for parameter specifications and lambdas #15837
Changes from 1 commit
9b4eac8
1959136
e796c6a
177b312
420f60d
d7cfbe9
d4c9146
0af630f
c5c1b76
582a4de
4f8afce
2d21032
59963c4
72da8f5
7a87692
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2713,6 +2713,7 @@ reveal_type(func(1)) # N: Revealed type is "builtins.int" | |
[builtins fixtures/tuple.pyi] | ||
|
||
[case testGenericLambdaGenericMethodNoCrash] | ||
# flags: --new-type-inference | ||
from typing import TypeVar, Union, Callable, Generic | ||
|
||
S = TypeVar("S") | ||
|
@@ -2723,7 +2724,7 @@ def f(x: Callable[[G[T]], int]) -> T: ... | |
class G(Generic[T]): | ||
def g(self, x: S) -> Union[S, T]: ... | ||
|
||
f(lambda x: x.g(0)) # E: Cannot infer type argument 1 of "f" | ||
f(lambda x: x.g(0)) # E: Incompatible return value type (got "Union[int, T]", expected "int") | ||
|
||
[case testDictStarInference] | ||
class B: ... | ||
|
@@ -3036,6 +3037,34 @@ reveal_type(dec2(id1)) # N: Revealed type is "def [UC <: __main__.C] (UC`5) -> | |
reveal_type(dec2(id2)) # N: Revealed type is "def (<nothing>) -> builtins.list[<nothing>]" \ | ||
# E: Argument 1 to "dec2" has incompatible type "Callable[[V], V]"; expected "Callable[[<nothing>], <nothing>]" | ||
|
||
[case testInferenceAgainstGenericLambdas] | ||
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. It's amazing how many new cases we can now handle! |
||
# flags: --new-type-inference | ||
from typing import TypeVar, Callable, List | ||
|
||
S = TypeVar('S') | ||
T = TypeVar('T') | ||
|
||
def dec1(f: Callable[[T], T]) -> Callable[[T], List[T]]: | ||
... | ||
def dec2(f: Callable[[S], T]) -> Callable[[S], List[T]]: | ||
... | ||
def dec3(f: Callable[[List[S]], T]) -> Callable[[S], T]: | ||
... | ||
def dec4(f: Callable[[S], List[T]]) -> Callable[[S], T]: | ||
... | ||
def dec5(f: Callable[[int], T]) -> Callable[[int], List[T]]: | ||
def g(x: int) -> List[T]: | ||
return [f(x)] * x | ||
return g | ||
Comment on lines
+3058
to
+3060
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. Is this function body particularly important? 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 thought it would be good to have at least few tests with bound type variables around (just in case), plus this is a good reminder/hint for a reader about why the test behaves as it does (see e.g. I added body for |
||
|
||
reveal_type(dec1(lambda x: x)) # N: Revealed type is "def [T] (T`2) -> builtins.list[T`2]" | ||
reveal_type(dec2(lambda x: x)) # N: Revealed type is "def [S] (S`3) -> builtins.list[S`3]" | ||
reveal_type(dec3(lambda x: x[0])) # N: Revealed type is "def [S] (S`5) -> S`5" | ||
reveal_type(dec4(lambda x: [x])) # N: Revealed type is "def [S] (S`7) -> S`7" | ||
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. Could you include tests that show incorrect usage of 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 added the test cases, but note that |
||
reveal_type(dec1(lambda x: 1)) # N: Revealed type is "def (builtins.int) -> builtins.list[builtins.int]" | ||
reveal_type(dec5(lambda x: x)) # N: Revealed type is "def (builtins.int) -> builtins.list[builtins.int]" | ||
[builtins fixtures/list.pyi] | ||
|
||
[case testInferenceAgainstGenericParamSpecBasicInList] | ||
# flags: --new-type-inference | ||
from typing import TypeVar, Callable, List, Tuple | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1375,19 +1375,21 @@ class B: pass | |
[builtins fixtures/list.pyi] | ||
|
||
[case testUninferableLambda] | ||
# flags: --new-type-inference | ||
from typing import TypeVar, Callable | ||
X = TypeVar('X') | ||
def f(x: Callable[[X], X]) -> X: pass | ||
y = f(lambda x: x) # E: Cannot infer type argument 1 of "f" | ||
y = f(lambda x: x) # E: Need type annotation for "y" | ||
|
||
[case testUninferableLambdaWithTypeError] | ||
# flags: --new-type-inference | ||
from typing import TypeVar, Callable | ||
X = TypeVar('X') | ||
def f(x: Callable[[X], X], y: str) -> X: pass | ||
y = f(lambda x: x, 1) # Fail | ||
[out] | ||
main:4: error: Cannot infer type argument 1 of "f" | ||
main:4: error: Argument 2 to "f" has incompatible type "int"; expected "str" | ||
main:5: error: Need type annotation for "y" | ||
main:5: error: Argument 2 to "f" has incompatible type "int"; expected "str" | ||
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. Maybe use the comment-style for test outputs? 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. Yes, I updated the test. |
||
|
||
[case testInferLambdaNone] | ||
# flags: --no-strict-optional | ||
|
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.
I think
extra_vars
could be a set maybe? That would mean an IMO simpler comprehension.I'm also not sure why
ctx.variables
is guaranteed to not include these new variables.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.
IIRC I use this logic with lists for variables here (and in few other places) to have stable order. Otherwise tests will randomly fail on
reveal_type()
(and it is generally good to have predictable stable order for comparison purposes).