Skip to content

bool |= bool complains about incompatible assignment type #1793

Closed
@asottile

Description

@asottile

From python/mypy#4386

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'

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 python/mypy#1237 so maybe this is correct?)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions