From d49306da136c1c433a95babc82cc278cbf192238 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Mar 2020 14:23:13 +0100 Subject: [PATCH 1/4] implement zeroed and uninitialized with MaybeUninit --- src/libcore/intrinsics.rs | 40 +------------------- src/libcore/mem/mod.rs | 4 +- src/librustc_codegen_llvm/intrinsic.rs | 22 +---------- src/librustc_typeck/check/intrinsic.rs | 2 - src/test/ui/init-large-type.rs | 8 +--- src/test/ui/init-unsafe.rs | 9 ----- src/test/ui/init-unsafe.stderr | 11 ------ src/test/ui/intrinsics/intrinsic-move-val.rs | 15 ++++---- src/test/ui/intrinsics/intrinsic-uninit.rs | 13 ------- 9 files changed, 14 insertions(+), 110 deletions(-) delete mode 100644 src/test/ui/init-unsafe.rs delete mode 100644 src/test/ui/init-unsafe.stderr delete mode 100644 src/test/ui/intrinsics/intrinsic-uninit.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3c060cc6e840b..265ed48809527 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1021,46 +1021,8 @@ extern "rust-intrinsic" { #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] pub fn caller_location() -> &'static crate::panic::Location<'static>; - /// Creates a value initialized to zero. - /// - /// `init` is unsafe because it returns a zeroed-out datum, - /// which is unsafe unless `T` is `Copy`. Also, even if T is - /// `Copy`, an all-zero value may not correspond to any legitimate - /// state for the type in question. - /// - /// The stabilized version of this intrinsic is - /// [`std::mem::zeroed`](../../std/mem/fn.zeroed.html). - #[unstable( - feature = "core_intrinsics", - reason = "intrinsics are unlikely to ever be stabilized, instead \ - they should be used through stabilized interfaces \ - in the rest of the standard library", - issue = "none" - )] - #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")] - pub fn init() -> T; - - /// Creates an uninitialized value. - /// - /// `uninit` is unsafe because there is no guarantee of what its - /// contents are. In particular its drop-flag may be set to any - /// state, which means it may claim either dropped or - /// undropped. In the general case one must use `ptr::write` to - /// initialize memory previous set to the result of `uninit`. - /// - /// The stabilized version of this intrinsic is - /// [`std::mem::MaybeUninit`](../../std/mem/union.MaybeUninit.html). - #[unstable( - feature = "core_intrinsics", - reason = "intrinsics are unlikely to ever be stabilized, instead \ - they should be used through stabilized interfaces \ - in the rest of the standard library", - issue = "none" - )] - #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")] - pub fn uninit() -> T; - /// Moves a value out of scope without running drop glue. + /// This exists solely for `mem::forget_unsized`; normal `forget` uses `ManuallyDrop` instead. pub fn forget(_: T); /// Reinterprets the bits of a value of one type as another type. diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 7d9a8bcd05b1c..9f7868005225e 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -500,7 +500,7 @@ pub unsafe fn zeroed() -> T { intrinsics::panic_if_zero_invalid::(); #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); - intrinsics::init() + MaybeUninit::zeroed().assume_init() } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -536,7 +536,7 @@ pub unsafe fn uninitialized() -> T { intrinsics::panic_if_any_invalid::(); #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); - intrinsics::uninit() + MaybeUninit::uninit().assume_init() } /// Swaps the values at two mutable locations, without deinitializing either one. diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1ae9d2a684131..aa42d557b0261 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -195,26 +195,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { .unwrap(); OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self) } - "init" => { - let ty = substs.type_at(0); - if !self.layout_of(ty).is_zst() { - // Just zero out the stack slot. - // If we store a zero constant, LLVM will drown in vreg allocation for large - // data structures, and the generated code will be awful. (A telltale sign of - // this is large quantities of `mov [byte ptr foo],0` in the generated code.) - memset_intrinsic( - self, - false, - ty, - llresult, - self.const_u8(0), - self.const_usize(1), - ); - } - return; - } - // Effectively no-ops - "uninit" | "forget" => { + // Effectively no-op + "forget" => { return; } "offset" => { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index d2a358c3e09b8..36b7ef87b5ef4 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -150,8 +150,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { "panic_if_uninhabited" | "panic_if_zero_invalid" | "panic_if_any_invalid" => { (1, Vec::new(), tcx.mk_unit()) } - "init" => (1, Vec::new(), param(0)), - "uninit" => (1, Vec::new(), param(0)), "forget" => (1, vec![param(0)], tcx.mk_unit()), "transmute" => (2, vec![param(0)], param(1)), "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/init-large-type.rs index a304fc9356b51..7a3ffbb6ad7bf 100644 --- a/src/test/ui/init-large-type.rs +++ b/src/test/ui/init-large-type.rs @@ -10,17 +10,13 @@ #![feature(intrinsics)] -use std::thread; - -extern "rust-intrinsic" { - pub fn init() -> T; -} +use std::{mem, thread}; const SIZE: usize = 1024 * 1024; fn main() { // do the test in a new thread to avoid (spurious?) stack overflows thread::spawn(|| { - let _memory: [u8; SIZE] = unsafe { init() }; + let _memory: [u8; SIZE] = unsafe { mem::zeroed() }; }).join(); } diff --git a/src/test/ui/init-unsafe.rs b/src/test/ui/init-unsafe.rs deleted file mode 100644 index 3d65cfc234092..0000000000000 --- a/src/test/ui/init-unsafe.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![allow(deprecated)] -#![feature(core_intrinsics)] - -use std::intrinsics::{init}; - -// Test that the `init` intrinsic is really unsafe -pub fn main() { - let stuff = init::(); //~ ERROR call to unsafe function is unsafe -} diff --git a/src/test/ui/init-unsafe.stderr b/src/test/ui/init-unsafe.stderr deleted file mode 100644 index e1126316af34e..0000000000000 --- a/src/test/ui/init-unsafe.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/init-unsafe.rs:8:17 - | -LL | let stuff = init::(); - | ^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/intrinsics/intrinsic-move-val.rs b/src/test/ui/intrinsics/intrinsic-move-val.rs index 75b4ec365fe03..b672f1ed26e8d 100644 --- a/src/test/ui/intrinsics/intrinsic-move-val.rs +++ b/src/test/ui/intrinsics/intrinsic-move-val.rs @@ -5,7 +5,6 @@ mod rusti { extern "rust-intrinsic" { - pub fn init() -> T; pub fn move_val_init(dst: *mut T, src: T); } } @@ -15,17 +14,17 @@ pub fn main() { // sanity check check_drops_state(0, None); - let mut x: Box = box D(1); - assert_eq!(x.0, 1); + let mut x: Option> = Some(box D(1)); + assert_eq!(x.as_ref().unwrap().0, 1); // A normal overwrite, to demonstrate `check_drops_state`. - x = box D(2); + x = Some(box D(2)); // At this point, one destructor has run, because the // overwrite of `x` drops its initial value. check_drops_state(1, Some(1)); - let mut y: Box = rusti::init(); + let mut y: Option> = std::mem::zeroed(); // An initial binding does not overwrite anything. check_drops_state(1, Some(1)); @@ -51,9 +50,9 @@ pub fn main() { // during such a destructor call. We do so after the end of // this scope. - assert_eq!(y.0, 2); - y.0 = 3; - assert_eq!(y.0, 3); + assert_eq!(y.as_ref().unwrap().0, 2); + y.as_mut().unwrap().0 = 3; + assert_eq!(y.as_ref().unwrap().0, 3); check_drops_state(1, Some(1)); } diff --git a/src/test/ui/intrinsics/intrinsic-uninit.rs b/src/test/ui/intrinsics/intrinsic-uninit.rs deleted file mode 100644 index 9555efb639b50..0000000000000 --- a/src/test/ui/intrinsics/intrinsic-uninit.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![feature(intrinsics)] - -mod rusti { - extern "rust-intrinsic" { - pub fn uninit() -> T; - } -} -pub fn main() { - let _a : isize = unsafe {rusti::uninit()}; -} From c7eb0f2a40c25b6cec131b28a3638a6c27dbb5e8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Mar 2020 19:41:41 +0100 Subject: [PATCH 2/4] fix expand-to-unstable test --- src/test/ui/proc-macro/auxiliary/derive-unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs index f702df66db1b8..2ccd3f88200e3 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-unstable.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs @@ -10,5 +10,5 @@ use proc_macro::TokenStream; #[proc_macro_derive(Unstable)] pub fn derive(_input: TokenStream) -> TokenStream { - "unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap() + "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap() } From 996a51bcd04e097254b5072270e10b1280ff1b28 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Mar 2020 14:38:33 +0100 Subject: [PATCH 3/4] init-large-type test needs optimizations --- src/test/ui/init-large-type.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/init-large-type.rs index 7a3ffbb6ad7bf..ce905572f2a8c 100644 --- a/src/test/ui/init-large-type.rs +++ b/src/test/ui/init-large-type.rs @@ -1,3 +1,4 @@ +// compile-flags: -O // run-pass #![allow(unused_must_use)] From a2160e6a4a91490117b9f0469c49b6f86d0d20d2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Mar 2020 17:37:26 +0100 Subject: [PATCH 4/4] make mem::{zeroed,uninitialized} inline(always) --- src/libcore/mem/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 9f7868005225e..ae4c0a98ea930 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -490,7 +490,7 @@ pub const fn needs_drop() -> bool { /// /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! /// ``` -#[inline] +#[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] @@ -525,7 +525,7 @@ pub unsafe fn zeroed() -> T { /// [uninit]: union.MaybeUninit.html#method.uninit /// [assume_init]: union.MaybeUninit.html#method.assume_init /// [inv]: union.MaybeUninit.html#initialization-invariant -#[inline] +#[inline(always)] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)]