Skip to content
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

Incorrect inference of Callable generic typing #5199

Closed
asottile opened this issue Jun 11, 2018 · 2 comments · Fixed by #5699
Closed

Incorrect inference of Callable generic typing #5199

asottile opened this issue Jun 11, 2018 · 2 comments · Fixed by #5699
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-type-variables

Comments

@asottile
Copy link
Contributor

from typing import Callable
from typing import Iterable
from typing import List
from typing import Optional
from typing import TypeVar


class C:
    x: str


T = TypeVar('T')


def f(i: Iterable[T], c: Callable[[T], bool]) -> Optional[T]:
    for x in i:
        if c(x):
            return x
    else:
        return None


def g(l: List[C], x: str) -> Optional[C]:
    return f(l, lambda d: d.x == x)
$ mypy test.py
test.py:24: error: Item "None" of "Optional[C]" has no attribute "x"
$ mypy --version
mypy 0.610

A little bit complicated, though I believe the lambda should be inferenced as Callable[[C], bool] though it appears to instead be inferenced as Callable[[Optional[C]], bool]

A related, less-lambda-y reproduction:

from typing import Callable
from typing import Iterable
from typing import List
from typing import Optional
from typing import TypeVar


class C:
    x: str


T = TypeVar('T')


def f(i: Iterable[T], c: Callable[[T], bool]) -> Optional[T]:
    for x in i:
        if c(x):
            return x
    else:
        return None


def g(l: List[C], x: str) -> Optional[C]:
    def pred(d: C) -> bool:
        return d.x == x

    return f(l, pred)
$ mypy test2.py
test2.py:27: error: Argument 2 to "f" has incompatible type "Callable[[C], bool]"; expected "Callable[[Optional[C]], bool]"
@ilevkivskyi
Copy link
Member

I believe this is a duplicate of #4872. It looks like just another example where mypy inference engine is being to "greedy".

Actually after some thinking it looks like fixing these particular examples might be tricky, so I would like to keep this one open.

@ilevkivskyi ilevkivskyi added bug mypy got something wrong topic-type-variables priority-1-normal false-positive mypy gave an error on correct code labels Jun 12, 2018
@mantognini
Copy link

I'm also interested in a fix for this as I encountered exactly the same issue today. :)

ilevkivskyi added a commit that referenced this issue Oct 2, 2018
Fixes #4872 
Fixes #3876
Fixes #2678 
Fixes #5199 
Fixes #5493 
(It also fixes a bunch of similar issues previously closed as duplicates, except one, see below).

This PR fixes a problems when mypy commits to soon to using outer context for type inference. This is done by:
* Postponing inference to inner (argument) context in situations where type inferred from outer (return) context doesn't satisfy bounds or constraints.
* Adding a special case for situation where optional return is inferred against optional context. In such situation, unwrapping the optional is a better idea in 99% of cases. (Note: this doesn't affect type safety, only gives empirically more reasonable inferred types.)

In general, instead of adding a special case, it would be better to use inner and outer context at the same time, but this a big change (see comment in code), and using the simple special case fixes majority of issues. Among reported issues, only #5311 will stay unfixed.
TV4Fun pushed a commit to TV4Fun/mypy that referenced this issue Oct 4, 2018
Fixes python#4872 
Fixes python#3876
Fixes python#2678 
Fixes python#5199 
Fixes python#5493 
(It also fixes a bunch of similar issues previously closed as duplicates, except one, see below).

This PR fixes a problems when mypy commits to soon to using outer context for type inference. This is done by:
* Postponing inference to inner (argument) context in situations where type inferred from outer (return) context doesn't satisfy bounds or constraints.
* Adding a special case for situation where optional return is inferred against optional context. In such situation, unwrapping the optional is a better idea in 99% of cases. (Note: this doesn't affect type safety, only gives empirically more reasonable inferred types.)

In general, instead of adding a special case, it would be better to use inner and outer context at the same time, but this a big change (see comment in code), and using the simple special case fixes majority of issues. Among reported issues, only python#5311 will stay unfixed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-type-variables
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants