Skip to content

bool == _Bool ? #53

Closed
Closed
@gnzlbg

Description

@gnzlbg

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 of 1,
  • true as i32 == 1 and false as i32 == 0, EDIT: that is always true, the valid bit patterns of bool is what matters here, e.g., on a platform where bool has the same size as i8, whether transmute::<_, i8>(true) == 1 and transmute::<_, 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 and 0 == (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 of repr(C), we end up guaranteeing these properties. AFAICT the only property about bool 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 if CHAR_BITS != 8 then bool 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., using bool 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 where CHAR_BITS == 16 passing a u16 to C / assembly / ... expecting a char 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 that bool has a size of 1: 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) that bool ABI (e.g. integer class or something else?), alignment, bit patterns denoting true and false, 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. for bindgen, 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 use c_bool in FFI to be cross platform compatible.

  • I worry that if we don't specify bool as byte sized, people will create a struct 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 of 1 ? (in the hypothetical case that we ever support a platform where this is not the case, we could raise an improper_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 a c_bool type, etc.

cc @rkruppe @withoutboats @briansmith @gankro @joshtriplett @cuviper @whitequark @est31 @SimonSapin

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions