Skip to content

Type inferred from assertion somehow gets lost in lambda expression #4973

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
Wiezzel opened this issue Apr 26, 2018 · 4 comments
Closed

Type inferred from assertion somehow gets lost in lambda expression #4973

Wiezzel opened this issue Apr 26, 2018 · 4 comments
Labels
false-positive mypy gave an error on correct code feature priority-1-normal

Comments

@Wiezzel
Copy link

Wiezzel commented Apr 26, 2018

This works:

class A:
    pass

class B(A):
    foo: str

def bar(a: A):
    assert isinstance(a, B)
    return a.foo

This gives an error:

class A:
    pass

class B(A):
    foo: str

def bar(a: A):
    assert isinstance(a, B)
    return map(lambda _: a.foo, [])

Error message:

11: error: "A" has no attribute "foo"

Mypy version: 0.590
Python version: 3.6.3

I believe the second example should not raise any errors when checked by mypy.
The code obviously makes no sense. I prepared the examples in order to explain the issue.

@ilevkivskyi
Copy link
Member

Type restrictions in mypy don't propagate to nested functions, see e.g. #2608, and lambda is a nested function. I think however this is not a duplicate since this use case is unrelated to None (also since lambdas are constrained to a single expression and a typically for immediate use, it feels safer to propagate the type restrictions).

@ikelos
Copy link

ikelos commented Jul 22, 2018

I have a similar test case, that uses None, but I believe it's actually the type restriction propagation through the lambda that's the issue here:

Mypy version: 0.620
Python version: 3.6.6

import typing

def method_good(children: typing.Optional[typing.List[int]], 
                sort_key: typing.Optional[typing.Callable] = None):
    if children is not None:
        if sort_key is not None:
            key_func = lambda x: sort_key(x)
            children = sorted(children, key = key_func)
    return children

def method_bad(children: typing.Optional[typing.List[int]], 
               sort_key: typing.Optional[typing.Callable] = None):
    if children is not None:
        if sort_key is not None:
            children = sorted(children, key = lambda x: sort_key(x))
    return children

Only method_bad raises an error. The workaround is easy, but confusing that it's necessary. If this belongs in #2608 or is a new issue, let me know and I can post this there instead...

@alcides
Copy link

alcides commented Jan 28, 2022

This is something that is happening a lot with me, in which I am writing interpreters for tree-like structures and need lambdas to create laziness in its evaluation. Having to access fields outside lambdas triples the number of lines of the files, and becomes more unreadable.

@hauntsaninja
Copy link
Collaborator

This will usually be fixed by the same heuristics that were good enough for #2608

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive mypy gave an error on correct code feature priority-1-normal
Projects
None yet
Development

No branches or pull requests

6 participants