Skip to content

Commit 8582b04

Browse files
authored
Rollup merge of rust-lang#69922 - RalfJung:less-intrinsic, r=oli-obk
implement zeroed and uninitialized with MaybeUninit This is the second attempt of doing such a change (first PR: rust-lang#62150). The last change [got reverted](rust-lang#63343) because it [caused](rust-lang#62825) some [issues](rust-lang#52898 (comment)) in [code that incorrectly used these functions](AltF02/x11-rs#99). Since then, the [problematic code has been fixed](AltF02/x11-rs#101), and rustc [gained a lint](rust-lang#63346) that is able to detect many misuses of these functions statically and a [dynamic check that panics](rust-lang#66059) instead of causing UB for some incorrect uses. Fixes rust-lang#62825
2 parents 90ebf47 + a2160e6 commit 8582b04

File tree

10 files changed

+18
-113
lines changed

10 files changed

+18
-113
lines changed

src/libcore/intrinsics.rs

+1-39
Original file line numberDiff line numberDiff line change
@@ -1027,46 +1027,8 @@ extern "rust-intrinsic" {
10271027
#[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
10281028
pub fn caller_location() -> &'static crate::panic::Location<'static>;
10291029

1030-
/// Creates a value initialized to zero.
1031-
///
1032-
/// `init` is unsafe because it returns a zeroed-out datum,
1033-
/// which is unsafe unless `T` is `Copy`. Also, even if T is
1034-
/// `Copy`, an all-zero value may not correspond to any legitimate
1035-
/// state for the type in question.
1036-
///
1037-
/// The stabilized version of this intrinsic is
1038-
/// [`std::mem::zeroed`](../../std/mem/fn.zeroed.html).
1039-
#[unstable(
1040-
feature = "core_intrinsics",
1041-
reason = "intrinsics are unlikely to ever be stabilized, instead \
1042-
they should be used through stabilized interfaces \
1043-
in the rest of the standard library",
1044-
issue = "none"
1045-
)]
1046-
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
1047-
pub fn init<T>() -> T;
1048-
1049-
/// Creates an uninitialized value.
1050-
///
1051-
/// `uninit` is unsafe because there is no guarantee of what its
1052-
/// contents are. In particular its drop-flag may be set to any
1053-
/// state, which means it may claim either dropped or
1054-
/// undropped. In the general case one must use `ptr::write` to
1055-
/// initialize memory previous set to the result of `uninit`.
1056-
///
1057-
/// The stabilized version of this intrinsic is
1058-
/// [`std::mem::MaybeUninit`](../../std/mem/union.MaybeUninit.html).
1059-
#[unstable(
1060-
feature = "core_intrinsics",
1061-
reason = "intrinsics are unlikely to ever be stabilized, instead \
1062-
they should be used through stabilized interfaces \
1063-
in the rest of the standard library",
1064-
issue = "none"
1065-
)]
1066-
#[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
1067-
pub fn uninit<T>() -> T;
1068-
10691030
/// Moves a value out of scope without running drop glue.
1031+
/// This exists solely for `mem::forget_unsized`; normal `forget` uses `ManuallyDrop` instead.
10701032
pub fn forget<T: ?Sized>(_: T);
10711033

10721034
/// Reinterprets the bits of a value of one type as another type.

src/libcore/mem/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ pub const fn needs_drop<T>() -> bool {
490490
///
491491
/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
492492
/// ```
493-
#[inline]
493+
#[inline(always)]
494494
#[stable(feature = "rust1", since = "1.0.0")]
495495
#[allow(deprecated_in_future)]
496496
#[allow(deprecated)]
@@ -500,7 +500,7 @@ pub unsafe fn zeroed<T>() -> T {
500500
intrinsics::assert_zero_valid::<T>();
501501
#[cfg(bootstrap)]
502502
intrinsics::panic_if_uninhabited::<T>();
503-
intrinsics::init()
503+
MaybeUninit::zeroed().assume_init()
504504
}
505505

506506
/// Bypasses Rust's normal memory-initialization checks by pretending to
@@ -525,7 +525,7 @@ pub unsafe fn zeroed<T>() -> T {
525525
/// [uninit]: union.MaybeUninit.html#method.uninit
526526
/// [assume_init]: union.MaybeUninit.html#method.assume_init
527527
/// [inv]: union.MaybeUninit.html#initialization-invariant
528-
#[inline]
528+
#[inline(always)]
529529
#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
530530
#[stable(feature = "rust1", since = "1.0.0")]
531531
#[allow(deprecated_in_future)]
@@ -536,7 +536,7 @@ pub unsafe fn uninitialized<T>() -> T {
536536
intrinsics::assert_uninit_valid::<T>();
537537
#[cfg(bootstrap)]
538538
intrinsics::panic_if_uninhabited::<T>();
539-
intrinsics::uninit()
539+
MaybeUninit::uninit().assume_init()
540540
}
541541

542542
/// Swaps the values at two mutable locations, without deinitializing either one.

src/librustc_codegen_llvm/intrinsic.rs

+2-20
Original file line numberDiff line numberDiff line change
@@ -195,26 +195,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
195195
.unwrap();
196196
OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
197197
}
198-
"init" => {
199-
let ty = substs.type_at(0);
200-
if !self.layout_of(ty).is_zst() {
201-
// Just zero out the stack slot.
202-
// If we store a zero constant, LLVM will drown in vreg allocation for large
203-
// data structures, and the generated code will be awful. (A telltale sign of
204-
// this is large quantities of `mov [byte ptr foo],0` in the generated code.)
205-
memset_intrinsic(
206-
self,
207-
false,
208-
ty,
209-
llresult,
210-
self.const_u8(0),
211-
self.const_usize(1),
212-
);
213-
}
214-
return;
215-
}
216-
// Effectively no-ops
217-
"uninit" | "forget" => {
198+
// Effectively no-op
199+
"forget" => {
218200
return;
219201
}
220202
"offset" => {

src/librustc_typeck/check/intrinsic.rs

-2
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
150150
"assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
151151
(1, Vec::new(), tcx.mk_unit())
152152
}
153-
"init" => (1, Vec::new(), param(0)),
154-
"uninit" => (1, Vec::new(), param(0)),
155153
"forget" => (1, vec![param(0)], tcx.mk_unit()),
156154
"transmute" => (2, vec![param(0)], param(1)),
157155
"move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),

src/test/ui/init-large-type.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// compile-flags: -O
12
// run-pass
23

34
#![allow(unused_must_use)]
@@ -10,17 +11,13 @@
1011

1112
#![feature(intrinsics)]
1213

13-
use std::thread;
14-
15-
extern "rust-intrinsic" {
16-
pub fn init<T>() -> T;
17-
}
14+
use std::{mem, thread};
1815

1916
const SIZE: usize = 1024 * 1024;
2017

2118
fn main() {
2219
// do the test in a new thread to avoid (spurious?) stack overflows
2320
thread::spawn(|| {
24-
let _memory: [u8; SIZE] = unsafe { init() };
21+
let _memory: [u8; SIZE] = unsafe { mem::zeroed() };
2522
}).join();
2623
}

src/test/ui/init-unsafe.rs

-9
This file was deleted.

src/test/ui/init-unsafe.stderr

-11
This file was deleted.

src/test/ui/intrinsics/intrinsic-move-val.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
mod rusti {
77
extern "rust-intrinsic" {
8-
pub fn init<T>() -> T;
98
pub fn move_val_init<T>(dst: *mut T, src: T);
109
}
1110
}
@@ -15,17 +14,17 @@ pub fn main() {
1514
// sanity check
1615
check_drops_state(0, None);
1716

18-
let mut x: Box<D> = box D(1);
19-
assert_eq!(x.0, 1);
17+
let mut x: Option<Box<D>> = Some(box D(1));
18+
assert_eq!(x.as_ref().unwrap().0, 1);
2019

2120
// A normal overwrite, to demonstrate `check_drops_state`.
22-
x = box D(2);
21+
x = Some(box D(2));
2322

2423
// At this point, one destructor has run, because the
2524
// overwrite of `x` drops its initial value.
2625
check_drops_state(1, Some(1));
2726

28-
let mut y: Box<D> = rusti::init();
27+
let mut y: Option<Box<D>> = std::mem::zeroed();
2928

3029
// An initial binding does not overwrite anything.
3130
check_drops_state(1, Some(1));
@@ -51,9 +50,9 @@ pub fn main() {
5150
// during such a destructor call. We do so after the end of
5251
// this scope.
5352

54-
assert_eq!(y.0, 2);
55-
y.0 = 3;
56-
assert_eq!(y.0, 3);
53+
assert_eq!(y.as_ref().unwrap().0, 2);
54+
y.as_mut().unwrap().0 = 3;
55+
assert_eq!(y.as_ref().unwrap().0, 3);
5756

5857
check_drops_state(1, Some(1));
5958
}

src/test/ui/intrinsics/intrinsic-uninit.rs

-13
This file was deleted.

src/test/ui/proc-macro/auxiliary/derive-unstable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(Unstable)]
1111
pub fn derive(_input: TokenStream) -> TokenStream {
1212

13-
"unsafe fn foo() -> u32 { ::std::intrinsics::init() }".parse().unwrap()
13+
"unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap()
1414
}

0 commit comments

Comments
 (0)