The spec has been updated so that only 0 and 1 are safe values for bool. This means that reading a bool value whose underlying byte representation has other bits set is implementation-defined and should be avoided. Consequently:
So got me curious what Julia does, and it seems whatever we do we have to live with it:
I would have though all non-zero should be true… and simple to check. Only the last bit seems to be “checked” with and al, 1. See: @code_native reinterpret(Bool, UInt8(2)).
I believe it’s intentional to have Bool in 8 bits, not 1, in many languages including C++. But non-zero not always might be true in some other languages, or not done the same, so what are the pros and cons of either/any decision? The and is simple, but most often you test with jne (including in Julia?), so might Julia have a bug?
People aren’t supposed to construct other than 0 and 1 Bools, so can it be disallowed/deprecated? I’m not sure it can however be stopped without speed penalty… and would be a breaking change to fail when seeing anything else. Or was that not promised behaviour to work?
help?> reinterpret
│ Warning
│
│ Use caution if some combinations of bits in Out are not considered valid and would otherwise be
│ prevented by the type's constructors and methods. Unexpected behavior may result without
│ additional validation.
Julia has unsafe operations and undefined behaviour, but has not really defined what is safe and what isn’t. The meaning of unsafety and undefined behaviour is mostly (only?) known to a handful of core devs.
Julia is a mostly safe language by default, i.e. excluding [ccall (or code depending on packages using… so basically all code), and @inbounds and], yes, reinterpret, then I think only for Bool (and only when “illegally” constructed; or on Big-endian, not a real worry).
I’m just thinking what was D’s reasoning, and would it apply to Julia?
I shorten the quote, missing this part from D:
void initialization of booleans is now deprecated in @safe code.
Reading a bool field from a union is now deprecated in @safe code.
For all other basic data types, all possible bit patterns are safe.
A pointer is a safe value when it is one of:
null
it points to a memory object that is live and the pointed to value in that memory object is safe.
Julia doesn’t have safe or unsafe regions of code (or then implied), like D and Rust, but could maybe.
They have @safe (and @nogc), a bit better than Julia, I think you need to opt into that (not sure) so actually D is historically an unsafe language like C++, but trying to be safe, has such a subset (I’m not sure if you can enable it globally), I think Julia might have an advantage, by being safe be default, except by how often in practice unsafe (and not easy to undo that or forbid that):
I’m not sure this is related to this issue, but I talked with @gbaraldi at JuliaCon, and it is unclear whether that’s worth it. There are points where a conversion to i8 are inevitable also in C, I seems to remember Gabriel came up with a C example involving pointers where also Clang was uplifting a boolean to i8, but now I don’t remember the details.
But why do you want to use reintrepret at all to get a boolean value out of another integer? You even had to wrap it in UInt8 (and good luck converting 256 with your approach) because that’s not really the intended way to do it. Unless you expect