Skip to content

Commit

Permalink
Add --strict-bool flag to prohib treating bool as int
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Jul 5, 2024
1 parent 6069718 commit 2849e58
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
20 changes: 20 additions & 0 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,26 @@ of the above sections.
assert text is not None # OK, check against None is allowed as a special case.
.. option:: --strict-bool

By default ``bool`` values are treated as subtypes of ``int``,
just like in runtime:

.. code-block:: python
>>> bool.__mro__
(<class 'bool'>, <class 'int'>, <class 'object'>)
While it will work in runtime,
some cases might require a little bit more strictness.
With this flag enabled, you will get the following error:

.. code-block:: python
def requires_int(arg: int) -> None: ...
requires_int(5 > 0) # Error: Argument 1 has incompatible type "bool"; expected "int"
.. option:: --extra-checks

This flag enables additional checks that are technically correct but may be
Expand Down
8 changes: 8 additions & 0 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,14 @@ def add_invertible_flag(
group=strictness_group,
)

add_invertible_flag(
"--strict-bool",
default=False,
strict_flag=True,
help="Prohib to treat bool as int",
group=strictness_group,
)

add_invertible_flag(
"--extra-checks",
default=False,
Expand Down
5 changes: 5 additions & 0 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class BuildType:
"mypyc",
"strict_concatenate",
"strict_equality",
"strict_bool",
"strict_optional",
"warn_no_return",
"warn_return_any",
Expand Down Expand Up @@ -208,6 +209,10 @@ def __init__(self) -> None:
# This makes 1 == '1', 1 in ['1'], and 1 is '1' errors.
self.strict_equality = False

# Prohibit to treat `bool` as `int` in subtyping contexts.
# This makes `def a(b: int): ...; a(True)` an error.
self.strict_bool = False

# Deprecated, use extra_checks instead.
self.strict_concatenate = False

Expand Down
7 changes: 7 additions & 0 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,13 @@ def visit_instance(self, left: Instance) -> bool:
if left.type.alt_promote and left.type.alt_promote.type is right.type:
return True
rname = right.type.fullname
if (
self.options
and self.options.strict_bool
and left.type.fullname == "builtins.bool"
and rname == "builtins.int"
):
return False
# Always try a nominal check if possible,
# there might be errors that a user wants to silence *once*.
# NamedTuples are a special case, because `NamedTuple` is not listed
Expand Down
34 changes: 34 additions & 0 deletions test-data/unit/check-flags.test
Original file line number Diff line number Diff line change
Expand Up @@ -2284,3 +2284,37 @@ class C(Generic[T]): ...

A = Union[C, List] # OK
[builtins fixtures/list.pyi]

[case testStrictBool]
# flags: --strict-bool --show-error-codes
from typing import List, Union

def a(x: int): ...
a(True) # E: Argument 1 to "a" has incompatible type "bool"; expected "int" [arg-type]
a(False) # E: Argument 1 to "a" has incompatible type "bool"; expected "int" [arg-type]

bl: bool
a(bl) # E: Argument 1 to "a" has incompatible type "bool"; expected "int" [arg-type]

def b() -> int:
return bl # E: Incompatible return value type (got "bool", expected "int") [return-value]

c: List[int] = [
True, # E: List item 0 has incompatible type "bool"; expected "int" [list-item]
False, # E: List item 1 has incompatible type "bool"; expected "int" [list-item]
bl, # E: List item 2 has incompatible type "bool"; expected "int" [list-item]
]

# OK:
def d(x: Union[int, bool], y: bool): ...
d(1, True)
d(True, False)
d(bl, bl)
[builtins fixtures/list.pyi]

[case testStrictBoolWithStrictFlag]
# flags: --strict

def a(x: int) -> None: ...
b: bool
a(b) # E: Argument 1 to "a" has incompatible type "bool"; expected "int"

0 comments on commit 2849e58

Please sign in to comment.