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

(🐞) reveal_type on a lambda parameter from an overloaded higher order function shows two results #11953

Open
KotlinIsland opened this issue Jan 10, 2022 · 4 comments · May be fixed by #12729
Labels
bug mypy got something wrong topic-overloads topic-reveal-type reveal_type() and reveal_locals()

Comments

@KotlinIsland
Copy link
Contributor

KotlinIsland commented Jan 10, 2022

Here the type of value is an non-inferred int, and there is only one usage of reveal_type, yet mypy is outputting two results (one of which is incorrect)

reveal_locals() shows two entries for value, but one being None not Any.

from typing import overload, Callable

@overload
def bar() -> None: ...
@overload
def bar(fn: Callable[[int], object]) -> None: ...

def bar(fn: object=1) -> None: ...
    

bar(lambda value: reveal_type(value))
bar(lambda value: reveal_locals())
main.py:11: note: Revealed type is "Any"
main.py:11: note: Revealed type is "builtins.int"
main.py:12: note: Revealed local types are:
main.py:12: note:     value: None
main.py:12: note:     value: builtins.int
Success: no issues found in 1 source file

Without removing duplicate messages you get this:

test.py:12: note: Revealed local types are:
test.py:12: note:     value: None
test.py:12: note: Revealed local types are:
test.py:12: note:     value: builtings.int
@KotlinIsland KotlinIsland added the bug mypy got something wrong label Jan 10, 2022
@KotlinIsland KotlinIsland changed the title reveal_type on a lambda parameter shows two results reveal_type on a lambda parameter from an overloaded higher order function shows two results Jan 10, 2022
@KotlinIsland KotlinIsland changed the title reveal_type on a lambda parameter from an overloaded higher order function shows two results (🐞) reveal_type on a lambda parameter from an overloaded higher order function shows two results Mar 4, 2022
@AlexWaygood AlexWaygood added the topic-reveal-type reveal_type() and reveal_locals() label Mar 25, 2022
@septatrix
Copy link
Contributor

septatrix commented May 4, 2022

For some reason reassigning the variable to another name suppresses this behaviour?!

def foobar(data: int | str) -> None:
    reveal_type(data)
    if isinstance(data, int):
        reveal_type(data)
        data2 = data
        filter(lambda element: element == reveal_type(data), [])
        filter(lambda element: element == reveal_type(data2), [])
lambda_confusion.py:2: note: Revealed type is "Union[builtins.int, builtins.str]"
lambda_confusion.py:4: note: Revealed type is "builtins.int"
lambda_confusion.py:6: note: Revealed type is "builtins.int"
lambda_confusion.py:6: note: Revealed type is "Union[builtins.int, builtins.str]"
lambda_confusion.py:7: note: Revealed type is "builtins.int"

PS: And when adding a cast it obviously complaints about a redundant cast so the reassignment actually seems to be the easiest workaround (apart from a strong type: ignore)

@KotlinIsland
Copy link
Contributor Author

@septatrix Strange, but whats happening here is that data is only locally narrowed (from the isinstance), so when assigning to data2 it's inferring the narrowed type, but when revealing within the lambda, mypy doesn't know that the lambda is executed immediatley, so it has to assume that data could be reassigned back to a str.

I think this is probably a similar but separate issue.

@KotlinIsland
Copy link
Contributor Author

KotlinIsland commented May 4, 2022

@AlexWaygood can you add topic-overloads , the reveal type is behaving strange here due to a deeper issue with the overload.

@KotlinIsland
Copy link
Contributor Author

KotlinIsland commented May 5, 2022

From what I can tell, this is caused by mypy.checkexpr.ExpressionChecker.check_overload_call which first executes:

arg_types = self.infer_arg_types_in_empty_context(args)

Which is accepting the body of the lambda without knowing the types of anything which causes all the types to be Any.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-overloads topic-reveal-type reveal_type() and reveal_locals()
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants