Skip to content

Commit 10763f4

Browse files
committed
pythongh-82012: Deprecate bitwise inversion (~) of bool
The bitwise inversion operator on bool returns the bitwise inversion of the underlying int value; i.e. `~True == -2` such that `bool(~True) == True`. It's a common pitfall that users mistake `~` as negation operator and actually want `not`. Supporting `~` is an artifact of bool inheriting from int. Since there is no real use-case for the current behavior, let's deprecate `~` on bool and later raise an error. This removes a potential source errors for users. Full reasoning: python#82012 (comment)
1 parent 81387fe commit 10763f4

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

Lib/test/test_bool.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ def test_math(self):
5858
self.assertEqual(-True, -1)
5959
self.assertEqual(abs(True), 1)
6060
self.assertIsNot(abs(True), True)
61-
self.assertEqual(~False, -1)
62-
self.assertEqual(~True, -2)
61+
with self.assertWarns(DeprecationWarning):
62+
self.assertEqual(~False, -1)
63+
with self.assertWarns(DeprecationWarning):
64+
self.assertEqual(~True, -2)
6365

6466
self.assertEqual(False+2, 2)
6567
self.assertEqual(True+2, 3)

Objects/boolobject.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ bool_vectorcall(PyObject *type, PyObject * const*args,
7373

7474
/* Arithmetic operations redefined to return bool if both args are bool. */
7575

76+
static PyObject *
77+
bool_invert(PyObject *v)
78+
{
79+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
80+
"Bitwise inversion '~' on bool is deprecated. This "
81+
"returns the bitwise inversion of the underlying int "
82+
"object and is usually not what you expect from negating "
83+
"a bool. Use the 'not' operator for boolean negation or "
84+
"~int(x) if you really want the bitwise inversion of the "
85+
"underlying int.",
86+
1) < 0) {
87+
return NULL;
88+
}
89+
return PyLong_Type.tp_as_number->nb_invert(v);
90+
}
91+
7692
static PyObject *
7793
bool_and(PyObject *a, PyObject *b)
7894
{
@@ -119,7 +135,7 @@ static PyNumberMethods bool_as_number = {
119135
0, /* nb_positive */
120136
0, /* nb_absolute */
121137
0, /* nb_bool */
122-
0, /* nb_invert */
138+
(unaryfunc)bool_invert, /* nb_invert */
123139
0, /* nb_lshift */
124140
0, /* nb_rshift */
125141
bool_and, /* nb_and */

0 commit comments

Comments
 (0)