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

bool |= bool complains about incompatible assignment type #4386

Closed
asottile opened this issue Dec 19, 2017 · 7 comments
Closed

bool |= bool complains about incompatible assignment type #4386

asottile opened this issue Dec 19, 2017 · 7 comments

Comments

@asottile
Copy link
Contributor

asottile commented Dec 19, 2017

I couldn't find any definitive specification on this other than PEP 285

Here's the input program (which I expect to cause no linting errors)

x = True
x |= False

However it results in the following:

$ mypy test.py
test.py:2: error: Incompatible types in assignment (expression has type "int", variable has type "bool")
$ pip freeze -l
mypy==0.560
psutil==5.4.2
typed-ast==1.1.0

It seems that PEP 285 is implemented faithfully in the versions of python I was able to check:

$ echo -n '2.6 2.7 3.4 3.5 3.6' | xargs -d' ' --replace -- bash -xc "python{} -c 'assert type(False | True) is bool'"
+ python2.6 -c 'assert type(False | True) is bool'
+ python2.7 -c 'assert type(False | True) is bool'
+ python3.4 -c 'assert type(False | True) is bool'
+ python3.5 -c 'assert type(False | True) is bool'
+ python3.6 -c 'assert type(False | True) is bool'
@asottile
Copy link
Contributor Author

This patch to typeshed makes the above pass:

$ git diff stdlib/3
diff --git a/stdlib/3/builtins.pyi b/stdlib/3/builtins.pyi
index f2cea0f..74eb806 100644
--- a/stdlib/3/builtins.pyi
+++ b/stdlib/3/builtins.pyi
@@ -537,6 +537,30 @@ class memoryview(Sized, Container[bytes]):
 
 class bool(int):
     def __init__(self, o: object = ...) -> None: ...
+    @overload  # type: ignore
+    def __and__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __and__(self, x: int) -> int: ...
+    @overload  # type: ignore
+    def __or__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __or__(self, x: int) -> int: ...
+    @overload  # type: ignore
+    def __xor__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __xor__(self, x: int) -> int: ...
+    @overload  # type: ignore
+    def __rand__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __rand__(self, x: int) -> int: ...
+    @overload  # type: ignore
+    def __ror__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __ror__(self, x: int) -> int: ...
+    @overload  # type: ignore
+    def __rxor__(self, x: bool) -> bool: ...
+    @overload  # type: ignore
+    def __rxor__(self, x: int) -> int: ...
 
 class slice:
     start = ...  # type: Optional[int]

though I'm concerned about the # type: ignore (bool does after all violate LSP ala #1237 so maybe this is correct?)

If this seems OK, I'll turn it into a PR :)

@ethanhs
Copy link
Collaborator

ethanhs commented Dec 19, 2017

This is an interesting case indeed. I believe the fix should probably happen in typeshed, so please open an issue there. Thanks!

@asottile
Copy link
Contributor Author

Thanks, opened python/typeshed#1793!

@ilevkivskyi
Copy link
Member

After looking at this carefully, it seems to me that the # type: ignores should not be needed here. So I think there is still also a mypy issue. Should we just reopen this one or create a new issue?

@gvanrossum
Copy link
Member

IIRC we looked at that before and it seemed complicated; maybe you can find an older issue for the overload on e.g. __and__ and review the discussion there? (Note that strictly speaking only the first @overload needs a # type: ignore.)

@ethanhs
Copy link
Collaborator

ethanhs commented Dec 24, 2017

Ah, this was already discussed in #1684, and closed in favor of python/typeshed#649, but I didn't see anything discussing the specific issue of needing the # type: ignore.

@ilevkivskyi
Copy link
Member

@ethanhs
Yes, it looks like # type: ignore was not discussed, but most likely PR #3263 will allow to remove these # type: ignores.

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

4 participants