-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Add #[repr(align = "N")] #1358
Conversation
Extend the existing `#[repr]` attribute on structs with an `align = "N"` option to specify a custom alignment for `struct` types. [Rendered][link] [link]: https://github.com/alexcrichton/rfcs/blob/repr-align/text/0000-repr-align.md
cc #325, an RFC issue also about this. |
I wish we had arbitrary tokens in attributes, to make this nicer. #[repr(align("32"))] #[repr(align("16"))]
struct Foo(u8); #[repr(align("16"), align("32"))]
struct Foo(u8); #[repr(align("32"))]
struct Foo(u8); |
Why the quotes? It would be certainly be nicer to be able to specify any constant expression. |
Yeah unfortunately the syntax for attributes doesn't allow Currently |
It's probably best for this to be another rfc, but I think we should consider allowing the |
@alexcrichton Ah, right, if we need token trees in that case, too, I'd take |
I don't think it makes sense to use RE: "Working with a raw integer, however, should provide the building block for building up other abstractions and should be maximally flexible," what are those "other abstractions"? |
Ah in rust-lang/rust#17537 a suggestion was made to have symbolic alignment (e.g. "aligned as much as this other type"). For example the compiler could possibly accept something like |
I'm having a hard time understanding this.
In particular, it seems bad to put identifiers and integers in quotes for no reason. Quotes should be reserved for strings. More generally, less noise is better, and the quotes are noise, as is the use of "=" and the use of "repr". |
What I want specifically is the equivalent of
https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx This RFC does not look like it does that. |
@briansmith currently there's a difference between "this parses" and "the compiler rejects this". The syntax for attributes simply does not allow integers or values of the form @retep998 sure, this may not exhaustively cover all possibilities of alignment right out the gate, but the idea is to hit as many as possible and to enable other possibilities in perhaps less ergonomic ways immediately while leaving the door open for future improvements. |
How does this interact with heap allocating? The documentation for
However, the page size can differ across systems. Should there be an upper bound on the alignment? |
Seems like a good starting point to me. It does seem like we want to have some sort of limit regarding page-size, but I guess that's mostly a technicality in practice. @alexcrichton do you in fact intend to allow multiple |
(Incidentally, I agree we should extend attribute syntax to include token trees in some form, but as a separate RFC. After that we could deprecate the use of a string constant here (or just accept both.)) |
* Alignment values must be a power of two. | ||
|
||
A custom alignment cannot *decrease* the alignment of a structure unless it is | ||
also declared with `#[repr(packed)]` (to mirror what C does in this regard), but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the behaviour of something like:
#[repr(packed, align = "2")]
struct Foo {
x: u8,
y: u16
}
I assume it has size 4, but there's no padding between the u8
and u16
(i.e. despite the fact that u16
has alignment 2)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if you include trailing padding (which we should do something about, at some point).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The behavior will likely just mirror what C does for now, e.g.:
#include <stddef.h>
#include <stdalign.h>
#include <stdio.h>
struct foo {
char a;
short b;
} __attribute__((packed, aligned(2)));
int main() {
printf("size: %d\n", (int) sizeof(struct foo));
printf("align: %d\n", (int) alignof(struct foo));
printf("a: %d\n", (int) offsetof(struct foo, a));
printf("b: %d\n", (int) offsetof(struct foo, b));
}
$ gcc foo.c && ./a.out
size: 4
align: 2
a: 0
b: 1
Since this only increases the alignment, I'd prefer if it wasn't named |
@retep998 This is why I prefer |
Yeah I'd intend to accept multiple alignment attributes here and the compiler would basically just take the max (e.g. it's correct that the alignment specified would be the minimum-ish). |
@alexcrichton: Is it, though? If I have some type that I need to interoperate with a coal-burning PCI card imported from Outer Elbonia with |
I'm curious as to why multiple alignment attributes would be a useful feature. Can someone please give an example of why someone would do this? |
@eternaleye ah yeah I guess it is, I vaguely remember coming across something where the alignment ended up being less but thinking again I don't think that's the case. Note that factorization and such don't matter as alignment is always a power of two (e.g. custom alignment has this requirement as well). @mark-i-m In terms of composability it's often nice to just add extra restrictions later on without explicitly going back and removing the prior ones. For example if a macro generated something with |
+1
|
This RFC should correlate to the behavior of I started an RFC for the |
Could we have a too-small align be a warning, rather than an error? The RFC doesn't state it explicitly, but it's implied to be an error. Macros and generic code could legitimately end up with this case (if you need at least N alignment, but higher alignment is fine). If I'm wrong about what the RFC means, I would like it to be clarified. Also, how about extending this to be applicable to individual fields? A |
Note that when combined with my pack RFC, this results in a very interesting edge case. Specifically the required alignment of any type is 1, unless the alignment is manually specified with So basically we need to decide whether we want the interaction semantics between |
That's a false choice, I think. It really needs to be either, depending on the ABI in use. |
So you're going the gcc route, where alignment attributes on a struct raise the overall alignment of the struct but it still behaves the same as a naturally aligned struct. A struct whose alignment was raised by |
Would this RFC allow something akin to C++11:
to get memory storage suitably sized and aligned to store a I've come across the usecase while trying to build a Note that if this RFC is not suitable for this, this is not an issue, an intrinsic or built-in could always be created for it. |
@matthieu-m If I'm understanding correctly, you want to use |
Can you use this on individual instances, or only on type declarations? Like in C++: // every object of type sse_t will be aligned to 16-byte boundary // the array "cacheline" will be aligned to 128-byte boundary Same keyword works in both cases |
@TrianglesPCT I might be wrong, but I'm not aware that attributes can be used on individual instances. |
At the @rust-lang/lang meeting, we decided not to decide on this just yet, because we were all a little confused by the back-and-forth on alignment. =) The text that @alexcrichton added to the RFC says that
But, given that the
this sentence seems somewhat incorrect. Reading this comment from @alexcrichton somewhat clarified the intention: I believe the idea is that the
Here, the natural alignment of the struct refers (presumably) to the maximum alignment of any individual field. (I don't believe that is clearly defined in the RFC itself, though I may be missing something.) So, first, @alexcrichton, do you agree with this summary? Anyway, re-reading the other comments more carefully now, I see that @retep998 has indeed highlighted the key difference here (emphasis mine):
I am not convinced that there is a "right choice" in this situation. The interaction with ABI compatibility, in particular, seems concerning. I can certainly imagine wanting the ability to "match" the behavior of the target C ABI, and yet I am not crazy about having Rust's layout be so tied to what the local C compiler does. But whether we pick "GNU" or "MSVC" style, we will be out of sync with the C conventions on some platform. This seems like a place where (As an aside, clearly we must work out the interaction of align and custom packed values, since we adopted the packed RFC, but I also agree with @retep998 that this was an issue before.) |
Indeed! Apologies if the RFC is a bit confusing, I seem to have a tendency to do that lately... But yes my assumption was that
Yes, I'm personally a fan of having understandable Rust semantics and then we can have shims to have compatibility with C as necessary. |
Discussed again in the @rust-lang/lang meeting. We feel like there is no clear right answer here, as I summarized before. Given the lack of feedback and experience, we wanted to propose a compromise: just disallow a struct with an explicit alignment attribute from being used inside of a packed struct, this sidestepping the distinction. We can then revisit the interaction between the two in a specific RFC when we have more experience or specific use cases in mind. Thoughts? |
@nikomatsakis that sounds reasonable to me, and to clarify, the rule would look like this, right?
|
Yes.
|
Ok, I've pushed an update indicating that it is illegal to mix the two attributes |
@alexcrichton I'm fine with the edit your posted, but it may be stronger than necessary. That is, I don't think there is a problem with having an "aligned" struct containing a "packed" struct: #[repr(align=16)]
struct Foo {
b: Bar
}
#[repr(packed)]
struct Bar {
x: u8,
y: u16
} Unless I'm missing something? |
The only issue is when a struct that has |
@nikomatsakis yeah that was intentional, but I've pushed an update now to allow it. |
Huzzah! The @rust-lang/lang team has decided to accept this RFC. |
Tracking issue: rust-lang/rust#33626 If you'd like to keep following the development of this feature, please subscribe to that issue, thanks! :) |
Extend the existing
#[repr]
attribute on structs with analign = "N"
optionto specify a custom alignment for
struct
types.Rendered