From 9caf0b52229ff935a17ff42f91e843b3d3d264e8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 29 Jul 2020 14:56:58 -0700 Subject: [PATCH 1/2] Make `{align,size}_of_val` `const` --- library/core/src/intrinsics.rs | 2 ++ library/core/src/lib.rs | 2 ++ library/core/src/mem/mod.rs | 8 +++++--- src/librustc_mir/interpret/intrinsics.rs | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 585e54342b773..44b86438f2a89 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1004,11 +1004,13 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). + #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] pub fn size_of_val(_: *const T) -> usize; /// The required alignment of the referenced value. /// /// The stabilized version of this intrinsic is /// [`std::mem::align_of_val`](../../std/mem/fn.align_of_val.html). + #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] pub fn min_align_of_val(_: *const T) -> usize; /// Gets a static string slice containing the name of a type. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index c2bd5d16088fd..550e07f9d5710 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -88,6 +88,8 @@ #![feature(const_result)] #![feature(const_slice_from_raw_parts)] #![feature(const_slice_ptr_len)] +#![feature(const_size_of_val)] +#![feature(const_align_of_val)] #![feature(const_type_name)] #![feature(const_likely)] #![feature(const_unreachable_unchecked)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 6ff7baab70f61..4e58e118562ef 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -332,7 +332,8 @@ pub const fn size_of() -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub fn size_of_val(val: &T) -> usize { +#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +pub const fn size_of_val(val: &T) -> usize { intrinsics::size_of_val(val) } @@ -466,9 +467,10 @@ pub const fn align_of() -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] #[allow(deprecated)] -pub fn align_of_val(val: &T) -> usize { - min_align_of_val(val) +pub const fn align_of_val(val: &T) -> usize { + intrinsics::min_align_of_val(val) } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 39ed3b607934b..d830879eff374 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -120,6 +120,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(location.ptr, dest)?; } + sym::min_align_of_val | sym::size_of_val => { + let place = self.deref_operand(args[0])?; + let (size, align) = self + .size_and_align_of(place.meta, place.layout)? + .ok_or_else(|| err_unsup_format!("`extern type` does not have known layout"))?; + + let result = match intrinsic_name { + sym::min_align_of_val => align.bytes(), + sym::size_of_val => size.bytes(), + _ => bug!(), + }; + + self.write_scalar(Scalar::from_machine_usize(result, self), dest)?; + } + sym::min_align_of | sym::pref_align_of | sym::needs_drop From 88fd4943a65fe7b18c0468255c54f9dee591dd1b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 29 Jul 2020 14:58:06 -0700 Subject: [PATCH 2/2] Test `{align,size}_of_val` in a const context --- ...st-size_of_val-align_of_val-extern-type.rs | 14 ++++++ ...ize_of_val-align_of_val-extern-type.stderr | 20 +++++++++ .../consts/const-size_of_val-align_of_val.rs | 45 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs create mode 100644 src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr create mode 100644 src/test/ui/consts/const-size_of_val-align_of_val.rs diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs new file mode 100644 index 0000000000000..96a8a8452edb0 --- /dev/null +++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -0,0 +1,14 @@ +#![feature(extern_types)] +#![feature(core_intrinsics)] +#![feature(const_size_of_val, const_align_of_val)] + +use std::intrinsics::{size_of_val, min_align_of_val}; + +extern { + type Opaque; +} + +const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR +const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR + +fn main() {} diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr new file mode 100644 index 0000000000000..d3f1b04d25154 --- /dev/null +++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -0,0 +1,20 @@ +error: any use of this value will cause an error + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 + | +LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; + | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | `extern type` does not have known layout + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 + | +LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; + | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | `extern type` does not have known layout + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/consts/const-size_of_val-align_of_val.rs b/src/test/ui/consts/const-size_of_val-align_of_val.rs new file mode 100644 index 0000000000000..e8e6f1d390099 --- /dev/null +++ b/src/test/ui/consts/const-size_of_val-align_of_val.rs @@ -0,0 +1,45 @@ +// run-pass + +#![feature(const_size_of_val, const_align_of_val)] + +use std::mem; + +struct Foo(u32); + +#[derive(Clone, Copy)] +struct Bar { + _x: u8, + _y: u16, + _z: u8, +} + +union Ugh { + _a: [u8; 3], + _b: Bar, +} + +const FOO: Foo = Foo(4); +const BAR: Bar = Bar { _x: 4, _y: 1, _z: 2 }; +const UGH: Ugh = Ugh { _a: [0; 3] }; + +const SIZE_OF_FOO: usize = mem::size_of_val(&FOO); +const SIZE_OF_BAR: usize = mem::size_of_val(&BAR); +const SIZE_OF_UGH: usize = mem::size_of_val(&UGH); + +const ALIGN_OF_FOO: usize = mem::align_of_val(&FOO); +const ALIGN_OF_BAR: usize = mem::align_of_val(&BAR); +const ALIGN_OF_UGH: usize = mem::align_of_val(&UGH); + +const SIZE_OF_SLICE: usize = mem::size_of_val("foobar".as_bytes()); + +fn main() { + assert_eq!(SIZE_OF_FOO, mem::size_of::()); + assert_eq!(SIZE_OF_BAR, mem::size_of::()); + assert_eq!(SIZE_OF_UGH, mem::size_of::()); + + assert_eq!(ALIGN_OF_FOO, mem::align_of::()); + assert_eq!(ALIGN_OF_BAR, mem::align_of::()); + assert_eq!(ALIGN_OF_UGH, mem::align_of::()); + + assert_eq!(SIZE_OF_SLICE, "foobar".len()); +}