Description
The T-compiler and T-lang teams signed off here, that
bool
has the same representation as_Bool
where on every platform that Rust currently supports this implies that:
bool
has a size and an alignment of1
,true as i32 == 1
andfalse as i32 == 0
, EDIT: that is always true, the valid bit patterns ofbool
is what matters here, e.g., on a platform wherebool
has the same size asi8
, whethertransmute::<_, i8>(true) == 1
andtransmute::<_, i8>(false) == 0
These two properties are not guaranteed by Rust, and unsafe
code cannot rely on these. In the last UCG WG meeting it was unclear whether we want to guarantee these two properties or not. As @rkruppe pointed out, this would be guaranteeing something different and incompatible with what T-lang and T-compiler guaranteed.
Note: any change that the UCG WG proposes will have to go through the RFC process anyways, were it might be rejected. This issue is being raised with stakeholders to evaluate whether there is something that needs changing or not, and if so, whether the change is possible, has chances to achieve consensus, etc.
The following arguments have been raised (hope I did not miss any):
-
T-lang and T-compiler did not specify which version of the C standard
_Bool
conforms to. In C++20 and C20, P0907r4 (C++) and N2218 (C) specify that:bool
and_Bool
contain no padding bits (only value bits),1 == (int)true
and0 == (int)false
.
In some of the merged PRs of the UCG we have already specified that the platform's C implementation needs to comply with some, e.g., C17 or "latest" C standard properties (e.g. for
repr(C) struct
layout). If we end up requiring C20 for representation / validity ofrepr(C)
, we end up guaranteeing these properties. AFAICT the only property aboutbool
that would remain as implementation-defined is its size and alignment. -
In Representation of bool, integers and floating points #9 / added floating point/int summary #49 , we ended up requiring that C's
CHAR_BITS == 8
. This implies that ifCHAR_BITS != 8
thenbool
cannot have the same representation as_Bool
. Some stakeholders still wanted to be able to do C FFI with these platforms, e.g. @briansmith suggested that Rust should diagnose, e.g., usingbool
on FFI on these platforms (Representation of bool, integers and floating points #9 (comment)), but that interfacing with those platforms via C FFI (e.g. against assembly) should still be possible (e.g. in a DSP whereCHAR_BITS == 16
passing au16
to C / assembly / ... expecting achar
or 16 bit integer should be doable). -
What exactly T-lang and T-compiler actually ended up guaranteeing isn't 100% clear. In Lint for the reserved ABI of bool rust#46176 the decision seems to be that
bool == _Bool
, but the PR that was actually merged only mentions thatbool
has a size of1
: Document the size of bool rust#46156. This might be an oversight in the docs, and some have mention that the reference is "non-normative". @briansmith pointed out (here and here) thatbool
ABI (e.g. integer class or something else?), alignment, bit patterns denotingtrue
andfalse
, etc. don't appear to be properly documented. @gankro summarized the status quo in Rust Layout and ABIs document and mentioned that projects like Firefox rely on these extra guarantees for correctness (e.g. forbindgen
, etc. to work properly, see here.
There are a couple of comments by @withoutboats that I think show both T-lang and T-compiler's rationale and the spirit behind their decision, here:
I worry that if we don't specify
bool
as equivalent to C and C++ booleans, people will need to usec_bool
in FFI to be cross platform compatible.I worry that if we don't specify
bool
as byte sized, people will create astruct Bool(u8)
to get that guarantee & keep their structs small.
and here:
People could come to the conclusion that they need a
c_bool
type for their FFI to be forward compatible with platforms we don't yet support. I think defining it as the same representation as_Bool
/ C++bool
makes it the least likely someone does something painful to avoid entirely hypothetical problems.
So even if the docs say that bool
has a size of 1
, and that's it, I believe that this last comment shows that the spirit of T-lang and T-compiler decision was to spare people from creating a c_bool
type to be forward compatible on C FFI with platforms that we might never properly support.
I think that the open questions that have to be clarified, are:
- Should we require C20 compatibility for
_Bool
, or do we want to stay backwards compatible with C99/11/17 ? (in this case, people can only rely on, e.g.,true == 1
on targets where the platform implementation is C20 "conforming" at least w.r.t._Bool
) - Do we want to require that
bool
has a size and an alignment of1
? (in the hypothetical case that we ever support a platform where this is not the case, we could raise animproper_ctype
warning / error on the platform, or some other form of diagnostic, as @briansmith suggested). This would be a change incompatible withbool == _Bool
, might lead people to create and use ac_bool
type, etc.
cc @rkruppe @withoutboats @briansmith @gankro @joshtriplett @cuviper @whitequark @est31 @SimonSapin