~bool deprecation

There’s reasoning behind the LSP, and it’s to avoid questions like the following.

With ~bool throwing an error, in this code, where is the bug?

def f(x: bool):
   ...
   # Perhaps unusual in reality, but
   # expressions like g(a == b) do occur.
   g(x)
   ...

def g(x: int):
   ...
   ~x
   ...

f is passing an int as g asks for. (It is passing a bool, which is an int.) g is calling bitwise not on an int. Both of these operations are supposed to be OK.

These functions may actually be in different packages, of course.

I can see a few answers, only one of which attracts me.

  1. f. Functions should not pass bools where a ints are expected. The best choice for a new language, but a huge change to Python.
  2. g. Functions should ensure that ints they don’t control are not bools before they use bitwise not on them. Bitwise not is pretty rare, but this still seems rather annoying.
  3. g. g should have documented that x must not be a bool in this case. This leaks implementation details of g and makes applying ~ to ints that are passed in a breaking API change.
  4. f. f should not call g with a bool unless it’s checked it doesn’t ~ it. This is a sufficient burden to put on every bool passed as an int argument and every (even non‐breaking) library update that it’s better just to shove int(x) in there, making this more or less equivalent to 1.
  5. Doesn’t matter – this never comes up in practice. Functions like g certainly come up in practice, I’d imagine as a pretty high proportion of all functions using bitwise not, so this doesn’t really rid us of the question. If the potential bug isn’t g’s fault, then it implicitly blames potential future fs (which it assumes don’t exist).
  6. Both functions are OK, and the bug is in bool. :wink:
1 Like