Skip to content

~bool deprecation not reported for literals #134280

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

Open
decorator-factory opened this issue May 19, 2025 · 8 comments
Open

~bool deprecation not reported for literals #134280

decorator-factory opened this issue May 19, 2025 · 8 comments
Assignees
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes 3.15 new features, bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@decorator-factory
Copy link
Contributor

decorator-factory commented May 19, 2025

Bug report

Bug description:

Related to: #103487

# literal.py
print(~False)
print(~True)

# var.py
a = True
print(~a)

b = False
print(~b)

A DeprecationWarning is reported for var.py, but not for literal.py.

$ python -c 'import sys; print(sys.version)'
3.15.0a0 (heads/main:42d03f3, May 19 2025, 23:32:01) [GCC 15.1.1 20250425 (Red Hat 15.1.1-1)]

$ python literal.py
-1
-2

$ python var.py
/tmp/scratch/var.py:2: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
  print(~a)
-2
/tmp/scratch/var.py:5: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
  print(~b)
-1

What's interesting is that there's a test for this:

with self.assertWarns(DeprecationWarning):
# also check that the warning is issued in case of constant
# folding at compile time
self.assertEqual(eval("~False"), -1)
and the DeprecationWarning is raised if eval("~True") is used instead of just ~True

$ python -c 'print(~True)'
-2
$ python -c 'print(eval("~True"))'
<string>:1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2

CPython versions tested on:

CPython main branch, 3.13

Operating systems tested on:

Linux

Linked PRs

@decorator-factory decorator-factory added the type-bug An unexpected behavior, bug, or error label May 19, 2025
@picnixz picnixz added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label May 19, 2025
@StanFromIreland
Copy link
Contributor

StanFromIreland commented May 19, 2025

It seems to warn for me on 3.15 and 3.14:

$ python3.15 -c 'print(~True)'
<sys>:0: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2

This is 3.13 only.

@decorator-factory
Copy link
Contributor Author

decorator-factory commented May 19, 2025

@StanFromIreland I ran it in a container (https://hub.docker.com/_/python/) on 3.14 for reproducibility:

$ podman run -ti --rm python:3.14.0b1-slim bash
root@a9edb8be24cb:/# python -c 'print(~True)'
-2
root@a9edb8be24cb:/# python -c 'print(eval("~True"))'
<string>:1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
root@a9edb8be24cb:/# python
Python 3.14.0b1 (main, May  9 2025, 23:49:24) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ~True
-2
>>> ~False
-1
>>>

On 3.15 in debug mode, I do get a warning:

$ ./configure --with-pydebug
...
$ make -j 12
...
$ ./python -c 'print(~True)'
<sys>:0: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
$ ./python
Python 3.15.0a0 (heads/main:42d03f3, May 20 2025, 00:35:04) [GCC 15.1.1 20250425 (Red Hat 15.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ~True
/home/df/clones/cpython/Lib/codeop.py:117: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
  codeob = compile(source, filename, symbol, flags, True)
-2
>>>

EDIT: seems like the warning is displayed in 3.13 and 3.14 if the -X dev flag is enabled

@AA-Turner AA-Turner added 3.13 bugs and security fixes 3.14 bugs and security fixes 3.15 new features, bugs and security fixes labels May 20, 2025
@AA-Turner
Copy link
Member

cc @timhoffm

@timhoffm
Copy link
Contributor

I will look into this.

@serhiy-storchaka
Copy link
Member

This works as intended. By default, DeprecationWarning is only reported for the __main__ module in the Python development mode or in the debug build.

Run Python with -W always or -X dev to see them.

@serhiy-storchaka serhiy-storchaka added the pending The issue will be closed if no feedback is provided label May 31, 2025
@decorator-factory
Copy link
Contributor Author

decorator-factory commented May 31, 2025

So in this case, the operation is considered to be in the __main__ module

if __name__ == "__main__":
    a = True
    print(~a)  # prints -2, with DeprecationWarning

but here it's considered to be outside of __main__?

if __name__ == "__main__":
    print(~True)  # prints -2, no DeprecationWarning

(from the docs (https://docs.python.org/3/library/exceptions.html#DeprecationWarning) and PEP 565 I'm assuming that you meant that deprecation warnings are only active in __main__ by default

default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning

)

@serhiy-storchaka
Copy link
Member

Well, this is obviously related to the fact that ~True is calculated at the compile time.

If warnings are ignored in the constant folding, this is a bug.

@serhiy-storchaka serhiy-storchaka self-assigned this May 31, 2025
@serhiy-storchaka serhiy-storchaka removed the pending The issue will be closed if no feedback is provided label May 31, 2025
serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue May 31, 2025
This moves the deprecation warning from compile time to runtime.
@serhiy-storchaka
Copy link
Member

#134982 disables constant folding for ~bool. This moves the deprecation warning from compile time to runtime.

Ideally, we could also emit a SyntaxWarning at compile time, like we do for ()(), but this is rather an additional feature with low benefit/cost ratio.

We narrowly avoided a bullet with not NotImplemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes 3.15 new features, bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

6 participants