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

Conditional expression produces different result than if (w/ callable()) #8265

Open
paravoid opened this issue Jan 9, 2020 · 2 comments
Open
Labels
bug mypy got something wrong priority-2-low topic-ternary-expression a if b else c topic-type-narrowing Conditional type narrowing / binder

Comments

@paravoid
Copy link

paravoid commented Jan 9, 2020

I saw a bunch of different bugs and chatter for both conditional expressions and but I'm unsure if this behavior is reported on any of them. Apologies if this is noise.

This is with mypy 0.761 (with no arguments) on Python 3.7.3, inline:

foo: Union[int, Callable[[Any], int]]
bar: Callable[[Any], int]

foo = lambda _: 0

# case A
# no errors:
if callable(foo):
    bar = foo
else:
    bar = lambda _: foo

# case B
# error: Incompatible return value type (got "Union[int, Callable[[int], int]]", expected "int")
bar = foo if callable(foo) else lambda _: foo

So it seems the behavior differs on whether the if is inline, which I found really surprising.

[Separately, setting foo to 0 also fails -- but on both of those cases, which I suppose would be a limitation, rather than a bug]

@msullivan msullivan added bug mypy got something wrong priority-2-low labels Jan 9, 2020
@msullivan
Copy link
Collaborator

I think the issue in this example, at least, is that since foo is initialized there, it is known to be callable, and the second branch of the else won't be typechecked (since it is treated as unreachable). If you remove the initialization, it will report an error, since type narrowing doesn't affect nested functions (since the variable could be reassigned before they are called).

We don't skip unreachable branches in conditional expressions, though, apparently? Maybe we should.

@JelleZijlstra JelleZijlstra added the topic-type-narrowing Conditional type narrowing / binder label Mar 19, 2022
@AlexWaygood AlexWaygood added the topic-ternary-expression a if b else c label Apr 1, 2022
@glroman
Copy link

glroman commented Jan 9, 2024

Note: this happens in the far more common case of checking between a str and bytes:

    def doit(x: Union[str, bytes]) -> None:
	v = x.decode() if isinstance(x, bytes) else str(x)

pkg/mod.py:3: error: "str" has no attribute "decode"; maybe "encode"? [attr-defined]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong priority-2-low topic-ternary-expression a if b else c topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

No branches or pull requests

5 participants