-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Deprecate pointer-width integer aliases #1400
Comments
The UCGs specifies that That is, we could deprecate Note that because we define This does not only matter for segmented architectures. An example of a modern architecture where this matters is ARM's CHERI. CHERI pointers are 128-bit wide, but they refer to a 64-bit address space - the other 64-bit are used for verification. This means that the maximum number of bytes that can be accessed, the maximum distance between two pointers, etc. are all values for a 64-bit address space. That is, in C, This is problematic for Rust in other ways. While in C loop indices would be of type For us to deprecate |
In fact, |
Code that relies on // given a libc API or type that uses `size_t`:
fn libc_foo(x: libc::size_t) {}
// most code I see is portable and does:
libc_foo(4);
// or:
libc_foo(4_i32 as _);
// Code that exploits the actual type of `libc::size_t` is not portable:
libc_foo(4_usize); From libc's POV, Sadly, Rust is not expressive enough to enforce this constrain of libc via the type system, which is why non-portable code is accepted by the compiler. |
It would be a huge breaking change that would require an RFC. The |
I don’t really disagree with you Brian, having to choose here is
suboptimal. A lot of unsafe code relies on being able to cast a *const f32
to an usize and back. If this isn’t a “lossless” operation, all unsafe code
would break. I think this is a hard constraint on what we could choose.
It would be very suboptimal to have to use 128 bit integers for size_t, but
at least that would work without breaking fundamental assumptions about
pointer to integer cast that Rust code currently relies on.
From this POV, the “usize == uintptr_t” makes sense, and on most archs this
matches “size_t”. In architectures where this does not match, I don’t think
breaking the uintptr_t assumption is possible. EDIT: this assumption is not only
relied on by unsafe Rust code, but the pointer to usize/isize conversions and
vice-versa are safe, so they are also relied on by safe Rust code.
|
Rust already made a mistake of assuming |
Rust guarantees that
Changing that would be a backward incompatible change that would break a lot of extremely subtle Deprecating I cannot find any official documentation that guarantees that there is a Rust type that's identical to FWIW @kornelski this allows targeting CHERI and RV128 by just defining If you think the current definition of |
I agree with that. However, the reason it was brought up in this issue is that, if/when that bug is fixed, then we will need a |
If somebody manages to get the time to start such a discussion thread, please do ping me there. Solving that issue is kind of required to provide really good support for CHERI. |
I was under impression that #include <stddef.h>
size_t len = 0; bindgen test.h /* automatically generated by rust-bindgen */
pub const len: usize = 0; |
That assumption isn't wrong for all targets that rustc currently support, but if you try to compile those crates for CHERI, you would get a compilation error because That's not great, but it isn't that bad. Suppose we were to change the definition of I really don't know of any way to fix this that wouldn't break something, but I hope there is a way to do that. We probably need to throw way more people at this problem to figure out all the alternatives and constraints. |
If we were to implement the breaking change where |
@briansmith we probably want to fix that anyways (independently of what we do with |
This has been some more discussion about this, e.g. https://internals.rust-lang.org/t/pre-rfc-usize-semantics/19444. I don't think there is any point in changing something here before we know exactly how/if Rust might change (I suspect it will at some point given CHERI). What that in mind, I am going to close this for now. |
Similar to #1304, we guarantee that
usize/isize
is layout compatible with C'suintptr_t/intptr_t
.From the Rust documentation on
usize
:From the C11 standard (N1570) section 7.20.1.4:
There is no need to provide type aliases (e.g.
libc::uintptr_t
) for these, in the same way that we don't provide alibc::c_bool
type alias forbool
.What about
size_t
andptrdiff_t
?We could potentially deprecate
libc::size_t
forusize
(andlibc::ptrdiff_t
forisize
). This is a more interesting question, as they are defined to be the type returned by a specific operation.From section 7.19 of the C11 standard:
For
ptrdiff_t
, Rust's pointer methodsptr::offset
andptr::offset_from
useisize
to represent the "difference between pointers".For
size_t
, Rust'score::mem::size_of
function returnsusize
.@gnzlbg @alexcrichton, I'm not sure what we should do here; I would love to know your thoughts. The argument for deprecation seems stronger for
size_t
than forptrdiff_t
.The reason we have
size_t/ptrdiff_t
anduintptr_t/intptr_t
in C is to support segmented addressing, but on every system I could find (including x86 Real Mode)uintptr_t
andsize_t
are the same. Also, Rust already seems to implicitly assume thatsize_t == usize
, this would just make it explicit.What about
ssize_t
?Note that we definitely don't want to deprecate
libc::ssize_t
because:<sys/types.h>
standardisize
. In fact,ssize_t
only needs to be able to have the range[-1, SSIZE_MAX]
andSSIZE_MAX
has no relation tosize_t
's SIZE_MAX.Also, see #1244 (comment)
What about
intmax_t
anduintmax_t
?While I did try to address those in #1244 and they are part of the C standard, defining them to either be
[u|i]size
or[u|i]64
would be wrong, as it would preclude a platform from using a 128-bit integer as it's largest type.The text was updated successfully, but these errors were encountered: