diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 82160080a44d4..ce7681c974a5d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1876,16 +1876,70 @@ declare_lint_pass!(InvalidValue => [INVALID_VALUE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) { - const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; - const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + #[derive(Debug, Copy, Clone, PartialEq)] + enum InitKind { Zeroed, Uninit }; /// Information about why a type cannot be initialized this way. /// Contains an error message and optionally a span to point at. type InitError = (String, Option); + /// Test if this constant is all-0. + fn is_zero(expr: &hir::Expr) -> bool { + use hir::ExprKind::*; + use syntax::ast::LitKind::*; + match &expr.node { + Lit(lit) => + if let Int(i, _) = lit.node { + i == 0 + } else { + false + }, + Tup(tup) => + tup.iter().all(is_zero), + _ => + false + } + } + + /// Determine if this expression is a "dangerous initialization". + fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { + const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; + const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + // `transmute` is inside an anonymous module (the `extern` block?); + // `Invalid` represents the empty string and matches that. + const TRANSMUTE_PATH: &[Symbol] = + &[sym::core, sym::intrinsics, kw::Invalid, sym::transmute]; + + if let hir::ExprKind::Call(ref path_expr, ref args) = expr.node { + if let hir::ExprKind::Path(ref qpath) = path_expr.node { + let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + + if cx.match_def_path(def_id, ZEROED_PATH) { + return Some(InitKind::Zeroed); + } + if cx.match_def_path(def_id, UININIT_PATH) { + return Some(InitKind::Uninit); + } + if cx.match_def_path(def_id, TRANSMUTE_PATH) { + if is_zero(&args[0]) { + return Some(InitKind::Zeroed); + } + } + // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and + // `MaybeUninit::uninit().assume_init()`. + } + } + + None + } + /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. - fn ty_find_init_error<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + fn ty_find_init_error<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + init: InitKind, + ) -> Option { use rustc::ty::TyKind::*; match ty.sty { // Primitive types that don't like 0 as a value. @@ -1893,8 +1947,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), - // Recurse for some compound types. + // Primitive types with other constraints. + Bool if init == InitKind::Uninit => + Some((format!("Booleans must be `true` or `false`"), None)), + Char if init == InitKind::Uninit => + Some((format!("Characters must be a valid unicode codepoint"), None)), + // Recurse and checks for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { + // First check f this ADT has a layout attribute (like `NonNull` and friends). + use std::ops::Bound; + match tcx.layout_scalar_valid_range(adt_def.did) { + // We exploit here that `layout_scalar_valid_range` will never + // return `Bound::Excluded`. (And we have tests checking that we + // handle the attribute correctly.) + (Bound::Included(lo), _) if lo > 0 => + return Some((format!("{} must be non-null", ty), None)), + (Bound::Included(_), _) | (_, Bound::Included(_)) + if init == InitKind::Uninit => + return Some(( + format!("{} must be initialized inside its custom valid range", ty), + None, + )), + _ => {} + } + // Now, recurse. match adt_def.variants.len() { 0 => Some((format!("0-variant enums have no valid value"), None)), 1 => { @@ -1905,6 +1981,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { ty_find_init_error( tcx, field.ty(tcx, substs), + init, ).map(|(mut msg, span)| if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. @@ -1918,57 +1995,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { }) }) } + // Multi-variant enums are tricky: if all but one variant are + // uninhabited, we might actually do layout like for a single-variant + // enum, and then even leaving them uninitialized could be okay. _ => None, // Conservative fallback for multi-variant enum. } } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field)) + ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } - // FIXME: Would be nice to also warn for `NonNull`/`NonZero*`. - // FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`, - // `char`, and any multivariant enum. // Conservative fallback. _ => None, } } - if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node { - if let hir::ExprKind::Path(ref qpath) = path_expr.node { - if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if cx.match_def_path(def_id, &ZEROED_PATH) || - cx.match_def_path(def_id, &UININIT_PATH) - { - // This conjures an instance of a type out of nothing, - // using zeroed or uninitialized memory. - // We are extremely conservative with what we warn about. - let conjured_ty = cx.tables.expr_ty(expr); - if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { - let mut err = cx.struct_span_lint( - INVALID_VALUE, - expr.span, - &format!( - "the type `{}` does not permit {}", - conjured_ty, - if cx.match_def_path(def_id, &ZEROED_PATH) { - "zero-initialization" - } else { - "being left uninitialized" - } - ), - ); - err.span_label(expr.span, - "this code causes undefined behavior when executed"); - err.span_label(expr.span, "help: use `MaybeUninit` instead"); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - } - } + if let Some(init) = is_dangerous_init(cx, expr) { + // This conjures an instance of a type out of nothing, + // using zeroed or uninitialized memory. + // We are extremely conservative with what we warn about. + let conjured_ty = cx.tables.expr_ty(expr); + if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { + let mut err = cx.struct_span_lint( + INVALID_VALUE, + expr.span, + &format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + ), + ); + err.span_label(expr.span, + "this code causes undefined behavior when executed"); + err.span_label(expr.span, "help: use `MaybeUninit` instead"); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); } + err.emit(); } } } diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 431ff356ade19..9edae1965ce16 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -1,5 +1,5 @@ #![feature(rustc_attrs, const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; use std::ptr::NonNull; diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 0d8f30159b316..bbab85c2121a5 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs index 0a427cd8857e8..baab14dc16141 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ b/src/test/ui/consts/const-eval/ub-upvars.rs @@ -1,5 +1,5 @@ #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index d816479bbbbe3..5cf62b8691239 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -2,11 +2,13 @@ // This test checks that calling `mem::{uninitialized,zeroed}` with certain types results // in a lint. -#![feature(never_type)] +#![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 {} @@ -16,6 +18,11 @@ 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); + #[allow(unused)] fn generic() { unsafe { @@ -29,6 +36,7 @@ fn generic() { 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 @@ -56,11 +64,28 @@ fn main() { 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 - // Some types that should work just fine. + let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = 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 + + // 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 + + // 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 = mem::zeroed(); let _val: i32 = mem::zeroed(); } } diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 1b15fc2152559..a36a32a39a11b 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:22:32 + --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:23:32 + --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:25:38 + --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:26:38 + --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:32:23 + --> $DIR/uninitialized-zeroed.rs:40:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:33:23 + --> $DIR/uninitialized-zeroed.rs:41:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:35:30 + --> $DIR/uninitialized-zeroed.rs:43:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:36:30 + --> $DIR/uninitialized-zeroed.rs:44:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:38:26 + --> $DIR/uninitialized-zeroed.rs:46:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:39:26 + --> $DIR/uninitialized-zeroed.rs:47:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:34 + --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:34 + --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:25 + --> $DIR/uninitialized-zeroed.rs:52:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:25 + --> $DIR/uninitialized-zeroed.rs:53:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:47:26 + --> $DIR/uninitialized-zeroed.rs:55:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:48:26 + --> $DIR/uninitialized-zeroed.rs:56:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:50:32 + --> $DIR/uninitialized-zeroed.rs:58:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:51:32 + --> $DIR/uninitialized-zeroed.rs:59:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:53:36 + --> $DIR/uninitialized-zeroed.rs:61:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:54:36 + --> $DIR/uninitialized-zeroed.rs:62:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:56:42 + --> $DIR/uninitialized-zeroed.rs:64:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:57:42 + --> $DIR/uninitialized-zeroed.rs:65:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,10 +280,102 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 22 previous errors +error: the type `std::ptr::NonNull` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:67:34 + | +LL | let _val: NonNull = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::ptr::NonNull must be non-null + +error: the type `std::ptr::NonNull` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:68:34 + | +LL | let _val: NonNull = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::ptr::NonNull must be non-null + +error: the type `bool` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:72:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: Booleans must be `true` or `false` + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:75:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | +note: Characters must be a valid unicode codepoint (in this struct field) + --> $DIR/uninitialized-zeroed.rs:18:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:78:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: NonBig must be initialized inside its custom valid range + +error: the type `&'static i32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:81:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `&'static [i32]` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:82:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `std::num::NonZeroU32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:83:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::num::NonZeroU32 must be non-null + +error: aborting due to 30 previous errors