-
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
Interaction of isize / usize with value layout #102
Comments
Yeah, that statement in the reference is incorrect. The maximal size of an object, even of an allocation, in LLVM is |
Is I wonder whether these are things that we should just "document" vs "guarantee". |
So I chatted with @eddyb and they recommended also pinging @sunfishcode to ask whether Cranelift has these limitations as well. @eddyb recommended not guaranteeing this, the maximum object size should be implementation-defined, and we identified the need for an intrinsic to compute the offset of a field within a struct, similar to C's EDIT: it seems that the need for |
In my book |
I'm not very familiar with GEP, but can't we just pass it wider signed integer types as offsets? E.g. if the base pointer is an unsigned |
Agreed, arrays of ZSTs can have
No, LLVM fixes the offset to be |
Closes rust-lang#102 .
Closes rust-lang#102 .
So #98 should now fix this issue. It document these things as implementation-defined, mentioning that the upper limit on object size, array length, and pointer offset is Instead of making array length and pointer offset implementation defined, we could guarantee that |
I believe there's two distinct open questions here:
|
So I've just documented in #98 what the implementation currently does, but the behavior remains unspecified. Guaranteeing anything about the maximum size of Rust objects is something that's probably worth doing on its own RFC (see the top comment for a brief summary). It would be nice to make progress towards that, and we can keep discussing the trade-offs here, but I feel that it is not worth blocking an MVP of the UCGs RFC on this issue so I'm tagging this as such. |
I agree that the pathological toy programs, e.g., that create arrays with There, whether the limit can actually achieved in practice on a particular platform (e.g. due to LLVM, lack of memory / stack space / etc.), or whether the limit is @joshtriplett @briansmith Another constraint when choosing Rust largest object size is being able to map to all C types in C FFI. With OTOH if we fix the maximum allowed value size to |
Notice that at least with LLVM, it is impossible in C as well to have values/typs larger than This doesn't change the lawyering much, but it means in practice this is not just a Rust limitation. |
Lawyering-wise, we could guarantee that Rust does not allow objects larger than |
For example, we could guarantee that objects larger than Guaranteeing how big the largest supported object is on all implementations would be a different guarantee that sounds unnecessarily constraining to me, so I doubt that's worth doing. Being able to query this information is, however, useful, so it might just be better to provide a |
Wait, so we're saying that this code would now not be considered portable? unsafe fn get_elem(slice: &[u8], idx: usize) -> *const u8 {
return slice.as_ptr().offset(idx as isize);
} But the equivalent with unsafe fn get_elem(slice: &[u8], idx: usize) -> *const u8 {
return slice.as_ptr().add(idx);
} This is somewhat concerning, since
At minimum the documentation needs to be changed: the documentation for |
Why do you think that? I don't think so, the docs of
This This also probably means that guaranteeing that |
I'm just saying that based on:
which implies that a Rust implementation could support slices larger than isize::max_value(), therefore any (non-standard-library) code that assumes they can't be is relying on implementation-defined behavior and is thus non-portable. Edit: And my claim about there being a difference between |
@comex I think i see your point now (@rkruppe helped a lot). The document says "implementation-defined" in those two clauses, but IMO we should change that to "unspecified". Specifying those to be
"unspecified" would mean that we don't know whether using |
Closing. It's not clear what parts of this remain unanswered, folks are free to open new issues with precise questions |
The part about max. object size is answered these days, |
EDIT: I'm recycling this issue to track how
isize
andusize
's layout interact with value layout in general. The old comment can be read below.The reference of
isize
/usize
currently documents the limits of the current implementation in a non-normative way:isize::max_value()
,usize::max_value()
,usize::max_value()
.These limits are unspecified (not implementation-defined), that is, we don't guarantee anything about these and the Rust implementation does not have to document them at all.
Changing these to either implementation defined, or to some guarantee that all implementations must satisfy probably would require an RFC on its own that answers the questions:
These limits could be implementation-defined, unspecified, or set to some value that all implementations must uphold (
isize::MAX
,usize::MAX
, etc.). And the trade-offs involved here are, among others, the kinds of code-generation backends Rust can easily support (e.g. LLVM and GCC limit some of these toisize::MAX
, although these might be worked around), the kinds of optimizations these backends can do, and language complexity (e.g. how easy it is for users to write portable code, etc.).old comment:
Layout
isize
/usize
The current reference says that the layout of
usize
determines the maximum size of Rust objects (size_of
andsize_of_val
return usize), the maximum number of elements in an array ([T; N: usize]
), and how much a pointer of a certain type can be offseted. It also says that the maximum size of any single value must fit within usize to ensure that pointer diff is representable.There are two issues with this:
unclear what's meant by "offseted". Pointer add operates on
usize
, but pointer offset operates onisize
. If by "offseted" we meanptr.add
we should probably be more explicit about this.contradiction: we state that the layout of usize determines the maximum size of an object, and then argue that this is to ensure that pointer diff is representable, but AFAICT if the maximum size of an object is larger than
isize
then pointer diff will overflow and is not representable. IIRC @nikomatsakis argued that currently all Rust objects can be at mostisize::max_value()
large because of this, but this is not what the text says.The text was updated successfully, but these errors were encountered: