-
Notifications
You must be signed in to change notification settings - Fork 59
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
bool == _Bool ? #53
Comments
|
@ubsan yes, I should have used |
The author of those proposals tweeted (really, this is the only source I have) about this proposal: https://twitter.com/jfbastien/status/989242576598327296?lang=en
I don't know which parts of p0907 and N2218 will make it into C and C++, but at least some of it is on track for C++20 and the next revision of the C standard. |
What is the problem with just saying " TBH I am a bit surprised to see so much fuzz about this, I feel there is an aspect to this discussion that I am missing. The one possible problem with this definition is that it means we can only ever port Rust to platforms that support C; however, I think that is an entirely theoretical concern at this point. |
Defining I don't have much respect for the boogeyman of weird bools, since aiui that's mostly I might be willing to accept a weaker statement of "we don't interoperate with c's bool on such a weird platform" but that pushes people back to spreading the folklore that c_bool is useful and good. |
All options have problems. The problem with that approach is that it doesn't guarantee that Rust If we would say that |
fn _static_assert_size_of() {
let _ = std::mem::transmute<bool, u8>;
} |
@SimonSapin preventing code from compiling is not the same producing portable code that compiles and works as expected. An equivalent solution (that prevents some code from compiling) would be to not allow |
The lang and compiler teams decided that this is not the case (i.e., they decided that This was actually called out in rust-lang/rust#46176 (comment):
(emphasis mine) I see no reason for us to overthrow their decision as part of this documentation process. If you want to change that decision, feel free to write an RFC, but that IMO has no place in the current UCG discussion phase. |
@SimonSapin Here is a version of that code that actually compiles: (from your very brief message, I had no idea whether you wanted to express that this is accepted or rejected by the compiler^^) fn static_assert_size_of() { unsafe {
let _ = std::mem::transmute::<bool, u8>(true);
} }
|
Huh? Of course we do. It compiles, and it's perfectly legitimate if you only target 64 bit platforms or properly |
You are right. Seems I misremembered. Even better, things are consistent then. |
A long discussion with @gnzlbg on Zulip uncovered why I am so confused here (in particular, I maintain that it makes no logical sense to bring up platforms with I think we should close this issue, and just document the T-lang + T-compiler decision that |
(Code in my previous comment did not compile because I forgot |
I am still interested in knowing what concrete platforms people want to actually support with more flexible bools. |
Nobody came up with any relevant ones in the last discussions - I mentioned that MSVC <= 4.2 had |
Historically, 32-bit |
Cray didn't have byte-level addressing, but I don't think anyone needs to target the Cray architecture anymore. I think we should mandate that |
What does that buy us? Pros of
Cons of
On one hand, I think that we should not make it impossible to write Rust that targets weird C platforms - there should not be room or excuses for people to use C. On the other hand, targeting weird C platforms is going to be hard anyways, most of the ecosystem might not be reused at least "as is" on those, etc. Is it worth it to leave most Rust users wondering about As @rkruppe argued, just because we leave those things as "implementation defined" does not mean that people won't assume that they hold everywhere if that holds on all platforms they care about. I don't care about platforms where |
To clarify, So as long as there's a fundamental conflict between guaranteeing the size on weird future platforms and guaranteeing C interop on weird future platforms, and "targeting weird C platforms is going to be hard anyways", it seems we gain a lot more from making |
@Ixrec the team has decided that it's better to be compatible with C, than predictably 1 byte, with bit patterns exactly |
What should miri do here? It currently implements an abstract machine where
bool is one Byte wide and 0x1 and 0x0 are used for true and false but
should it panic on any sort of “bool type punning” ? The “host” and the
“target” can vary in behavior so this could impact const fn.
We already have similar problems with floats, but I don’t know if they are
the same.
|
regardless of our decision, bool's sizing is no different from usize vs u32/u64, which I don't believe is considered an "interesting" problem in miri |
No, it implements an abstract machine where
That's correct. But it seems that'll soon be fixed in C/C++ as well so it seems fine. |
We discussed this briefly in today's meeting, so I think we can close this. We agreed on writing down something along these lines (the exact wording will be in a PR, we can discuss the nits there - cc @avadacatavra ): Representation invariant of boolRust's note: on all platforms that Rust's currently supports, the size and alignment of Validity invariant of boolRust's note: on all platforms that Rust's currently supports, note: there are two proposals, N2218 for C and P0907 for C++, which propose defining We didn't say anything about the safety invariant of There was interest in documenting the "controversy" here but there was some agreement that there isn't really much controversy about this, just different goals that are at tension. EDIT: briefly about the goals at tension: the unsafe code guidelines answer the question "What is The T-lang and T-compiler team considered many goals, like "people should use |
The T-compiler and T-lang teams signed off here, that
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.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:
and here:
So even if the docs say that
bool
has a size of1
, 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 ac_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:
_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
)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
The text was updated successfully, but these errors were encountered: