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

type checking on boolean expressions #1871

Closed
TadLeonard opened this issue Jul 15, 2016 · 14 comments
Closed

type checking on boolean expressions #1871

TadLeonard opened this issue Jul 15, 2016 · 14 comments
Assignees

Comments

@TadLeonard
Copy link
Contributor

TadLeonard commented Jul 15, 2016

I came across this while reading Daniel Moisset's impression of mypy. He mentions satisfying mypy by wrapping a boolean return expression in bool(), which I think is unnecessary. Below is a simple example that mypy fails on with Incompatible return value type (got "Union[str, bool]", expected "bool"). Note that the return expression is of the form <expression> and <comparison> or <comparison>.

def bool_expr_test(line: str) -> bool:
    return line and line[0] == '"' or line[0] == "'"

Tested on 64c0acd and 0.4.3 (from pip).

@TadLeonard TadLeonard changed the title type checking on boolean expression with str type checking on and expression Jul 15, 2016
@TadLeonard TadLeonard changed the title type checking on and expression type checking on boolean expressions Jul 15, 2016
@gvanrossum
Copy link
Member

gvanrossum commented Jul 15, 2016 via email

@gvanrossum
Copy link
Member

However, 'line and True' does not always return bool. If line is '' it returns that.

@rwbarton
Copy link
Contributor

Also see #1477 for the first example. The remaining examples are all correct as @gvanrossum noted (line could be '' or 0).

@TadLeonard
Copy link
Contributor Author

Ah, thanks. Removed simpler line and examples from the ticket. I thought I knew Python, but I guess I usually use <expr> or <expr> as assignment and return expressions. Never thought to use <expr> and <expr>.

@gvanrossum
Copy link
Member

There's an interesting symmetry though -- in general both <expr> or <expr> and <expr> or <expr> can return the type of either the first or
the second expression. It's mostly when you combine them that interesting
and wonderful things happen. You can probably construct an example using
(<expr> or <expr>) and <expr> too. :-)

@ddfisher
Copy link
Collaborator

This will be fixed by #1751 (which was partially implemented by #1828).

@ddfisher ddfisher added this to the 0.4.x milestone Jul 21, 2016
@ddfisher ddfisher self-assigned this Jul 21, 2016
@ddfisher
Copy link
Collaborator

Actually, I think #1751 isn't sufficient to fix this. It looks like we'll need #1698.

@gvanrossum
Copy link
Member

Here's another example I ran into:

mypy/mypy/main.py

Lines 342 to 343 in c528638

dir, mod = os.path.split(arg)
mod = strip_py(mod) or mod

mypy/main.py:343: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str")

The error is misguided: while strip_py(mod) indeed returns Optional[str], the or mod turns the None into a str and hence the type of strip_py(mod) or mod is in fact str.

@ddfisher
Copy link
Collaborator

It's odd that that doesn't work, because we actually have an explicit test for that behavior.

@gvanrossum
Copy link
Member

gvanrossum commented Jul 22, 2016

The test has a context that may affect it. This definitely gives an error
with strict optional:

def f(s: str) -> Optional[str]: pass
x = ''
x = f(x) or x

@rwbarton
Copy link
Contributor

Oh, the difference is because the logic for this case goes through the type binder, which only stores information about the types of expressions like x[i].a, not expressions like f(x). (It's originally intended for handling things like if isinstance(x[i].a, C): ... x[i].a ..., where there are two occurrences of the expression x[i].a. We assume that x[i].a will not change type in ways that are invisible to the binder, but we don't assume that about function calls like f(x).)

@gvanrossum
Copy link
Member

gvanrossum commented Jul 22, 2016 via email

@dmoisset
Copy link
Contributor

dmoisset commented Aug 5, 2016

Both these examples (bool_expr_test on the ticket description, and the later one posted by @gvanrossum ) seem to work ok and fixed after applying #1989 . Also the strict optional error in mypy/main.py

@ddfisher
Copy link
Collaborator

Fixed by #1989.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants