diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile index b3376f8a72358..f5787903a2b59 100644 --- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile @@ -7,3 +7,5 @@ all: $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value + $(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) librustc_msan + $(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value diff --git a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs new file mode 100644 index 0000000000000..a9ae85f57639e --- /dev/null +++ b/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs @@ -0,0 +1,8 @@ +use std::mem::MaybeUninit; + +fn main() { + // This is technically not sound -- but we're literally trying to test + // that the sanitizer catches this, so I guess "intentionally unsound"? + let xs: [u8; 4] = unsafe { MaybeUninit::uninit().assume_init() }; + let y = xs[0] + xs[1]; +} diff --git a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs index cb857e3bc38d3..eae52508f6585 100644 --- a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs +++ b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs @@ -1,7 +1,7 @@ -use std::mem; - fn main() { + // This is technically not sound -- but we're literally trying to test + // that the sanitizer catches this, so I guess "intentionally unsound"? #[allow(deprecated)] - let xs: [u8; 4] = unsafe { mem::uninitialized() }; + let xs: [u8; 4] = unsafe { std::mem::uninitialized() }; let y = xs[0] + xs[1]; } diff --git a/src/test/rustdoc/issue-52873.rs b/src/test/rustdoc/issue-52873.rs index 653c004c04b23..8000ce73bd42f 100644 --- a/src/test/rustdoc/issue-52873.rs +++ b/src/test/rustdoc/issue-52873.rs @@ -105,8 +105,7 @@ impl Add for UInt { impl Add for UTerm { type Output = U; fn add(self, _: U) -> Self::Output { - #[allow(deprecated)] - unsafe { ::std::mem::uninitialized() } + unimplemented!() } } @@ -137,7 +136,7 @@ where { type Output = UInt>, B0>; fn mul(self, _: UInt) -> Self::Output { - unsafe { ::std::mem::uninitialized() } + unimplemented!() } } diff --git a/src/test/ui/abi/stack-probes.rs b/src/test/ui/abi/stack-probes.rs index 1ab1d6df66d4b..1d5b362e29dfe 100644 --- a/src/test/ui/abi/stack-probes.rs +++ b/src/test/ui/abi/stack-probes.rs @@ -13,7 +13,7 @@ // ignore-sgx no processes // ignore-musl FIXME #31506 -use std::mem; +use std::mem::MaybeUninit; use std::process::Command; use std::thread; use std::env; @@ -28,8 +28,8 @@ fn main() { let args = env::args().skip(1).collect::>(); if args.len() > 0 { match &args[0][..] { - "main-thread" => recurse(&[]), - "child-thread" => thread::spawn(|| recurse(&[])).join().unwrap(), + "main-thread" => recurse(&MaybeUninit::uninit()), + "child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(), _ => panic!(), } return @@ -48,10 +48,11 @@ fn main() { } #[allow(unconditional_recursion)] -fn recurse(array: &[u64]) { - unsafe { black_box(array.as_ptr() as u64); } - #[allow(deprecated)] - let local: [_; 1024] = unsafe { mem::uninitialized() }; +fn recurse(array: &MaybeUninit<[u64; 1024]>) { + unsafe { + black_box(array.as_ptr() as u64); + } + let local: MaybeUninit<[u64; 1024]> = MaybeUninit::uninit(); recurse(&local); } diff --git a/src/test/ui/const-generics/issues/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs index 45d37b6a2f3c5..4fa150ffef09e 100644 --- a/src/test/ui/const-generics/issues/issue-61422.rs +++ b/src/test/ui/const-generics/issues/issue-61422.rs @@ -5,6 +5,10 @@ use std::mem; +// Neither of the uninits below are currently accepted as not UB, however, +// this code does not run and is merely checking that we do not ICE on this pattern, +// so this is fine. + fn foo() { let arr: [u8; SIZE] = unsafe { #[allow(deprecated)] @@ -13,4 +17,12 @@ fn foo() { }; } +fn bar() { + let arr: [u8; SIZE] = unsafe { + let array: [u8; SIZE] = mem::MaybeUninit::uninit().assume_init(); + array + }; +} + + fn main() {} diff --git a/src/test/ui/for-loop-while/for-loop-has-unit-body.rs b/src/test/ui/for-loop-while/for-loop-has-unit-body.rs index 38c34d2dc2e6f..eba385461b951 100644 --- a/src/test/ui/for-loop-while/for-loop-has-unit-body.rs +++ b/src/test/ui/for-loop-while/for-loop-has-unit-body.rs @@ -2,8 +2,8 @@ fn main() { // Check that the tail statement in the body unifies with something for _ in 0..3 { - #[allow(deprecated)] - unsafe { std::mem::uninitialized() } + // `()` is fine to zero-initialize as it is zero sized and inhabited. + unsafe { std::mem::zeroed() } } // Check that the tail statement in the body can be unit diff --git a/src/test/ui/issues/issue-48131.rs b/src/test/ui/issues/issue-48131.rs index c8540729352b2..85664e62eaded 100644 --- a/src/test/ui/issues/issue-48131.rs +++ b/src/test/ui/issues/issue-48131.rs @@ -1,7 +1,7 @@ // This note is annotated because the purpose of the test // is to ensure that certain other notes are not generated. #![deny(unused_unsafe)] //~ NOTE -#![allow(deprecated)] + // (test that no note is generated on this unsafe fn) pub unsafe fn a() { @@ -20,8 +20,8 @@ pub fn b() { unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe` //~^ NOTE } - - let () = ::std::mem::uninitialized(); + // `()` is fine to zero-initialize as it is zero sized and inhabited. + let () = ::std::mem::zeroed(); inner() } diff --git a/src/test/ui/issues/issue-58212.rs b/src/test/ui/issues/issue-58212.rs index 21dcdd56bf60c..4695497c3a184 100644 --- a/src/test/ui/issues/issue-58212.rs +++ b/src/test/ui/issues/issue-58212.rs @@ -1,13 +1,12 @@ -// run-pass +// check-pass trait FromUnchecked { - unsafe fn from_unchecked(); + fn from_unchecked(); } impl FromUnchecked for [u8; 1] { - unsafe fn from_unchecked() { - #[allow(deprecated)] - let mut array: Self = std::mem::uninitialized(); + fn from_unchecked() { + let mut array: Self = [0; 1]; let _ptr = &mut array as *mut [u8] as *mut u8; } } diff --git a/src/test/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs b/src/test/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs index 78d8e5e3a5dbf..7d15d607dd606 100644 --- a/src/test/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs +++ b/src/test/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs @@ -69,8 +69,10 @@ fn main() { unsafe { // This should be safe, because we don't match on it unless it's fully formed, // and it doesn't have a destructor. - #[allow(deprecated)] - let mut dest: MyEnum = mem::uninitialized(); + // + // MyEnum is repr(C, u8) so it is guaranteed to have a separate discriminant and each + // variant can be zero initialized. + let mut dest: MyEnum = mem::zeroed(); while buf.len() > 0 { match parse_my_enum(&mut dest, &mut buf) { Ok(()) => output.push(Ok(dest)), diff --git a/src/test/ui/structs-enums/enum-non-c-like-repr-c.rs b/src/test/ui/structs-enums/enum-non-c-like-repr-c.rs index 1209533efda82..fc9efdeca7d19 100644 --- a/src/test/ui/structs-enums/enum-non-c-like-repr-c.rs +++ b/src/test/ui/structs-enums/enum-non-c-like-repr-c.rs @@ -69,8 +69,11 @@ fn main() { unsafe { // This should be safe, because we don't match on it unless it's fully formed, // and it doesn't have a destructor. - #[allow(deprecated)] - let mut dest: MyEnum = mem::uninitialized(); + // + // Furthermore, there are no types within MyEnum which cannot be initialized with zero, + // specifically, though padding and such are present, there are no references or similar + // types. + let mut dest: MyEnum = mem::zeroed(); while buf.len() > 0 { match parse_my_enum(&mut dest, &mut buf) { Ok(()) => output.push(Ok(dest)), diff --git a/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs b/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs index 5dd9c1863d62d..f9e96c1a0f4ae 100644 --- a/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs +++ b/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs @@ -65,8 +65,10 @@ fn main() { unsafe { // This should be safe, because we don't match on it unless it's fully formed, // and it doesn't have a destructor. - #[allow(deprecated)] - let mut dest: MyEnum = mem::uninitialized(); + // + // MyEnum is repr(u8) so it is guaranteed to have a separate discriminant and each variant + // can be zero initialized. + let mut dest: MyEnum = mem::zeroed(); while buf.len() > 0 { match parse_my_enum(&mut dest, &mut buf) { Ok(()) => output.push(Ok(dest)), diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs index a5360fa13c4ea..e804afcf9ed99 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs @@ -1,5 +1,4 @@ -#![allow(deprecated)] - +use std::mem::zeroed; enum Void {} fn main() { @@ -8,21 +7,25 @@ fn main() { Ok(n) => n, }; - let x: &Void = unsafe { std::mem::uninitialized() }; + // This is pretty much instant UB. However, we have no choice -- we need to + // test matching on a reference to `&Void`; we cannot do anything other than + // just accept the fact that this is UB if `main` did run, but it doesn't; + // this test only checks that these are feature-gated. + let x: &Void = unsafe { zeroed() }; let _ = match x {}; //~ ERROR non-exhaustive - let x: (Void,) = unsafe { std::mem::uninitialized() }; + let x: (Void,) = unsafe { zeroed() }; let _ = match x {}; //~ ERROR non-exhaustive - let x: [Void; 1] = unsafe { std::mem::uninitialized() }; + let x: [Void; 1] = unsafe { zeroed() }; let _ = match x {}; //~ ERROR non-exhaustive - let x: &[Void] = unsafe { std::mem::uninitialized() }; + let x: &[Void] = unsafe { zeroed() }; let _ = match x { //~ ERROR non-exhaustive &[] => (), }; - let x: Void = unsafe { std::mem::uninitialized() }; + let x: Void = unsafe { zeroed() }; let _ = match x {}; // okay let x: Result = Ok(23); diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index 18ffdccb9b2db..a667e1fe2da3a 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:7:19 + --> $DIR/uninhabited-matches-feature-gated.rs:6:19 | LL | let _ = match x { | ^ pattern `Err(_)` not covered @@ -7,7 +7,7 @@ LL | let _ = match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `&Void` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:12:19 + --> $DIR/uninhabited-matches-feature-gated.rs:15:19 | LL | enum Void {} | ------------ `Void` defined here @@ -18,7 +18,7 @@ LL | let _ = match x {}; = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:15:19 + --> $DIR/uninhabited-matches-feature-gated.rs:18:19 | LL | let _ = match x {}; | ^ @@ -26,7 +26,7 @@ LL | let _ = match x {}; = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:18:19 + --> $DIR/uninhabited-matches-feature-gated.rs:21:19 | LL | let _ = match x {}; | ^ @@ -34,7 +34,7 @@ LL | let _ = match x {}; = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:21:19 + --> $DIR/uninhabited-matches-feature-gated.rs:24:19 | LL | let _ = match x { | ^ pattern `&[_, ..]` not covered @@ -42,7 +42,7 @@ LL | let _ = match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:29:19 + --> $DIR/uninhabited-matches-feature-gated.rs:32:19 | LL | let _ = match x { | ^ pattern `Err(_)` not covered @@ -50,7 +50,7 @@ LL | let _ = match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/uninhabited-matches-feature-gated.rs:34:9 + --> $DIR/uninhabited-matches-feature-gated.rs:37:9 | LL | let Ok(x) = x; | ^^^^^ pattern `Err(_)` not covered diff --git a/src/test/ui/uninit-empty-types.rs b/src/test/ui/uninit-empty-types.rs index 0d1235776a6ef..b21de882b2ceb 100644 --- a/src/test/ui/uninit-empty-types.rs +++ b/src/test/ui/uninit-empty-types.rs @@ -1,17 +1,19 @@ -// run-pass +// build-pass // Test the uninit() construct returning various empty types. // pretty-expanded FIXME #23616 -use std::mem; +use std::mem::MaybeUninit; -#[derive(Clone)] struct Foo; #[allow(deprecated)] pub fn main() { unsafe { - let _x: Foo = mem::uninitialized(); - let _x: [Foo; 2] = mem::uninitialized(); + // `Foo` and `[Foo; 2]` are both zero sized and inhabited, so this is safe. + let _x: Foo = MaybeUninit::uninit().assume_init(); + let _x: [Foo; 2] = MaybeUninit::uninit().assume_init(); + let _x: Foo = std::mem::uninitialized(); + let _x: [Foo; 2] = std::mem::uninitialized(); } }