]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #67538 - varkor:lhs-assign-diagnostics, r=Centril
authorMazdak Farrokhzad <twingoow@gmail.com>
Mon, 23 Dec 2019 14:16:29 +0000 (15:16 +0100)
committerGitHub <noreply@github.com>
Mon, 23 Dec 2019 14:16:29 +0000 (15:16 +0100)
Improve diagnostics for invalid assignment

- Improve wording and span information for invalid assignment diagnostics.
- Link to https://github.com/rust-lang/rfcs/issues/372 when it appears the user is trying a destructuring assignment.
- Make the equality constraint in `where` clauses error consistent with the invalid assignment error.

27 files changed:
src/libcore/intrinsics.rs
src/libcore/lib.rs
src/libcore/macros/mod.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/ty/constness.rs
src/librustc_lint/types.rs
src/librustc_typeck/check/demand.rs
src/librustdoc/html/static/main.js
src/libstd/io/cursor.rs
src/test/run-make-fulldeps/sanitizer-memory/Makefile
src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs [new file with mode: 0644]
src/test/run-make-fulldeps/sanitizer-memory/uninit.rs
src/test/rustdoc/issue-52873.rs
src/test/ui/abi/stack-probes.rs
src/test/ui/const-generics/issues/issue-61422.rs
src/test/ui/consts/const-eval/simd/insert_extract.rs
src/test/ui/consts/const-fn-type-name.rs
src/test/ui/for-loop-while/for-loop-has-unit-body.rs
src/test/ui/issues/issue-48131.rs
src/test/ui/issues/issue-58212.rs
src/test/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs
src/test/ui/structs-enums/enum-non-c-like-repr-c.rs
src/test/ui/structs-enums/enum-non-c-like-repr-int.rs
src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs
src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
src/test/ui/uninit-empty-types.rs

index e6bae4864a4e1721106d2040780a21c5b4a2e09a..502090731f4a159f04c25151a60f17721c63ced6 100644 (file)
@@ -1,6 +1,22 @@
 //! Compiler intrinsics.
 //!
 //! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
+//! The corresponding const implementations are in `librustc_mir/interpret/intrinsics.rs`
+//!
+//! # Const intrinsics
+//!
+//! Note: any changes to the constness of intrinsics should be discussed with the language team.
+//! This includes changes in the stability of the constness.
+//!
+//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
+//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
+//! `librustc_mir/interpret/intrinsics.rs` and add a
+//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
+//!
+//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
+//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
+//! without T-lang consulation, because it bakes a feature into the language that cannot be
+//! replicated in user code without compiler support.
 //!
 //! # Volatiles
 //!
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
+    #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
     /// Drop glue is not run on the destination.
     pub fn move_val_init<T>(dst: *mut T, src: T);
 
+    #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
+    #[rustc_const_unstable(feature = "const_pref_align_of", issue = "0")]
     pub fn pref_align_of<T>() -> usize;
 
     /// The size of the referenced value in bytes.
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
 
     /// Gets a static string slice containing the name of a type.
+    #[rustc_const_unstable(feature = "const_type_name", issue = "0")]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
+    #[rustc_const_unstable(feature = "const_type_id", issue = "0")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
     pub fn panic_if_uninhabited<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
+    #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
     /// Creates a value initialized to zero.
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
+    #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
 
     /// Calculates the offset from a pointer.
     pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
 
     /// Returns the number of bits set in an integer type `T`
+    #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
     pub fn ctpop<T>(x: T) -> T;
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
     /// let num_leading = ctlz(x);
     /// assert_eq!(num_leading, 16);
     /// ```
+    #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
     pub fn ctlz<T>(x: T) -> T;
 
     /// Like `ctlz`, but extra-unsafe as it returns `undef` when
     /// let num_leading = unsafe { ctlz_nonzero(x) };
     /// assert_eq!(num_leading, 3);
     /// ```
+    #[rustc_const_unstable(feature = "constctlz", issue = "0")]
     pub fn ctlz_nonzero<T>(x: T) -> T;
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
     /// let num_trailing = cttz(x);
     /// assert_eq!(num_trailing, 16);
     /// ```
+    #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
     pub fn cttz<T>(x: T) -> T;
 
     /// Like `cttz`, but extra-unsafe as it returns `undef` when
     /// let num_trailing = unsafe { cttz_nonzero(x) };
     /// assert_eq!(num_trailing, 3);
     /// ```
+    #[rustc_const_unstable(feature = "const_cttz", issue = "0")]
     pub fn cttz_nonzero<T>(x: T) -> T;
 
     /// Reverses the bytes in an integer type `T`.
+    #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
     pub fn bswap<T>(x: T) -> T;
 
     /// Reverses the bits in an integer type `T`.
+    #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
     pub fn bitreverse<T>(x: T) -> T;
 
     /// Performs checked integer addition.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_add` method. For example,
     /// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer subtraction
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_sub` method. For example,
     /// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer multiplication
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_mul` method. For example,
     /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs an exact division, resulting in undefined behavior where
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked addition, resulting in
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_left<T>(x: T, y: T) -> T;
 
     /// Performs rotate right.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_right<T>(x: T, y: T) -> T;
 
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_add<T>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T>(a: T, b: T) -> T;
 
     /// Computes `a + b`, while saturating at numeric bounds.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
+    #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T>(a: T, b: T) -> T;
     /// Computes `a - b`, while saturating at numeric bounds.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
     /// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
+    #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_sub<T>(a: T, b: T) -> T;
 
     /// Returns the value of the discriminant for the variant in 'v',
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 
     /// See documentation of `<*const T>::offset_from` for details.
+    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "0")]
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// Internal hook used by Miri to implement unwinding.
index 7c5e06ace67292b9bf9e34b36074aaa122b43fe6..d12aebb87b975a5a58e135881e47198feace7ce8 100644 (file)
 #![feature(maybe_uninit_slice)]
 #![feature(external_doc)]
 #![feature(associated_type_bounds)]
+#![feature(const_type_id)]
+#![feature(const_caller_location)]
 
 #[prelude_import]
 #[allow(unused)]
index 6c7ec2cbfe3219d744b45948a2a65fdc692c5833..1a3d338fb98767401bff787f1cf484d38ef4baf6 100644 (file)
@@ -5,6 +5,7 @@
     // the `caller_location` intrinsic, but once  `#[track_caller]` is implemented,
     // `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
     core_intrinsics,
+    const_caller_location,
 )]
 #[stable(feature = "core", since = "1.6.0")]
 macro_rules! panic {
index 83869951ea2a15afe36876aae620f6520955200f..a702eb839845e4aa55fa4853cd22211d1a81b557 100644 (file)
@@ -3437,65 +3437,3 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'hir>>) -> Vec<hir::BodyId>
     body_ids.sort_by_key(|b| bodies[b].value.span);
     body_ids
 }
-
-/// Checks if the specified expression is a built-in range literal.
-/// (See: `LoweringContext::lower_expr()`).
-pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
-    use hir::{Path, QPath, ExprKind, TyKind};
-
-    // Returns whether the given path represents a (desugared) range,
-    // either in std or core, i.e. has either a `::std::ops::Range` or
-    // `::core::ops::Range` prefix.
-    fn is_range_path(path: &Path) -> bool {
-        let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
-        let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
-
-        // "{{root}}" is the equivalent of `::` prefix in `Path`.
-        if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
-            (*std_core == "std" || *std_core == "core") && range.starts_with("Range")
-        } else {
-            false
-        }
-    };
-
-    // Check whether a span corresponding to a range expression is a
-    // range literal, rather than an explicit struct or `new()` call.
-    fn is_lit(sess: &Session, span: &Span) -> bool {
-        let source_map = sess.source_map();
-        let end_point = source_map.end_point(*span);
-
-        if let Ok(end_string) = source_map.span_to_snippet(end_point) {
-            !(end_string.ends_with("}") || end_string.ends_with(")"))
-        } else {
-            false
-        }
-    };
-
-    match expr.kind {
-        // All built-in range literals but `..=` and `..` desugar to `Struct`s.
-        ExprKind::Struct(ref qpath, _, _) => {
-            if let QPath::Resolved(None, ref path) = **qpath {
-                return is_range_path(&path) && is_lit(sess, &expr.span);
-            }
-        }
-
-        // `..` desugars to its struct path.
-        ExprKind::Path(QPath::Resolved(None, ref path)) => {
-            return is_range_path(&path) && is_lit(sess, &expr.span);
-        }
-
-        // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
-        ExprKind::Call(ref func, _) => {
-            if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
-                if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
-                    let new_call = segment.ident.name == sym::new;
-                    return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
-                }
-            }
-        }
-
-        _ => {}
-    }
-
-    false
-}
index 3c7860ae02fe7494fee6dcf840bc89d396f29aef..bf95324d776dc12fe0d87b1368781237f3b0eeb6 100644 (file)
 pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto};
 pub use syntax::ast::{CaptureBy, Constness, Movability, Mutability, Unsafety};
 use syntax::attr::{InlineAttr, OptimizeAttr};
-use syntax::source_map::Spanned;
-use syntax::symbol::{kw, Symbol};
 use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
+use syntax_pos::source_map::{SourceMap, Spanned};
+use syntax_pos::symbol::{kw, sym, Symbol};
 use syntax_pos::{MultiSpan, Span, DUMMY_SP};
 
 /// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
@@ -1564,6 +1564,68 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+/// Checks if the specified expression is a built-in range literal.
+/// (See: `LoweringContext::lower_expr()`).
+///
+/// FIXME(#60607): This function is a hack. If and when we have `QPath::Lang(...)`,
+/// we can use that instead as simpler, more reliable mechanism, as opposed to using `SourceMap`.
+pub fn is_range_literal(sm: &SourceMap, expr: &Expr) -> bool {
+    // Returns whether the given path represents a (desugared) range,
+    // either in std or core, i.e. has either a `::std::ops::Range` or
+    // `::core::ops::Range` prefix.
+    fn is_range_path(path: &Path) -> bool {
+        let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect();
+        let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
+
+        // "{{root}}" is the equivalent of `::` prefix in `Path`.
+        if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
+            (*std_core == "std" || *std_core == "core") && range.starts_with("Range")
+        } else {
+            false
+        }
+    };
+
+    // Check whether a span corresponding to a range expression is a
+    // range literal, rather than an explicit struct or `new()` call.
+    fn is_lit(sm: &SourceMap, span: &Span) -> bool {
+        let end_point = sm.end_point(*span);
+
+        if let Ok(end_string) = sm.span_to_snippet(end_point) {
+            !(end_string.ends_with("}") || end_string.ends_with(")"))
+        } else {
+            false
+        }
+    };
+
+    match expr.kind {
+        // All built-in range literals but `..=` and `..` desugar to `Struct`s.
+        ExprKind::Struct(ref qpath, _, _) => {
+            if let QPath::Resolved(None, ref path) = **qpath {
+                return is_range_path(&path) && is_lit(sm, &expr.span);
+            }
+        }
+
+        // `..` desugars to its struct path.
+        ExprKind::Path(QPath::Resolved(None, ref path)) => {
+            return is_range_path(&path) && is_lit(sm, &expr.span);
+        }
+
+        // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
+        ExprKind::Call(ref func, _) => {
+            if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind {
+                if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind {
+                    let new_call = segment.ident.name == sym::new;
+                    return is_range_path(&path) && is_lit(sm, &expr.span) && new_call;
+                }
+            }
+        }
+
+        _ => {}
+    }
+
+    false
+}
+
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum ExprKind {
     /// A `box x` expression.
index 897a3678c40046ee7700e682caa1d9d08890e5d5..7fe950ef7b7f6050268fcf4bd69a92e836f26070 100644 (file)
@@ -2,7 +2,7 @@
 use crate::hir::def_id::DefId;
 use crate::hir;
 use crate::ty::TyCtxt;
-use syntax_pos::symbol::{sym, Symbol};
+use syntax_pos::symbol::Symbol;
 use rustc_target::spec::abi::Abi;
 use crate::hir::map::blocks::FnLikeNode;
 use syntax::attr;
@@ -41,51 +41,12 @@ pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
         }
     }
 
-    /// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted
-    /// for being called from stable `const fn`s (`min_const_fn`).
-    ///
-    /// Adding more intrinsics requires sign-off from @rust-lang/lang.
-    ///
-    /// This list differs from the list in `is_const_intrinsic` in the sense that any item on this
-    /// list must be on the `is_const_intrinsic` list, too, because if an intrinsic is callable from
-    /// stable, it must be callable at all.
-    fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool {
-        match self.item_name(def_id) {
-            | sym::size_of
-            | sym::min_align_of
-            | sym::needs_drop
-            // Arithmetic:
-            | sym::add_with_overflow // ~> .overflowing_add
-            | sym::sub_with_overflow // ~> .overflowing_sub
-            | sym::mul_with_overflow // ~> .overflowing_mul
-            | sym::wrapping_add // ~> .wrapping_add
-            | sym::wrapping_sub // ~> .wrapping_sub
-            | sym::wrapping_mul // ~> .wrapping_mul
-            | sym::saturating_add // ~> .saturating_add
-            | sym::saturating_sub // ~> .saturating_sub
-            | sym::unchecked_shl // ~> .wrapping_shl
-            | sym::unchecked_shr // ~> .wrapping_shr
-            | sym::rotate_left // ~> .rotate_left
-            | sym::rotate_right // ~> .rotate_right
-            | sym::ctpop // ~> .count_ones
-            | sym::ctlz // ~> .leading_zeros
-            | sym::cttz // ~> .trailing_zeros
-            | sym::bswap // ~> .swap_bytes
-            | sym::bitreverse // ~> .reverse_bits
-            => true,
-            _ => false,
-        }
-    }
-
     /// Returns `true` if this function must conform to `min_const_fn`
     pub fn is_min_const_fn(self, def_id: DefId) -> bool {
         // Bail out if the signature doesn't contain `const`
         if !self.is_const_fn_raw(def_id) {
             return false;
         }
-        if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
-            return self.is_intrinsic_min_const_fn(def_id);
-        }
 
         if self.features().staged_api {
             // In order for a libstd function to be considered min_const_fn
@@ -134,62 +95,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option<bool> {
         match tcx.fn_sig(def_id).abi() {
             Abi::RustIntrinsic |
-            Abi::PlatformIntrinsic => {
-                // FIXME: deduplicate these two lists as much as possible
-                match tcx.item_name(def_id) {
-                    // Keep this list in the same order as the match patterns in
-                    // `librustc_mir/interpret/intrinsics.rs`
-
-                    // This whitelist is a list of intrinsics that have a miri-engine implementation
-                    // and can thus be called when enabling enough feature gates. The similar
-                    // whitelist in `is_intrinsic_min_const_fn` (in this file), exists for allowing
-                    // the intrinsics to be called by stable const fns.
-                    | sym::caller_location
-
-                    | sym::min_align_of
-                    | sym::pref_align_of
-                    | sym::needs_drop
-                    | sym::size_of
-                    | sym::type_id
-                    | sym::type_name
-
-                    | sym::ctpop
-                    | sym::cttz
-                    | sym::cttz_nonzero
-                    | sym::ctlz
-                    | sym::ctlz_nonzero
-                    | sym::bswap
-                    | sym::bitreverse
-
-                    | sym::wrapping_add
-                    | sym::wrapping_sub
-                    | sym::wrapping_mul
-                    | sym::add_with_overflow
-                    | sym::sub_with_overflow
-                    | sym::mul_with_overflow
-
-                    | sym::saturating_add
-                    | sym::saturating_sub
-
-                    | sym::unchecked_shl
-                    | sym::unchecked_shr
-
-                    | sym::rotate_left
-                    | sym::rotate_right
-
-                    | sym::ptr_offset_from
-
-                    | sym::transmute
-
-                    | sym::simd_insert
-
-                    | sym::simd_extract
-
-                    => Some(true),
-
-                    _ => Some(false)
-                }
-            }
+            Abi::PlatformIntrinsic => Some(tcx.lookup_const_stability(def_id).is_some()),
             _ => None
         }
     }
index 8c9279d025d8008751c7c3924bada09a2bfb5d61..45b8666c42b45d111aa081b3b1c8c4f00601991a 100644 (file)
@@ -3,8 +3,7 @@
 use crate::hir::def_id::DefId;
 use lint::{LateContext, LintArray, LintContext};
 use lint::{LateLintPass, LintPass};
-use rustc::hir::lowering::is_range_literal;
-use rustc::hir::{ExprKind, Node};
+use rustc::hir::{is_range_literal, ExprKind, Node};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
@@ -266,7 +265,7 @@ fn lint_int_literal<'a, 'tcx>(
         let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
         if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
             if let hir::ExprKind::Struct(..) = par_e.kind {
-                if is_range_literal(cx.sess(), par_e)
+                if is_range_literal(cx.sess().source_map(), par_e)
                     && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
                 {
                     // The overflowing literal lint was overridden.
@@ -318,7 +317,7 @@ fn lint_uint_literal<'a, 'tcx>(
                         return;
                     }
                 }
-                hir::ExprKind::Struct(..) if is_range_literal(cx.sess(), par_e) => {
+                hir::ExprKind::Struct(..) if is_range_literal(cx.sess().source_map(), par_e) => {
                     let t = t.name_str();
                     if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
                         // The overflowing literal lint was overridden.
index d63d30b7b8d83c53af330254ad9370eb84822925..9a14b75ca2f4dc4ec66be06434e117e04ba1efe4 100644 (file)
@@ -3,9 +3,7 @@
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 
 use errors::{Applicability, DiagnosticBuilder};
-use rustc::hir;
-use rustc::hir::Node;
-use rustc::hir::{lowering::is_range_literal, print};
+use rustc::hir::{self, is_range_literal, print, Node};
 use rustc::ty::adjustment::AllowTwoPhase;
 use rustc::ty::{self, AssocItem, Ty};
 use syntax::symbol::sym;
@@ -478,7 +476,7 @@ pub fn check_ref(
                             // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
                             // parenthesize borrows of range literals (Issue #54505)
-                            _ if is_range_literal(self.tcx.sess, expr) => true,
+                            _ if is_range_literal(self.tcx.sess.source_map(), expr) => true,
                             _ => false,
                         };
                         let sugg_expr = if needs_parens { format!("({})", src) } else { src };
index 1459e8f37cd32ff23e474001e7a31c06edc9dd6e..8ccb74d6f15d3b7c025e8d0c8c8b3cf57f380d17 100644 (file)
@@ -138,6 +138,22 @@ function getSearchElement() {
         }
     }
 
+    function showSearchResults(search) {
+        if (search === null || typeof search === 'undefined') {
+            search = getSearchElement();
+        }
+        addClass(main, "hidden");
+        removeClass(search, "hidden");
+    }
+
+    function hideSearchResults(search) {
+        if (search === null || typeof search === 'undefined') {
+            search = getSearchElement();
+        }
+        addClass(search, "hidden");
+        removeClass(main, "hidden");
+    }
+
     // used for special search precedence
     var TY_PRIMITIVE = itemTypes.indexOf("primitive");
     var TY_KEYWORD = itemTypes.indexOf("keyword");
@@ -169,8 +185,7 @@ function getSearchElement() {
         if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
             // This block occurs when clicking on an element in the navbar while
             // in a search.
-            addClass(search, "hidden");
-            removeClass(main, "hidden");
+            hideSearchResults(search);
             var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
             if (browserSupportsHistoryApi()) {
                 history.replaceState(hash, "", "?search=#" + hash);
@@ -331,8 +346,7 @@ function getSearchElement() {
             displayHelp(false, ev, help);
         } else if (hasClass(search, "hidden") === false) {
             ev.preventDefault();
-            addClass(search, "hidden");
-            removeClass(main, "hidden");
+            hideSearchResults(search);
             document.title = titleBeforeSearch;
         }
         defocusSearchBar();
@@ -390,8 +404,8 @@ function getSearchElement() {
         return null;
     }
 
-    document.onkeypress = handleShortcut;
-    document.onkeydown = handleShortcut;
+    document.addEventListener("keypress", handleShortcut);
+    document.addEventListener("keydown", handleShortcut);
 
     var handleSourceHighlight = (function() {
         var prev_line_id = 0;
@@ -430,7 +444,7 @@ function getSearchElement() {
         }
     })();
 
-    document.onclick = function(ev) {
+    document.addEventListener("click", function(ev) {
         if (hasClass(ev.target, "collapse-toggle")) {
             collapseDocs(ev.target, "toggle");
         } else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
@@ -452,7 +466,7 @@ function getSearchElement() {
                 expandSection(a.hash.replace(/^#/, ""));
             }
         }
-    };
+    });
 
     var x = document.getElementsByClassName("version-selector");
     if (x.length > 0) {
@@ -1264,8 +1278,7 @@ function getSearchElement() {
                 }
                 dst = dst[0];
                 if (window.location.pathname === dst.pathname) {
-                    addClass(getSearchElement(), "hidden");
-                    removeClass(main, "hidden");
+                    hideSearchResults();
                     document.location.href = dst.href;
                 }
             };
@@ -1340,8 +1353,6 @@ function getSearchElement() {
                     e.preventDefault();
                 } else if (e.which === 16) { // shift
                     // Does nothing, it's just to avoid losing "focus" on the highlighted element.
-                } else if (e.which === 27) { // escape
-                    handleEscape(e);
                 } else if (actives[currentTab].length > 0) {
                     removeClass(actives[currentTab][0], "highlighted");
                 }
@@ -1491,10 +1502,9 @@ function getSearchElement() {
                 "</div><div id=\"results\">" +
                 ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
 
-            addClass(main, "hidden");
             var search = getSearchElement();
-            removeClass(search, "hidden");
             search.innerHTML = output;
+            showSearchResults(search);
             var tds = search.getElementsByTagName("td");
             var td_width = 0;
             if (tds.length > 0) {
@@ -1699,13 +1709,7 @@ function getSearchElement() {
                     if (browserSupportsHistoryApi()) {
                         history.replaceState("", window.currentCrate + " - Rust", "?search=");
                     }
-                    if (hasClass(main, "content")) {
-                        removeClass(main, "hidden");
-                    }
-                    var search_c = getSearchElement();
-                    if (hasClass(search_c, "content")) {
-                        addClass(search_c, "hidden");
-                    }
+                    hideSearchResults();
                 } else {
                     searchTimeout = setTimeout(search, 500);
                 }
@@ -1718,6 +1722,10 @@ function getSearchElement() {
                 search();
             };
             search_input.onchange = function(e) {
+                if (e.target !== document.activeElement) {
+                    // To prevent doing anything when it's from a blur event.
+                    return;
+                }
                 // Do NOT e.preventDefault() here. It will prevent pasting.
                 clearTimeout(searchTimeout);
                 // zero-timeout necessary here because at the time of event handler execution the
@@ -1741,19 +1749,8 @@ function getSearchElement() {
                 // Store the previous <title> so we can revert back to it later.
                 var previousTitle = document.title;
 
-                window.onpopstate = function(e) {
+                window.addEventListener("popstate", function(e) {
                     var params = getQueryStringParams();
-                    // When browsing back from search results the main page
-                    // visibility must be reset.
-                    if (!params.search) {
-                        if (hasClass(main, "content")) {
-                            removeClass(main, "hidden");
-                        }
-                        var search_c = getSearchElement();
-                        if (hasClass(search_c, "content")) {
-                            addClass(search_c, "hidden");
-                        }
-                    }
                     // Revert to the previous title manually since the History
                     // API ignores the title parameter.
                     document.title = previousTitle;
@@ -1765,18 +1762,21 @@ function getSearchElement() {
                     // perform the search. This will empty the bar if there's
                     // nothing there, which lets you really go back to a
                     // previous state with nothing in the bar.
-                    if (params.search) {
+                    if (params.search && params.search.length > 0) {
                         search_input.value = params.search;
+                        // Some browsers fire "onpopstate" for every page load
+                        // (Chrome), while others fire the event only when actually
+                        // popping a state (Firefox), which is why search() is
+                        // called both here and at the end of the startSearch()
+                        // function.
+                        search(e);
                     } else {
                         search_input.value = "";
+                        // When browsing back from search results the main page
+                        // visibility must be reset.
+                        hideSearchResults();
                     }
-                    // Some browsers fire "onpopstate" for every page load
-                    // (Chrome), while others fire the event only when actually
-                    // popping a state (Firefox), which is why search() is
-                    // called both here and at the end of the startSearch()
-                    // function.
-                    search();
-                };
+                });
             }
             search();
         }
@@ -2522,9 +2522,9 @@ function getSearchElement() {
     }
 
     function putBackSearch(search_input) {
-        if (search_input.value !== "") {
-            addClass(main, "hidden");
-            removeClass(getSearchElement(), "hidden");
+        var search = getSearchElement();
+        if (search_input.value !== "" && hasClass(search, "hidden")) {
+            showSearchResults(search);
             if (browserSupportsHistoryApi()) {
                 history.replaceState(search_input.value,
                                      "",
@@ -2541,10 +2541,9 @@ function getSearchElement() {
 
     var params = getQueryStringParams();
     if (params && params.search) {
-        addClass(main, "hidden");
         var search = getSearchElement();
-        removeClass(search, "hidden");
         search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>";
+        showSearchResults(search);
     }
 
     var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
index 1492f70436c262b5d80d6da8a3ceceb4ef177bc9..9787cbb556bd237ba7c76bfaee5142c981cc303e 100644 (file)
@@ -72,7 +72,7 @@
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
 pub struct Cursor<T> {
     inner: T,
     pos: u64,
@@ -942,4 +942,16 @@ fn vec_seek_and_write_past_usize_max() {
         c.set_position(<usize>::max_value() as u64 + 1);
         assert!(c.write_all(&[1, 2, 3]).is_err());
     }
+
+    #[test]
+    fn test_partial_eq() {
+        assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new()));
+    }
+
+    #[test]
+    fn test_eq() {
+        struct AssertEq<T: Eq>(pub T);
+
+        let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new()));
+    }
 }
index b3376f8a72358d3dd80e3e07c5ae5a2c7d523e9c..f5787903a2b594e3e6f440e3c6f25f086423da7d 100644 (file)
@@ -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 (file)
index 0000000..a9ae85f
--- /dev/null
@@ -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];
+}
index cb857e3bc38d352561278f03ec51216deba01f94..eae52508f658543ee92825830af6aebe13176880 100644 (file)
@@ -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];
 }
index 653c004c04b231c2606ce5f879dca7d4fb0b8d4c..8000ce73bd42fcc2db36b8ef1809c2a96726260d 100644 (file)
@@ -105,8 +105,7 @@ fn add(self, _: B0) -> Self::Output {
 impl<U: Unsigned> Add<U> for UTerm {
     type Output = U;
     fn add(self, _: U) -> Self::Output {
-        #[allow(deprecated)]
-        unsafe { ::std::mem::uninitialized() }
+        unimplemented!()
     }
 }
 
@@ -137,7 +136,7 @@ impl<Ul: Unsigned, B: Bit, Ur: Unsigned> Mul<UInt<Ur, B>> for UInt<Ul, B0>
 {
     type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
     fn mul(self, _: UInt<Ur, B>) -> Self::Output {
-        unsafe { ::std::mem::uninitialized() }
+        unimplemented!()
     }
 }
 
index 1ab1d6df66d4b95ac3c9c84103c70704bf886c59..1d5b362e29dfe9e276b36e96b0243b0bb32c1f3e 100644 (file)
@@ -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::<Vec<_>>();
     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);
 }
 
index 45d37b6a2f3c5d115214bb5dd00954e94f112ad0..4fa150ffef09ecd2384e4e58d6d23823269c3d78 100644 (file)
@@ -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<const SIZE: usize>() {
     let arr: [u8; SIZE] = unsafe {
         #[allow(deprecated)]
@@ -13,4 +17,12 @@ fn foo<const SIZE: usize>() {
     };
 }
 
+fn bar<const SIZE: usize>() {
+    let arr: [u8; SIZE] = unsafe {
+        let array: [u8; SIZE] = mem::MaybeUninit::uninit().assume_init();
+        array
+    };
+}
+
+
 fn main() {}
index d3462d802ea4e9c6fd666edabea7d54baac0b13b..92231d4ced321ea9f87d0ff529ed9deedbca36b2 100644 (file)
@@ -2,6 +2,8 @@
 #![feature(const_fn)]
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
+#![feature(staged_api)]
+#![stable(feature = "foo", since = "1.33.7")]
 #![allow(non_camel_case_types)]
 
 #[repr(simd)] struct i8x1(i8);
@@ -9,7 +11,9 @@
 #[repr(simd)] struct f32x3(f32, f32, f32);
 
 extern "platform-intrinsic" {
+    #[rustc_const_stable(feature = "foo", since = "1.3.37")]
     fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
+    #[rustc_const_stable(feature = "foo", since = "1.3.37")]
     fn simd_extract<T, U>(x: T, idx: u32) -> U;
 }
 
index 2bb1aeecf376d9d8abdc97779d5fd5a38f9b6695..72fac19c191739171f29d3e6fcd5c4380d8086d6 100644 (file)
@@ -2,6 +2,7 @@
 
 #![feature(core_intrinsics)]
 #![feature(const_fn)]
+#![feature(const_type_name)]
 #![allow(dead_code)]
 
 const fn type_name_wrapper<T>(_: &T) -> &'static str {
index 38c34d2dc2e6f8fbc7802b706aa4267a7418d977..eba385461b951e192ed400d39745c969a3f90d1c 100644 (file)
@@ -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
index c8540729352b270111be4af7913aa6e94d55972b..85664e62eaded5ee6c62ce5f4b37b20a134e28fe 100644 (file)
@@ -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 @@ fn inner() {
             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()
     }
index 21dcdd56bf60c1289926e27f0c21c88495af8d15..4695497c3a184881567d1b6515a66bce68e90168 100644 (file)
@@ -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;
     }
 }
index 78d8e5e3a5dbf39e9abf8059883df24647bdf652..7d15d607dd60619837139a78a7c173ff8e9151c6 100644 (file)
@@ -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)),
index 1209533efda82097f7564bfa2e4f9294398e83d5..fc9efdeca7d19bc3d42341ec7b430f22b6e926f3 100644 (file)
@@ -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)),
index 5dd9c1863d62da2b00b5343e8c4b35d956c59803..f9e96c1a0f4aeb71717c6e260325e1af7c114be5 100644 (file)
@@ -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)),
index a5360fa13c4ea22f730ed317413532b976db2976..e804afcf9ed99bf214a9ea4d51f1f48c2eacfcd3 100644 (file)
@@ -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<u32, Void> = Ok(23);
index 18ffdccb9b2db89ac024975770363525c4e7e70c..a667e1fe2da3a99eb6624b44fafca854874c15ac 100644 (file)
@@ -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
index 0d1235776a6ef7574e8d48286067ed836c28e0d4..b21de882b2ceb95bf684c52824106c438dab6b58 100644 (file)
@@ -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();
     }
 }