From c19daa472b69fdcbbb15402e8d1e8e05bae39f38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 22:56:01 +0200 Subject: make invalid_value lint a bit smarter around enums --- .../validate_uninhabited_zsts.32bit.stderr | 8 +- .../validate_uninhabited_zsts.64bit.stderr | 8 +- src/test/ui/lint/invalid_value.rs | 159 ++++++ src/test/ui/lint/invalid_value.stderr | 611 +++++++++++++++++++++ src/test/ui/lint/uninitialized-zeroed.rs | 137 ----- src/test/ui/lint/uninitialized-zeroed.stderr | 528 ------------------ src/test/ui/statics/uninhabited-static.stderr | 12 +- 7 files changed, 788 insertions(+), 675 deletions(-) create mode 100644 src/test/ui/lint/invalid_value.rs create mode 100644 src/test/ui/lint/invalid_value.stderr delete mode 100644 src/test/ui/lint/uninitialized-zeroed.rs delete mode 100644 src/test/ui/lint/uninitialized-zeroed.stderr (limited to 'src/test') diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr index bdaeb4a0fbe..b568518b449 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: enums with no variants have no valid value (in this struct field) - --> $DIR/validate_uninhabited_zsts.rs:16:22 +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 | -LL | pub struct Empty(Void); - | ^^^^ +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr index bdaeb4a0fbe..b568518b449 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | -note: enums with no variants have no valid value (in this struct field) - --> $DIR/validate_uninhabited_zsts.rs:16:22 +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 | -LL | pub struct Empty(Void); - | ^^^^ +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/src/test/ui/lint/invalid_value.rs b/src/test/ui/lint/invalid_value.rs new file mode 100644 index 00000000000..c37a472ffe1 --- /dev/null +++ b/src/test/ui/lint/invalid_value.rs @@ -0,0 +1,159 @@ +// This test checks that calling `mem::{uninitialized,zeroed}` with certain types results +// in a lint. + +#![feature(never_type, rustc_attrs)] +#![allow(deprecated)] +#![deny(invalid_value)] + +use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; +use std::num::NonZeroU32; + +enum Void {} + +struct Ref(&'static i32); +struct RefPair((&'static i32, i32)); + +struct Wrap { wrapped: T } +enum WrapEnum { Wrapped(T) } + +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + +/// A two-variant enum, thus needs a tag and may not remain uninitialized. +enum Fruit { + Apple, + Banana, +} + +/// Looks like two variants but really only has one. +enum OneFruit { + Apple(!), + Banana, +} + +enum OneFruitNonZero { + Apple(!), + Banana(NonZeroU32), +} + +enum TwoUninhabited { + A(!), + B(!), +} + +#[allow(unused)] +fn generic() { + unsafe { + let _val: &'static T = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static T = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<&'static T> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<&'static T> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + } +} + +fn main() { + unsafe { + // Things that cannot even be zero. + let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: (i32, !) = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: (i32, !) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Void = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Void = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: &'static i32 = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Ref = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Ref = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: fn() = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: fn() = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: WrapEnum = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: WrapEnum = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Fruit = mem::zeroed(); + let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [bool; 2] = mem::zeroed(); + let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: i32 = mem::zeroed(); + let _val: i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: f32 = mem::zeroed(); + let _val: f32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const () = mem::zeroed(); + let _val: *const () = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const [()] = mem::zeroed(); + let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things where 0 is okay due to rustc implementation details, + // but that are not guaranteed to keep working. + let _val: Result = mem::zeroed(); + let _val: Result = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Some things that happen to work due to rustc implementation details, + // but are not guaranteed to keep working. + let _val: OneFruit = mem::zeroed(); + let _val: OneFruit = mem::uninitialized(); + + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + + // `MaybeUninit` cases + let _val: NonNull = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + + // Some more types that should work just fine. + let _val: Option<&'static i32> = mem::zeroed(); + let _val: Option = mem::zeroed(); + let _val: MaybeUninit<&'static i32> = mem::zeroed(); + let _val: bool = MaybeUninit::zeroed().assume_init(); + let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); + let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); + } +} diff --git a/src/test/ui/lint/invalid_value.stderr b/src/test/ui/lint/invalid_value.stderr new file mode 100644 index 00000000000..750b3c76c44 --- /dev/null +++ b/src/test/ui/lint/invalid_value.stderr @@ -0,0 +1,611 @@ +error: the type `&T` does not permit zero-initialization + --> $DIR/invalid_value.rs:50:32 + | +LL | let _val: &'static T = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: the lint level is defined here + --> $DIR/invalid_value.rs:6:9 + | +LL | #![deny(invalid_value)] + | ^^^^^^^^^^^^^ + = note: references must be non-null + +error: the type `&T` does not permit being left uninitialized + --> $DIR/invalid_value.rs:51:32 + | +LL | let _val: &'static T = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Wrap<&T>` does not permit zero-initialization + --> $DIR/invalid_value.rs:53:38 + | +LL | let _val: Wrap<&'static T> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap<&T>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:54:38 + | +LL | let _val: Wrap<&'static T> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `!` does not permit zero-initialization + --> $DIR/invalid_value.rs:61:23 + | +LL | let _val: ! = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `!` does not permit being left uninitialized + --> $DIR/invalid_value.rs:62:23 + | +LL | let _val: ! = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit zero-initialization + --> $DIR/invalid_value.rs:64:30 + | +LL | let _val: (i32, !) = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit being left uninitialized + --> $DIR/invalid_value.rs:65:30 + | +LL | let _val: (i32, !) = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: integers must not be uninitialized + +error: the type `Void` does not permit zero-initialization + --> $DIR/invalid_value.rs:67:26 + | +LL | let _val: Void = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `Void` does not permit being left uninitialized + --> $DIR/invalid_value.rs:68:26 + | +LL | let _val: Void = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:70:34 + | +LL | let _val: &'static i32 = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:71:34 + | +LL | let _val: &'static i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Ref` does not permit zero-initialization + --> $DIR/invalid_value.rs:73:25 + | +LL | let _val: Ref = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `Ref` does not permit being left uninitialized + --> $DIR/invalid_value.rs:74:25 + | +LL | let _val: Ref = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `fn()` does not permit zero-initialization + --> $DIR/invalid_value.rs:76:26 + | +LL | let _val: fn() = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `fn()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:77:26 + | +LL | let _val: fn() = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `Wrap` does not permit zero-initialization + --> $DIR/invalid_value.rs:79:32 + | +LL | let _val: Wrap = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/invalid_value.rs:80:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `WrapEnum` does not permit zero-initialization + --> $DIR/invalid_value.rs:82:36 + | +LL | let _val: WrapEnum = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum { Wrapped(T) } + | ^ + +error: the type `WrapEnum` does not permit being left uninitialized + --> $DIR/invalid_value.rs:83:36 + | +LL | let _val: WrapEnum = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum { Wrapped(T) } + | ^ + +error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization + --> $DIR/invalid_value.rs:85:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:86:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `NonNull` does not permit zero-initialization + --> $DIR/invalid_value.rs:88:34 + | +LL | let _val: NonNull = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `NonNull` does not permit being left uninitialized + --> $DIR/invalid_value.rs:89:34 + | +LL | let _val: NonNull = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `*const dyn Send` does not permit zero-initialization + --> $DIR/invalid_value.rs:91:37 + | +LL | let _val: *const dyn Send = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `*const dyn Send` does not permit being left uninitialized + --> $DIR/invalid_value.rs:92:37 + | +LL | let _val: *const dyn Send = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `[fn(); 2]` does not permit zero-initialization + --> $DIR/invalid_value.rs:94:31 + | +LL | let _val: [fn(); 2] = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `[fn(); 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:95:31 + | +LL | let _val: [fn(); 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `TwoUninhabited` does not permit zero-initialization + --> $DIR/invalid_value.rs:97:36 + | +LL | let _val: TwoUninhabited = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `TwoUninhabited` does not permit being left uninitialized + --> $DIR/invalid_value.rs:98:36 + | +LL | let _val: TwoUninhabited = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit zero-initialization + --> $DIR/invalid_value.rs:100:37 + | +LL | let _val: OneFruitNonZero = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit being left uninitialized + --> $DIR/invalid_value.rs:101:37 + | +LL | let _val: OneFruitNonZero = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:105:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/invalid_value.rs:108:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: characters must be a valid Unicode codepoint (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/invalid_value.rs:111:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `NonBig` must be initialized inside its custom valid range + +error: the type `Fruit` does not permit being left uninitialized + --> $DIR/invalid_value.rs:114:27 + | +LL | let _val: Fruit = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $DIR/invalid_value.rs:26:1 + | +LL | enum Fruit { + | ^^^^^^^^^^ + +error: the type `[bool; 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:117:31 + | +LL | let _val: [bool; 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:120:25 + | +LL | let _val: i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: integers must not be uninitialized + +error: the type `f32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:123:25 + | +LL | let _val: f32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: floats must not be uninitialized + +error: the type `*const ()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:126:31 + | +LL | let _val: *const () = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must not be uninitialized + +error: the type `*const [()]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:129:33 + | +LL | let _val: *const [()] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must not be uninitialized + +error: the type `Result` does not permit being left uninitialized + --> $DIR/invalid_value.rs:134:38 + | +LL | let _val: Result = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $SRC_DIR/core/src/result.rs:LL:COL + | +LL | pub enum Result { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:142:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&[i32]` does not permit zero-initialization + --> $DIR/invalid_value.rs:143:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `NonZeroU32` does not permit zero-initialization + --> $DIR/invalid_value.rs:144:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + +error: the type `NonNull` does not permit zero-initialization + --> $DIR/invalid_value.rs:147:34 + | +LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `NonNull` does not permit being left uninitialized + --> $DIR/invalid_value.rs:148:34 + | +LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:149:26 + | +LL | let _val: bool = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: aborting due to 48 previous errors + diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs deleted file mode 100644 index dae258407eb..00000000000 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ /dev/null @@ -1,137 +0,0 @@ -// This test checks that calling `mem::{uninitialized,zeroed}` with certain types results -// in a lint. - -#![feature(never_type, rustc_attrs)] -#![allow(deprecated)] -#![deny(invalid_value)] - -use std::mem::{self, MaybeUninit}; -use std::ptr::NonNull; -use std::num::NonZeroU32; - -enum Void {} - -struct Ref(&'static i32); -struct RefPair((&'static i32, i32)); - -struct Wrap { wrapped: T } -enum WrapEnum { Wrapped(T) } - -#[rustc_layout_scalar_valid_range_start(0)] -#[rustc_layout_scalar_valid_range_end(128)] -#[repr(transparent)] -pub(crate) struct NonBig(u64); - -/// A two-variant enum, thus needs a tag and may not remain uninitialized. -enum Fruit { - Apple, - Banana, -} - -/// Looks like two variants but really only has one. -enum OneFruit { - Apple(!), - Banana, -} - -#[allow(unused)] -fn generic() { - unsafe { - let _val: &'static T = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: &'static T = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Wrap<&'static T> = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Wrap<&'static T> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - } -} - -fn main() { - unsafe { - // Things that cannot even be zero. - let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: (i32, !) = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: (i32, !) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Void = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Void = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: &'static i32 = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: &'static i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Ref = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Ref = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: fn() = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: fn() = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Wrap = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: WrapEnum = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: WrapEnum = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - // Things that can be zero, but not uninit. - let _val: bool = mem::zeroed(); - let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Wrap = mem::zeroed(); - let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: NonBig = mem::zeroed(); - let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: Fruit = mem::zeroed(); - let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: [bool; 2] = mem::zeroed(); - let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: i32 = mem::zeroed(); - let _val: i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: f32 = mem::zeroed(); - let _val: f32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: *const () = mem::zeroed(); - let _val: *const () = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - let _val: *const [()] = mem::zeroed(); - let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - - // Transmute-from-0 - let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization - let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization - let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization - - // `MaybeUninit` cases - let _val: NonNull = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization - let _val: NonNull = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized - let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized - - // Some more types that should work just fine. - let _val: Option<&'static i32> = mem::zeroed(); - let _val: Option = mem::zeroed(); - let _val: MaybeUninit<&'static i32> = mem::zeroed(); - let _val: bool = MaybeUninit::zeroed().assume_init(); - let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); - let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); - - // Some things that happen to work due to rustc implementation details, - // but are not guaranteed to keep working. - let _val: OneFruit = mem::uninitialized(); - } -} diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr deleted file mode 100644 index b46042e7be4..00000000000 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ /dev/null @@ -1,528 +0,0 @@ -error: the type `&T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:40:32 - | -LL | let _val: &'static T = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: the lint level is defined here - --> $DIR/uninitialized-zeroed.rs:6:9 - | -LL | #![deny(invalid_value)] - | ^^^^^^^^^^^^^ - = note: references must be non-null - -error: the type `&T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:41:32 - | -LL | let _val: &'static T = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: references must be non-null - -error: the type `Wrap<&T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:43:38 - | -LL | let _val: Wrap<&'static T> = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 - | -LL | struct Wrap { wrapped: T } - | ^^^^^^^^^^ - -error: the type `Wrap<&T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:44:38 - | -LL | let _val: Wrap<&'static T> = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 - | -LL | struct Wrap { wrapped: T } - | ^^^^^^^^^^ - -error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:51:23 - | -LL | let _val: ! = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: the `!` type has no valid value - -error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:52:23 - | -LL | let _val: ! = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: the `!` type has no valid value - -error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:54:30 - | -LL | let _val: (i32, !) = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: the `!` type has no valid value - -error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:55:30 - | -LL | let _val: (i32, !) = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: integers must not be uninitialized - -error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:57:26 - | -LL | let _val: Void = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: enums with no variants have no valid value - -error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:58:26 - | -LL | let _val: Void = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: enums with no variants have no valid value - -error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:60:34 - | -LL | let _val: &'static i32 = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: references must be non-null - -error: the type `&i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:61:34 - | -LL | let _val: &'static i32 = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: references must be non-null - -error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:63:25 - | -LL | let _val: Ref = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 - | -LL | struct Ref(&'static i32); - | ^^^^^^^^^^^^ - -error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:64:25 - | -LL | let _val: Ref = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 - | -LL | struct Ref(&'static i32); - | ^^^^^^^^^^^^ - -error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:66:26 - | -LL | let _val: fn() = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: function pointers must be non-null - -error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:67:26 - | -LL | let _val: fn() = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: function pointers must be non-null - -error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:69:32 - | -LL | let _val: Wrap = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 - | -LL | struct Wrap { wrapped: T } - | ^^^^^^^^^^ - -error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:70:32 - | -LL | let _val: Wrap = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 - | -LL | struct Wrap { wrapped: T } - | ^^^^^^^^^^ - -error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:72:36 - | -LL | let _val: WrapEnum = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 - | -LL | enum WrapEnum { Wrapped(T) } - | ^ - -error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:73:36 - | -LL | let _val: WrapEnum = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 - | -LL | enum WrapEnum { Wrapped(T) } - | ^ - -error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:75:42 - | -LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 - | -LL | struct RefPair((&'static i32, i32)); - | ^^^^^^^^^^^^^^^^^^^ - -error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:76:42 - | -LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: references must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 - | -LL | struct RefPair((&'static i32, i32)); - | ^^^^^^^^^^^^^^^^^^^ - -error: the type `NonNull` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:78:34 - | -LL | let _val: NonNull = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `std::ptr::NonNull` must be non-null - -error: the type `NonNull` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:79:34 - | -LL | let _val: NonNull = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `std::ptr::NonNull` must be non-null - -error: the type `*const dyn Send` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:81:37 - | -LL | let _val: *const dyn Send = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: the vtable of a wide raw pointer must be non-null - -error: the type `*const dyn Send` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:82:37 - | -LL | let _val: *const dyn Send = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: the vtable of a wide raw pointer must be non-null - -error: the type `[fn(); 2]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:84:31 - | -LL | let _val: [fn(); 2] = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: function pointers must be non-null - -error: the type `[fn(); 2]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:85:31 - | -LL | let _val: [fn(); 2] = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: function pointers must be non-null - -error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:89:26 - | -LL | let _val: bool = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: booleans must be either `true` or `false` - -error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:92:32 - | -LL | let _val: Wrap = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: characters must be a valid Unicode codepoint (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 - | -LL | struct Wrap { wrapped: T } - | ^^^^^^^^^^ - -error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:95:28 - | -LL | let _val: NonBig = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `NonBig` must be initialized inside its custom valid range - -error: the type `Fruit` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:98:27 - | -LL | let _val: Fruit = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | -note: enums have to be initialized to a variant - --> $DIR/uninitialized-zeroed.rs:26:1 - | -LL | enum Fruit { - | ^^^^^^^^^^ - -error: the type `[bool; 2]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:101:31 - | -LL | let _val: [bool; 2] = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: booleans must be either `true` or `false` - -error: the type `i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:104:25 - | -LL | let _val: i32 = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: integers must not be uninitialized - -error: the type `f32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:107:25 - | -LL | let _val: f32 = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: floats must not be uninitialized - -error: the type `*const ()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:110:31 - | -LL | let _val: *const () = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: raw pointers must not be uninitialized - -error: the type `*const [()]` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:113:33 - | -LL | let _val: *const [()] = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: raw pointers must not be uninitialized - -error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:116:34 - | -LL | let _val: &'static i32 = mem::transmute(0usize); - | ^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: references must be non-null - -error: the type `&[i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:117:36 - | -LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: references must be non-null - -error: the type `NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:118:32 - | -LL | let _val: NonZeroU32 = mem::transmute(0); - | ^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `std::num::NonZeroU32` must be non-null - -error: the type `NonNull` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:121:34 - | -LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `std::ptr::NonNull` must be non-null - -error: the type `NonNull` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:122:34 - | -LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: `std::ptr::NonNull` must be non-null - -error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:123:26 - | -LL | let _val: bool = MaybeUninit::uninit().assume_init(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - | - = note: booleans must be either `true` or `false` - -error: aborting due to 43 previous errors - diff --git a/src/test/ui/statics/uninhabited-static.stderr b/src/test/ui/statics/uninhabited-static.stderr index 88ee4cbdc2e..6d37de8ff3f 100644 --- a/src/test/ui/statics/uninhabited-static.stderr +++ b/src/test/ui/statics/uninhabited-static.stderr @@ -59,7 +59,11 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `#[warn(invalid_value)]` on by default - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ error[E0080]: could not evaluate static initializer --> $DIR/uninhabited-static.rs:16:32 @@ -76,7 +80,11 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; | this code causes undefined behavior when executed | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | - = note: enums with no variants have no valid value +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ error: aborting due to 6 previous errors; 2 warnings emitted -- cgit 1.4.1-3-g733a5