-
-
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
'Cannot call function of unknown type' for sequence of callables with different signatures #9527
Comments
Note, you can get your code to type check by putting the annotation on the same line:
|
Can also get it to type check by using a calls_different_signatures: List[Tuple[Callable[..., int], Tuple[int, ...]]]
calls_different_signatures = [
(identity, (1,)),
(add, (1, 2)),
] Which I think does suggest a variance issue? This type checks as well (still using Sequence for the type but defining the data structure with a list rather than a tuple.) calls_different_signatures: Sequence[Tuple[Callable[..., int], Tuple[int, ...]]]
calls_different_signatures = [
(identity, (1,)),
(add, (1, 2)),
] |
I think it's not as much a variance issue, as it is that the invariance of list serendipitously helps you out here. When you assign to a variable (and the annotation is on a different line [1]), mypy attempts to infer the most specific type possible that is compatible with the annotation. That's why for the following you see such a verbose type on line 18:
Now the reveal_type on line 19 (which also applies to your loop). Here mypy is performing what it calls a join, where it tries to describe multiple types as a single type. You see it comes up with Why does it work for list? It's because mypy narrows to the specific type that's compatible with the annotation. That's how variance happily affects you here. I think the most actionable thing here is mypy doing a better job of listening to your annotation. See [1] [1] The difference in behaviour when the annotation is on a different line is surprising and has downsides, so we've resolved to change it (see #2008 and a recent discussion on typing-sig). It's still a little unclear what the ideal behaviour is for cases like yours (generics that involve Any), but thanks to your report, we'll take it into account when figuring out what the right tradeoffs are :-) |
Thanks @hauntsaninja that's a very helpful explanation! Happy to close this if it doesn't seem like a bug. |
A similar phenomenon occurs with dispatcher: dict[
typing.Union[typing.Type[list], typing.Type[str], typing.Type[int]],
typing.Callable[
[
typing.Union[list, int, str],
str,
],
dict[str, list],
],
] = {
list: list_handling_fun,
int: int_handling_fun,
str: str_handling_fun,
} mypy tells me that
|
I think your issue might be different? At least, it looks like |
sorry, turned it upside down in my head. feel free to moderate my comment away :) |
I ran into this or a similar bug by constructing a tuple from typed items like in this gist - could someone check whether this is a duplicate or it's its own thing? TIA! |
It's a duplicate |
Bug Report
When working with sequences of callables, if all callables in the sequence do not have the same signature mypy will raise false positives when trying to access and call the callables.
To Reproduce
Trying to fix this with annotations results in what may be a more revealing error?
Expected Behavior
I'd expect this to type check.
I'm not sure if it might be a contravariant vs. covariant thing? That is, does this issue stem from the question over whether the function is a
Callable[[int], int]
or aCallable[..., int]
when it comes out of the sequence?Actual Behavior
Mypy raises an error when attempting to call functions in
calls_different_signatures
,Cannot call function of unknown type
in the first example,Incompatible types in assignment (expression has type "function", variable has type "Callable[..., int]")
in the second.Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: