Skip to content

mypy reports unexpected errors in the statement "result = list(map(abspath, x))" #2389

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

Closed
eikooo opened this issue Nov 2, 2016 · 4 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-type-variables

Comments

@eikooo
Copy link

eikooo commented Nov 2, 2016

Hi,

I've a function in my code, where mypy reports errors, that I don't understand. A simple example:

from os.path import abspath

def test1( x : List[str]) -> List[str] :
    # this is not working
    result = list(map(abspath, x)) # Line 5
    return result                  # Line 6

def test2( x : List[str]) -> List[str] :
    # this is working
    return list(map(abspath, x))

This produces the following output (mypy 0.4.5):

TypeHints.py: note: In function "test1":
TypeHints.py:5: error: Argument 1 to "map" has incompatible type Callable[[AnyStr], AnyStr]; expected Callable[[str], AnyStr]
TypeHints.py:6: error: Incompatible return value type (got List[AnyStr], expected List[str])

Am I doing something wrong? Or is this a problem of mypy?

@rwbarton
Copy link
Contributor

rwbarton commented Nov 2, 2016

I think it's a weakness of mypy's type inference. abspath has type

def abspath(path: AnyStr) -> AnyStr: ...

where AnyStr is a type variable that can be either str or bytes. In test1, mypy should determine from the type of x that it should pick str. But it's not smart enough to do this. In test2, the fact that list(map(abspath, x)) is being returned as a List[str] is enough for mypy to figure out what to do.

You can make your test1 work by adding a type annotation to result:

def test1( x : List[str]) -> List[str] :
    result = list(map(abspath, x)) # type: List[str]
    ...

@gvanrossum
Copy link
Member

At first I thought this is a general problem due to the way contexts don't reach back into expressions, but it really does look like the line result = list(map(abspath, x)) should infer type List[str] for result, but doesn't. I'll qualify it as a bug; I think it's not all that important because it looks pretty rare and there's an easy workaround (adding the annotation).

@sterliakov
Copy link
Collaborator

Annotating does not help in all cases, consider:

from typing import TypeVar
from collections.abc import Iterable

a = TypeVar("a")
b = TypeVar("b")

def snd(x: tuple[a, b]) -> b:
    """Return the second element of a pair."""
    return x[1]

xs: Iterable[tuple[str, int]]
x: list[int] = list(map(snd, xs))  # E: Argument 1 to "map" has incompatible type "Callable[[tuple[a, b]], b]"; expected "Callable[[tuple[str, int]], b]"  [arg-type]

Playground here, reporting after this SO question.

@ilevkivskyi
Copy link
Member

Both original example and the example by @sterliakov now work correctly (polymorphic inference strikes again LOL).

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

No branches or pull requests

7 participants