Rust: #[repr(align(4))] struct has 8 byte alignment

Created on 12 Feb 2018  路  11Comments  路  Source: rust-lang/rust

See it live:

#![allow(non_camel_case_types)]
pub enum c_void {}

type uintptr_t = usize;
type int16_t = u16;
type uint16_t = int16_t;
type uint32_t = u32;
type intptr_t = uintptr_t;

#[repr(C)]
#[repr(align(4))]
pub struct kevent {
    pub ident: uintptr_t,
    pub filter: int16_t,
    pub flags: uint16_t,
    pub fflags: uint32_t,
    pub data: intptr_t,
    pub udata: *mut c_void,
}

fn main() {
    assert_eq!(::std::mem::align_of::<kevent>(), 4); // ERROR: 8 != 4
}

No warning, no error, nu nothing.

This is https://github.com/rust-lang/libc/issues/914

A-diagnostics C-feature-request T-compiler

Most helpful comment

It would be nice to have a lint to warn you you when #[repr(align(N))] has no effect due to the struct's natural alignment already being that high.

All 11 comments

cc #33626

If we follow the text of the original RFC 1358, this is intended:

// Lowering has no effect
#[repr(align = "1")]
struct Align1(i32);

so the problem is missing diagnostic. Not sure if portability lint is needed due to the pointer-sized things.

Might be that what we need here is just repr(packed): https://github.com/rust-lang/rust/issues/33158

It would be nice to have a lint to warn you you when #[repr(align(N))] has no effect due to the struct's natural alignment already being that high.

How would that lint work portably? What say you wanted 8 byte alignment on all targets with

#[repr(align = "8")]
struct Align8(usize);

the lint would fire on 64-bit targets.

In that case you can just #[allow(whatever_the_lint_name_is_idk)]

Or use #[cfg_attr(not(target_pointer_width="8"), repr(align(8)))]

Btw, why doesn't #[repr(align(16))] work on struct members?
It's inconvenient to have to wrap a member in another type just to specify the alignment.

Probably because you can't do that in C. At least for __declspec(align) it cannot be applied to individual fields.

@retep998 Just because it's not possible in C doesn't mean it can't be possible in LLVM / Rust. Even if it's only possible on a struct, rustc could auto-generate a wrapper struct for the codegen and auto-wrap the member in it, if it has that attribute.

@Boscop I'm not saying we shouldn't have that feature, I'm just explaining why we don't have that yet. Feel free to open an issue or PR about that extension of #[repr(align)]. This issue isn't really the place for it.

Prior art: In C++, an alignas specifier lower than the natural alignment is a hard error. (Reference: this page; search for "ill-formed".)

Was this page helpful?
0 / 5 - 0 ratings