Skip to content

Commit

Permalink
Document #[repr] on non-C-like enums
Browse files Browse the repository at this point in the history
rustc accepts the following today:

    #[repr(u8)]
    enum Flag<T> {
        Dropped,
        Alive(T),
    }

and it has a good use (it appears to me): this inhibits the non-nullable
pointer optimization that the regular Option<T> and similar enums allow.

Document this in the reference, and add tests to make sure it compiles.

This means that we guarantee with `repr` that the discriminant will be
present and with that size, but not sure if we want to guarantee
anything more (no guarantee on placement in struct).
  • Loading branch information
Ulrik Sverdrup committed May 28, 2015
1 parent 541fe5f commit d0e6396
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1892,12 +1892,13 @@ interpreted:

On `enum`s:

- `repr` - on C-like enums, this sets the underlying type used for
representation. Takes one argument, which is the primitive
type this enum should be represented for, or `C`, which specifies that it
should be the default `enum` size of the C ABI for that platform. Note that
enum representation in C is undefined, and this may be incorrect when the C
code is compiled with certain flags.
- `repr` - this sets the underlying type used for representation of the
discriminant. Takes one argument, which is the primitive type this enum
should be represented as, or `C`, which specifies that it should be the
default `enum` size of the C ABI for that platform. Note that enum
representation in C is implementation defined, and this may be incorrect when
the C code is compiled with certain flags. The representation attribute
inhibits elision of the enum discriminant in layout optimizations.

On `struct`s:

Expand Down
107 changes: 107 additions & 0 deletions src/test/run-pass/enum-discrim-manual-sizing-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that explicit discriminant sizing inhibits the non-nullable pointer
// optimization in enum layout.

use std::mem::size_of;

#[repr(i8)]
enum Ei8<T> {
_None,
_Some(T),
}

#[repr(u8)]
enum Eu8<T> {
_None,
_Some(T),
}

#[repr(i16)]
enum Ei16<T> {
_None,
_Some(T),
}

#[repr(u16)]
enum Eu16<T> {
_None,
_Some(T),
}

#[repr(i32)]
enum Ei32<T> {
_None,
_Some(T),
}

#[repr(u32)]
enum Eu32<T> {
_None,
_Some(T),
}

#[repr(i64)]
enum Ei64<T> {
_None,
_Some(T),
}

#[repr(u64)]
enum Eu64<T> {
_None,
_Some(T),
}

#[repr(isize)]
enum Eint<T> {
_None,
_Some(T),
}

#[repr(usize)]
enum Euint<T> {
_None,
_Some(T),
}

#[repr(C)]
enum EC<T> {
_None,
_Some(T),
}

pub fn main() {
assert_eq!(size_of::<Ei8<()>>(), 1);
assert_eq!(size_of::<Eu8<()>>(), 1);
assert_eq!(size_of::<Ei16<()>>(), 2);
assert_eq!(size_of::<Eu16<()>>(), 2);
assert_eq!(size_of::<Ei32<()>>(), 4);
assert_eq!(size_of::<Eu32<()>>(), 4);
assert_eq!(size_of::<Ei64<()>>(), 8);
assert_eq!(size_of::<Eu64<()>>(), 8);
assert_eq!(size_of::<Eint<()>>(), size_of::<isize>());
assert_eq!(size_of::<Euint<()>>(), size_of::<usize>());

let ptrsize = size_of::<&i32>();
assert!(size_of::<Ei8<&i32>>() > ptrsize);
assert!(size_of::<Eu8<&i32>>() > ptrsize);
assert!(size_of::<Ei16<&i32>>() > ptrsize);
assert!(size_of::<Eu16<&i32>>() > ptrsize);
assert!(size_of::<Ei32<&i32>>() > ptrsize);
assert!(size_of::<Eu32<&i32>>() > ptrsize);
assert!(size_of::<Ei64<&i32>>() > ptrsize);
assert!(size_of::<Eu64<&i32>>() > ptrsize);
assert!(size_of::<Eint<&i32>>() > ptrsize);
assert!(size_of::<Euint<&i32>>() > ptrsize);

assert!(size_of::<EC<&i32>>() > ptrsize);
}

0 comments on commit d0e6396

Please sign in to comment.