Skip to content

Commit db440ab

Browse files
authored
Don't consider 'object' always truthy (#14510)
There are two reasons I'm proposing this change. First, we know that many subclasses of 'object' can be falsy. Second, mypy sometimes simplifies `object | Any` into just `object`. The latter was considered always truthy, while the prior one wasn't. Now both of them are treated consistently. An alternative fix would be to not simplify unions like `object | Any`, but this seems a bit ad hoc. This only has an effect when the `truthy-bool` error code is explicitly enabled. Fixes #14480. This doesn't just fix the regression but fixes a more general issue.
1 parent 77f8725 commit db440ab

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

mypy/checker.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5151,6 +5151,7 @@ def _is_truthy_type(self, t: ProperType) -> bool:
51515151
and bool(t.type)
51525152
and not t.type.has_readable_member("__bool__")
51535153
and not t.type.has_readable_member("__len__")
5154+
and t.type.fullname != "builtins.object"
51545155
)
51555156
or isinstance(t, FunctionLike)
51565157
or (

test-data/unit/check-errorcodes.test

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -803,12 +803,15 @@ from typing_extensions import TypedDict
803803

804804
Foo = TypedDict("Bar", {}) # E: First argument "Bar" to TypedDict() does not match variable name "Foo" [name-match]
805805
[builtins fixtures/dict.pyi]
806+
806807
[case testTruthyBool]
807808
# flags: --enable-error-code truthy-bool
808-
from typing import List, Union
809+
from typing import List, Union, Any
809810

810811
class Foo:
811812
pass
813+
class Bar:
814+
pass
812815

813816
foo = Foo()
814817
if foo: # E: "__main__.foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
@@ -836,15 +839,30 @@ if good_union:
836839
if not good_union:
837840
pass
838841

839-
bad_union: Union[Foo, object] = Foo()
840-
if bad_union: # E: "__main__.bad_union" has type "Union[Foo, object]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
842+
bad_union: Union[Foo, Bar] = Foo()
843+
if bad_union: # E: "__main__.bad_union" has type "Union[Foo, Bar]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
844+
pass
845+
if not bad_union: # E: "__main__.bad_union" has type "Union[Foo, Bar]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
846+
pass
847+
848+
# 'object' is special and is treated as potentially falsy
849+
obj: object = Foo()
850+
if obj:
841851
pass
842-
if not bad_union: # E: "__main__.bad_union" has type "object" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool]
852+
if not obj:
843853
pass
844854

845855
lst: List[int] = []
846856
if lst:
847857
pass
858+
859+
a: Any
860+
if a:
861+
pass
862+
863+
any_or_object: Union[object, Any]
864+
if any_or_object:
865+
pass
848866
[builtins fixtures/list.pyi]
849867

850868
[case testTruthyFunctions]

0 commit comments

Comments
 (0)