From 00d537dcd03f9ff5ebdf8b86e039dbdb0a7f850c Mon Sep 17 00:00:00 2001
From: Marcel Hellwig <git@cookiesoft.de>
Date: Thu, 2 Jul 2020 09:32:41 +0200
Subject: [PATCH 01/32] deny(unsafe_op_in_unsafe_fn) in libstd/path.rs

---
 library/std/src/path.rs | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index e3d529df7de16..92c0f61972c83 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -60,6 +60,7 @@
 //! [`push`]: PathBuf::push
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 use crate::borrow::{Borrow, Cow};
 use crate::cmp;
@@ -293,7 +294,8 @@ fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
     unsafe { &*(s as *const OsStr as *const [u8]) }
 }
 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
-    &*(s as *const [u8] as *const OsStr)
+    // SAFETY: see the comment of `os_str_as_u8_slice`
+    unsafe { &*(s as *const [u8] as *const OsStr) }
 }
 
 // Detect scheme on Redox
@@ -313,24 +315,21 @@ fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
 
 // basic workhorse for splitting stem and extension
 fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
-    unsafe {
-        if os_str_as_u8_slice(file) == b".." {
-            return (Some(file), None);
-        }
-
-        // The unsafety here stems from converting between &OsStr and &[u8]
-        // and back. This is safe to do because (1) we only look at ASCII
-        // contents of the encoding and (2) new &OsStr values are produced
-        // only from ASCII-bounded slices of existing &OsStr values.
-
-        let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
-        let after = iter.next();
-        let before = iter.next();
-        if before == Some(b"") {
-            (Some(file), None)
-        } else {
-            (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s)))
-        }
+    if os_str_as_u8_slice(file) == b".." {
+        return (Some(file), None);
+    }
+
+    // The unsafety here stems from converting between &OsStr and &[u8]
+    // and back. This is safe to do because (1) we only look at ASCII
+    // contents of the encoding and (2) new &OsStr values are produced
+    // only from ASCII-bounded slices of existing &OsStr values.
+    let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
+    let after = iter.next();
+    let before = iter.next();
+    if before == Some(b"") {
+        (Some(file), None)
+    } else {
+        unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) }
     }
 }
 
@@ -1701,7 +1700,7 @@ impl Path {
     // The following (private!) function allows construction of a path from a u8
     // slice, which is only safe when it is known to follow the OsStr encoding.
     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
-        Path::new(u8_slice_as_os_str(s))
+        unsafe { Path::new(u8_slice_as_os_str(s)) }
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
     fn as_u8_slice(&self) -> &[u8] {

From 0f2bd56b29857453835e47abbe96a80b175632d1 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Mon, 3 Aug 2020 11:08:03 +0100
Subject: [PATCH 02/32] lint/ty: move fns to avoid abstraction violation

This commit moves `transparent_newtype_field` and `is_zst` to
`LateContext` where they are used, rather than being on the `VariantDef`
and `TyS` types.

Signed-off-by: David Wood <david@davidtw.co>
---
 compiler/rustc_lint/src/builtin.rs  |  6 +++---
 compiler/rustc_lint/src/types.rs    | 26 +++++++++++++++++++++++---
 compiler/rustc_middle/src/ty/mod.rs | 15 +--------------
 compiler/rustc_middle/src/ty/sty.rs |  5 -----
 4 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ea624b9ed3003..694455171e9ec 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -21,7 +21,8 @@
 //! `late_lint_methods!` invocation in `lib.rs`.
 
 use crate::{
-    types::CItemKind, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
+    types::{transparent_newtype_field, CItemKind},
+    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
 };
 use rustc_ast::attr::{self, HasAttrs};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -2180,8 +2181,7 @@ impl ClashingExternDeclarations {
                         if is_transparent && !is_non_null {
                             debug_assert!(def.variants.len() == 1);
                             let v = &def.variants[VariantIdx::new(0)];
-                            ty = v
-                                .transparent_newtype_field(tcx)
+                            ty = transparent_newtype_field(tcx, v)
                                 .expect(
                                     "single-variant transparent structure with zero-sized field",
                                 )
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 35c462c24c8e8..132e9286f6b3b 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -533,6 +533,26 @@ crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtD
         .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed))
 }
 
+/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
+/// field.
+pub fn transparent_newtype_field<'a, 'tcx>(
+    tcx: TyCtxt<'tcx>,
+    variant: &'a ty::VariantDef,
+) -> Option<&'a ty::FieldDef> {
+    let param_env = tcx.param_env(variant.def_id);
+    for field in &variant.fields {
+        let field_ty = tcx.type_of(field.did);
+        let is_zst =
+            tcx.layout_of(param_env.and(field_ty)).map(|layout| layout.is_zst()).unwrap_or(false);
+
+        if !is_zst {
+            return Some(field);
+        }
+    }
+
+    None
+}
+
 /// Is type known to be non-null?
 crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool {
     let tcx = cx.tcx;
@@ -548,7 +568,7 @@ crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: C
             }
 
             for variant in &def.variants {
-                if let Some(field) = variant.transparent_newtype_field(tcx) {
+                if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
                     if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
                         return true;
                     }
@@ -569,7 +589,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
         ty::Adt(field_def, field_substs) => {
             let inner_field_ty = {
                 let first_non_zst_ty =
-                    field_def.variants.iter().filter_map(|v| v.transparent_newtype_field(tcx));
+                    field_def.variants.iter().filter_map(|v| transparent_newtype_field(cx.tcx, v));
                 debug_assert_eq!(
                     first_non_zst_ty.clone().count(),
                     1,
@@ -710,7 +730,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         if def.repr.transparent() {
             // Can assume that only one field is not a ZST, so only check
             // that field's type for FFI-safety.
-            if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) {
+            if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
                 self.check_field_type_for_ffi(cache, field, substs)
             } else {
                 bug!("malformed transparent type");
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b6300a40b0d8d..8027bed2c8cf0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2005,7 +2005,7 @@ pub struct VariantDef {
     flags: VariantFlags,
 }
 
-impl<'tcx> VariantDef {
+impl VariantDef {
     /// Creates a new `VariantDef`.
     ///
     /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
@@ -2071,19 +2071,6 @@ impl<'tcx> VariantDef {
     pub fn is_recovered(&self) -> bool {
         self.flags.intersects(VariantFlags::IS_RECOVERED)
     }
-
-    /// `repr(transparent)` structs can have a single non-ZST field, this function returns that
-    /// field.
-    pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> {
-        for field in &self.fields {
-            let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id));
-            if !field_ty.is_zst(tcx, self.def_id) {
-                return Some(field);
-            }
-        }
-
-        None
-    }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c1f354c7a15f3..2af3fb7f8638a 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2280,9 +2280,4 @@ impl<'tcx> TyS<'tcx> {
             }
         }
     }
-
-    /// Is this a zero-sized type?
-    pub fn is_zst(&'tcx self, tcx: TyCtxt<'tcx>, did: DefId) -> bool {
-        tcx.layout_of(tcx.param_env(did).and(self)).map(|layout| layout.is_zst()).unwrap_or(false)
-    }
 }

From db109c662e4bc4a8d81aaa69e6bd37c43d191259 Mon Sep 17 00:00:00 2001
From: CDirkx <christiaan@dirkx.com>
Date: Mon, 31 Aug 2020 02:11:48 +0200
Subject: [PATCH 03/32] Stabilize some Option methods as const

Stabilize the following methods of `Option` as const:
 - `is_some`
 - `is_none`
 - `as_ref`

Possible because of stabilization of #49146 (Allow if and match in constants).
---
 library/core/src/option.rs         | 6 +++---
 src/test/ui/consts/const-option.rs | 2 --
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index dd7556758be7d..fa0f917c79dca 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -175,7 +175,7 @@ impl<T> Option<T> {
     /// ```
     #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
     #[inline]
-    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_some(&self) -> bool {
         matches!(*self, Some(_))
@@ -195,7 +195,7 @@ impl<T> Option<T> {
     #[must_use = "if you intended to assert that this doesn't have a value, consider \
                   `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"]
     #[inline]
-    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_none(&self) -> bool {
         !self.is_some()
@@ -254,7 +254,7 @@ impl<T> Option<T> {
     /// println!("still can print text: {:?}", text);
     /// ```
     #[inline]
-    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn as_ref(&self) -> Option<&T> {
         match *self {
diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs
index fbf20b9db6741..793f78c8d20fa 100644
--- a/src/test/ui/consts/const-option.rs
+++ b/src/test/ui/consts/const-option.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(const_option)]
-
 const X: Option<i32> = Some(32);
 const Y: Option<&i32> = X.as_ref();
 

From 04e4a391985994f7ccb579eae530b52d704eb887 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Fri, 4 Sep 2020 00:13:25 +0200
Subject: [PATCH 04/32] Move const tests for `Option` to `library\core`

Part of #76268
---
 library/core/tests/option.rs       | 16 ++++++++++++++++
 src/test/ui/consts/const-option.rs | 12 ------------
 2 files changed, 16 insertions(+), 12 deletions(-)
 delete mode 100644 src/test/ui/consts/const-option.rs

diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index fa308160fc228..5049ba954c7a2 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -357,3 +357,19 @@ fn test_replace() {
     assert_eq!(x, Some(3));
     assert_eq!(old, None);
 }
+
+#[test]
+fn option_const() {
+    // test that the methods of `Option` are usable in a const context
+
+    const OPTION: Option<usize> = Some(32);
+
+    const REF: Option<&usize> = OPTION.as_ref();
+    assert_eq!(REF, Some(&32));
+
+    const IS_SOME: bool = OPTION.is_some();
+    assert!(IS_SOME);
+
+    const IS_NONE: bool = OPTION.is_none();
+    assert!(!IS_NONE);
+}
diff --git a/src/test/ui/consts/const-option.rs b/src/test/ui/consts/const-option.rs
deleted file mode 100644
index 793f78c8d20fa..0000000000000
--- a/src/test/ui/consts/const-option.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-
-const X: Option<i32> = Some(32);
-const Y: Option<&i32> = X.as_ref();
-
-const IS_SOME: bool = X.is_some();
-const IS_NONE: bool = Y.is_none();
-
-fn main() {
-    assert!(IS_SOME);
-    assert!(!IS_NONE)
-}

From 6092828d1f432bb313818e7cfab961c0e494f69e Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Thu, 3 Sep 2020 19:59:51 -0700
Subject: [PATCH 05/32] Add `[T; N]: TryFrom<Vec<T>>`

This is very similar to the existing `Box<[T; N]>: TryFrom<Box<[T]>>`, but allows avoiding the `shrink_to_fit` if you have a vector and not a boxed slice.
---
 library/alloc/src/vec.rs | 52 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 9013e3fc16ab9..b6d923daaf2ab 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -55,6 +55,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use core::cmp::{self, Ordering};
+use core::convert::TryFrom;
 use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::intrinsics::{arith_offset, assume};
@@ -2771,6 +2772,57 @@ impl From<&str> for Vec<u8> {
     }
 }
 
+#[stable(feature = "array_try_from_vec", since = "1.47.0")]
+impl<T, const N: usize> TryFrom<Vec<T>> for [T; N] {
+    type Error = Vec<T>;
+
+    /// Gets the entire contents of the `Vec<T>` as an array,
+    /// if its size exactly matches that of the requested array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::convert::TryInto;
+    /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
+    /// assert_eq!(<Vec<i32>>::new().try_into(), Ok([]));
+    /// ```
+    ///
+    /// If the length doesn't match, the input comes back in `Err`:
+    /// ```
+    /// use std::convert::TryInto;
+    /// let r: Result<[i32; 4], _> = (0..10).collect::<Vec<_>>().try_into();
+    /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
+    /// ```
+    ///
+    /// If you're fine with just getting a prefix of the `Vec<T>`,
+    /// you can call [`.truncate(N)`](Vec::truncate) first.
+    /// ```
+    /// use std::convert::TryInto;
+    /// let mut v = String::from("hello world").into_bytes();
+    /// v.sort();
+    /// v.truncate(2);
+    /// let [a, b]: [_; 2] = v.try_into().unwrap();
+    /// assert_eq!(a, b' ');
+    /// assert_eq!(b, b'd');
+    /// ```
+    fn try_from(mut vec: Vec<T>) -> Result<[T; N], Vec<T>> {
+        if vec.len() != N {
+            return Err(vec);
+        }
+
+        // SAFETY: `.set_len(0)` is always sound.
+        unsafe { vec.set_len(0) };
+
+        // SAFETY: A `Vec`'s pointer is always aligned property, and
+        // the alignment the array needs is the same as the items.
+        // We checked earlier that we have sufficient items.
+        // The items will not double-drop as the `set_len`
+        // tells the `Vec` not to also drop them.
+        let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) };
+        Ok(array)
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Clone-on-write
 ////////////////////////////////////////////////////////////////////////////////

From 6cb671628393e292d5e68e6367f80488ace46532 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
Date: Sun, 16 Aug 2020 03:01:38 +0000
Subject: [PATCH 06/32] Add test for checking if-let or-patterns

---
 src/test/mir-opt/issues/issue-75439.rs        | 21 +++++
 ...e_75439.foo.MatchBranchSimplification.diff | 87 +++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 src/test/mir-opt/issues/issue-75439.rs
 create mode 100644 src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff

diff --git a/src/test/mir-opt/issues/issue-75439.rs b/src/test/mir-opt/issues/issue-75439.rs
new file mode 100644
index 0000000000000..44d6bc619d3bb
--- /dev/null
+++ b/src/test/mir-opt/issues/issue-75439.rs
@@ -0,0 +1,21 @@
+// EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff
+
+#![feature(const_fn_transmute)]
+#![feature(or_patterns)]
+
+use std::mem::transmute;
+
+pub fn foo(bytes: [u8; 16]) -> Option<[u8; 4]> {
+    // big endian `u32`s
+    let dwords: [u32; 4] = unsafe { transmute(bytes) };
+    const FF: u32 = 0x0000_ffff_u32.to_be();
+    if let [0, 0, 0 | FF, ip] = dwords {
+        Some(unsafe { transmute(ip) })
+    } else {
+        None
+    }
+}
+
+fn main() {
+  let _ = foo([0; 16]);
+}
diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
new file mode 100644
index 0000000000000..43422b36e1e52
--- /dev/null
+++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -0,0 +1,87 @@
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+  
+  fn foo(_1: [u8; 16]) -> Option<[u8; 4]> {
+      debug bytes => _1;                   // in scope 0 at $DIR/issue-75439.rs:8:12: 8:17
+      let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:8:32: 8:47
+      let _2: [u32; 4];                    // in scope 0 at $DIR/issue-75439.rs:10:9: 10:15
+      let mut _3: [u8; 16];                // in scope 0 at $DIR/issue-75439.rs:10:47: 10:52
+      let mut _5: [u8; 4];                 // in scope 0 at $DIR/issue-75439.rs:13:14: 13:38
+      let mut _6: u32;                     // in scope 0 at $DIR/issue-75439.rs:13:33: 13:35
+      scope 1 {
+          debug dwords => _2;              // in scope 1 at $DIR/issue-75439.rs:10:9: 10:15
+          let _4: u32;                     // in scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          scope 3 {
+              debug ip => _4;              // in scope 3 at $DIR/issue-75439.rs:12:27: 12:29
+              scope 4 {
+              }
+          }
+      }
+      scope 2 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/issue-75439.rs:10:9: 10:15
+          StorageLive(_3);                 // scope 2 at $DIR/issue-75439.rs:10:47: 10:52
+          _3 = _1;                         // scope 2 at $DIR/issue-75439.rs:10:47: 10:52
+          _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:10:37: 10:53
+                                           // mir::Constant
+                                           // + span: $DIR/issue-75439.rs:10:37: 10:46
+                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {std::intrinsics::transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          StorageDead(_3);                 // scope 2 at $DIR/issue-75439.rs:10:52: 10:53
+          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:13: 12:14
+      }
+  
+      bb2: {
+          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:16: 12:17
+      }
+  
+      bb3: {
+          switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:19: 12:20
+      }
+  
+      bb4: {
+          discriminant(_0) = 0;            // scope 1 at $DIR/issue-75439.rs:15:9: 15:13
+          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb5: {
+          StorageLive(_5);                 // scope 3 at $DIR/issue-75439.rs:13:14: 13:38
+          StorageLive(_6);                 // scope 4 at $DIR/issue-75439.rs:13:33: 13:35
+          _6 = _4;                         // scope 4 at $DIR/issue-75439.rs:13:33: 13:35
+          _5 = transmute::<u32, [u8; 4]>(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:13:23: 13:36
+                                           // mir::Constant
+                                           // + span: $DIR/issue-75439.rs:13:23: 13:32
+                                           // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::<u32, [u8; 4]>}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb6: {
+          StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb7: {
+          StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:12:27: 12:29
+          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb8: {
+          StorageDead(_6);                 // scope 4 at $DIR/issue-75439.rs:13:35: 13:36
+          ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39
+          discriminant(_0) = 1;            // scope 3 at $DIR/issue-75439.rs:13:9: 13:39
+          StorageDead(_5);                 // scope 3 at $DIR/issue-75439.rs:13:38: 13:39
+          StorageDead(_4);                 // scope 1 at $DIR/issue-75439.rs:14:5: 14:6
+          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:12:5: 16:6
+      }
+  
+      bb9: {
+          StorageDead(_2);                 // scope 0 at $DIR/issue-75439.rs:17:1: 17:2
+          return;                          // scope 0 at $DIR/issue-75439.rs:17:2: 17:2
+      }
+  }
+  

From 2c8a4c8f73e8b36e72b15e7f97ef29ad36c15e17 Mon Sep 17 00:00:00 2001
From: scottmcm <scottmcm@users.noreply.github.com>
Date: Sat, 5 Sep 2020 19:02:21 +0000
Subject: [PATCH 07/32] Nightly is currently 1.48

---
 library/alloc/src/vec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index b6d923daaf2ab..4a263829bd421 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -2772,7 +2772,7 @@ impl From<&str> for Vec<u8> {
     }
 }
 
-#[stable(feature = "array_try_from_vec", since = "1.47.0")]
+#[stable(feature = "array_try_from_vec", since = "1.48.0")]
 impl<T, const N: usize> TryFrom<Vec<T>> for [T; N] {
     type Error = Vec<T>;
 

From 685f04220ee584f00f60e5ff9d7aca16351c5399 Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Sun, 6 Sep 2020 12:00:22 +0800
Subject: [PATCH 08/32] Clean up vec benches bench_in_place style

---
 library/alloc/benches/vec.rs | 43 ++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index 5ba3e0e00572c..6703a99b15155 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -457,9 +457,7 @@ fn bench_clone_from_10_1000_0100(b: &mut Bencher) {
 }
 
 macro_rules! bench_in_place {
-    (
-        $($fname:ident, $type:ty , $count:expr, $init: expr);*
-    ) => {
+    ($($fname:ident, $type:ty, $count:expr, $init:expr);*) => {
         $(
             #[bench]
             fn $fname(b: &mut Bencher) {
@@ -467,7 +465,8 @@ macro_rules! bench_in_place {
                     let src: Vec<$type> = black_box(vec![$init; $count]);
                     let mut sink = src.into_iter()
                         .enumerate()
-                        .map(|(idx, e)| { (idx as $type) ^ e }).collect::<Vec<$type>>();
+                        .map(|(idx, e)| idx as $type ^ e)
+                        .collect::<Vec<$type>>();
                     black_box(sink.as_mut_ptr())
                 });
             }
@@ -476,24 +475,24 @@ macro_rules! bench_in_place {
 }
 
 bench_in_place![
-    bench_in_place_xxu8_i0_0010,     u8,     10, 0;
-    bench_in_place_xxu8_i0_0100,     u8,    100, 0;
-    bench_in_place_xxu8_i0_1000,     u8,   1000, 0;
-    bench_in_place_xxu8_i1_0010,     u8,     10, 1;
-    bench_in_place_xxu8_i1_0100,     u8,    100, 1;
-    bench_in_place_xxu8_i1_1000,     u8,   1000, 1;
-    bench_in_place_xu32_i0_0010,    u32,     10, 0;
-    bench_in_place_xu32_i0_0100,    u32,    100, 0;
-    bench_in_place_xu32_i0_1000,    u32,   1000, 0;
-    bench_in_place_xu32_i1_0010,    u32,     10, 1;
-    bench_in_place_xu32_i1_0100,    u32,    100, 1;
-    bench_in_place_xu32_i1_1000,    u32,   1000, 1;
-    bench_in_place_u128_i0_0010,   u128,     10, 0;
-    bench_in_place_u128_i0_0100,   u128,    100, 0;
-    bench_in_place_u128_i0_1000,   u128,   1000, 0;
-    bench_in_place_u128_i1_0010,   u128,     10, 1;
-    bench_in_place_u128_i1_0100,   u128,    100, 1;
-    bench_in_place_u128_i1_1000,   u128,   1000, 1
+    bench_in_place_xxu8_0010_i0,   u8,   10, 0;
+    bench_in_place_xxu8_0100_i0,   u8,  100, 0;
+    bench_in_place_xxu8_1000_i0,   u8, 1000, 0;
+    bench_in_place_xxu8_0010_i1,   u8,   10, 1;
+    bench_in_place_xxu8_0100_i1,   u8,  100, 1;
+    bench_in_place_xxu8_1000_i1,   u8, 1000, 1;
+    bench_in_place_xu32_0010_i0,  u32,   10, 0;
+    bench_in_place_xu32_0100_i0,  u32,  100, 0;
+    bench_in_place_xu32_1000_i0,  u32, 1000, 0;
+    bench_in_place_xu32_0010_i1,  u32,   10, 1;
+    bench_in_place_xu32_0100_i1,  u32,  100, 1;
+    bench_in_place_xu32_1000_i1,  u32, 1000, 1;
+    bench_in_place_u128_0010_i0, u128,   10, 0;
+    bench_in_place_u128_0100_i0, u128,  100, 0;
+    bench_in_place_u128_1000_i0, u128, 1000, 0;
+    bench_in_place_u128_0010_i1, u128,   10, 1;
+    bench_in_place_u128_0100_i1, u128,  100, 1;
+    bench_in_place_u128_1000_i1, u128, 1000, 1
 ];
 
 #[bench]

From 3d89ee9586354e736cfe4a472d8aaa507d10f77c Mon Sep 17 00:00:00 2001
From: scottmcm <scottmcm@users.noreply.github.com>
Date: Mon, 7 Sep 2020 02:30:42 +0000
Subject: [PATCH 09/32] Typo fix

Thanks, Amanieu

Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
---
 library/alloc/src/vec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index 4a263829bd421..ccba23f684877 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -2813,7 +2813,7 @@ impl<T, const N: usize> TryFrom<Vec<T>> for [T; N] {
         // SAFETY: `.set_len(0)` is always sound.
         unsafe { vec.set_len(0) };
 
-        // SAFETY: A `Vec`'s pointer is always aligned property, and
+        // SAFETY: A `Vec`'s pointer is always aligned properly, and
         // the alignment the array needs is the same as the items.
         // We checked earlier that we have sufficient items.
         // The items will not double-drop as the `set_len`

From caeb5544ecd9dba4d67b68b8c1b32d8132c6d5f2 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 7 Sep 2020 11:31:37 +0200
Subject: [PATCH 10/32] do not inline black_box when building for Miri

---
 library/core/src/hint.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index d40a380286762..a7b8c2f373a9e 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -108,7 +108,8 @@ pub fn spin_loop() {
 /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
 /// extent to which it can block optimisations may vary depending upon the platform and code-gen
 /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
-#[inline]
+#[cfg_attr(not(miri), inline)]
+#[cfg_attr(miri, inline(never))]
 #[unstable(feature = "test", issue = "50297")]
 #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
 pub fn black_box<T>(dummy: T) -> T {

From 4b5cd544d1268df8f95424a7dc77ce6c852bac56 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 7 Sep 2020 11:37:35 +0200
Subject: [PATCH 11/32] use black_box instead of local optimziation barriers in
 const tests where possible

---
 .../ui/consts/cast-discriminant-zst-enum.rs     | 14 ++++++--------
 src/test/ui/consts/const_discriminant.rs        | 17 ++++++-----------
 2 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index a77258120111e..743043609ec32 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,5 +1,6 @@
 // run-pass
 // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32.
+use std::hint::black_box;
 
 #[derive(Copy, Clone)]
 enum Nums {
@@ -12,9 +13,6 @@ const NEG_ONE_I32: i32 = Nums::NegOne as i32;
 const NEG_ONE_I64: i64 = Nums::NegOne as i64;
 const NEG_ONE_I128: i128 = Nums::NegOne as i128;
 
-#[inline(never)]
-fn identity<T>(t: T) -> T { t }
-
 fn test_as_arg(n: Nums) {
     assert_eq!(-1i8, n as i8);
     assert_eq!(-1i16, n as i16);
@@ -31,11 +29,11 @@ fn main() {
     assert_eq!(-1i64, kind as i64);
     assert_eq!(-1i128, kind as i128);
 
-    assert_eq!(-1i8, identity(kind) as i8);
-    assert_eq!(-1i16, identity(kind) as i16);
-    assert_eq!(-1i32, identity(kind) as i32);
-    assert_eq!(-1i64, identity(kind) as i64);
-    assert_eq!(-1i128, identity(kind) as i128);
+    assert_eq!(-1i8, black_box(kind) as i8);
+    assert_eq!(-1i16, black_box(kind) as i16);
+    assert_eq!(-1i32, black_box(kind) as i32);
+    assert_eq!(-1i64, black_box(kind) as i64);
+    assert_eq!(-1i128, black_box(kind) as i128);
 
     test_as_arg(Nums::NegOne);
 
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index 1ad5134e71c52..24fb760f5a3f7 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -1,14 +1,9 @@
 // run-pass
-#![feature(const_discriminant)]
+#![feature(const_discriminant, test)]
 #![allow(dead_code)]
 
 use std::mem::{discriminant, Discriminant};
-
-// `discriminant(const_expr)` may get const-propagated.
-// As we want to check that const-eval is equal to ordinary exection,
-// we wrap `const_expr` with a function which is not const to prevent this.
-#[inline(never)]
-fn identity<T>(x: T) -> T { x }
+use std::hint::black_box;
 
 enum Test {
     A(u8),
@@ -31,10 +26,10 @@ const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);
 
 fn main() {
     assert_eq!(TEST_A, TEST_A_OTHER);
-    assert_eq!(TEST_A, discriminant(identity(&Test::A(17))));
-    assert_eq!(TEST_B, discriminant(identity(&Test::B)));
+    assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));
+    assert_eq!(TEST_B, discriminant(black_box(&Test::B)));
     assert_ne!(TEST_A, TEST_B);
-    assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 })));
+    assert_ne!(TEST_B, discriminant(black_box(&Test::C { a: 42, b: 7 })));
 
-    assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V)));
+    assert_eq!(TEST_V, discriminant(black_box(&SingleVariant::V)));
 }

From 47668edb64ed1f8676cfcb4c9ccb6fe018f660c5 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 7 Sep 2020 13:04:41 +0200
Subject: [PATCH 12/32] Separate feature flags

Co-authored-by: Ivan Tham <pickfire@riseup.net>
---
 src/test/ui/consts/const_discriminant.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index 24fb760f5a3f7..d016d236dbf81 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -1,5 +1,6 @@
 // run-pass
-#![feature(const_discriminant, test)]
+#![feature(const_discriminant)]
+#![feature(test)]
 #![allow(dead_code)]
 
 use std::mem::{discriminant, Discriminant};

From 284b16913aa6fccdf7b14edc3bb2693aadd39919 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 7 Sep 2020 13:05:59 +0200
Subject: [PATCH 13/32] add missing feature flag

---
 src/test/ui/consts/cast-discriminant-zst-enum.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index 743043609ec32..9c02d232e134b 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,5 +1,6 @@
 // run-pass
 // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32.
+#![feature(test)]
 use std::hint::black_box;
 
 #[derive(Copy, Clone)]

From 91f7d761e762d0d9f47cf61cf5d942fd93eaf2a8 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 12 Sep 2020 10:33:49 +0200
Subject: [PATCH 14/32] also assert ScalarMaybeUninit size

---
 compiler/rustc_middle/src/mir/interpret/value.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 7d6ff3eb5c1cc..7741c76ff3e45 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -578,6 +578,9 @@ pub enum ScalarMaybeUninit<Tag = ()> {
     Uninit,
 }
 
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(ScalarMaybeUninit, 24);
+
 impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
     #[inline(always)]
     fn from(s: Scalar<Tag>) -> Self {

From f567287f9f35e4d4781213bddc5770e270f48d0a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Tue, 15 Sep 2020 22:44:43 +0200
Subject: [PATCH 15/32] don't convert types to the same type with try_into
 (clippy::useless_conversion)

---
 compiler/rustc_mir/src/dataflow/move_paths/builder.rs | 5 +----
 compiler/rustc_mir/src/interpret/place.rs             | 6 ++----
 compiler/rustc_mir_build/src/build/matches/util.rs    | 2 +-
 3 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index b083044a9c6d9..eb92461672259 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -4,7 +4,6 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
-use std::convert::TryInto;
 use std::mem;
 
 use super::abs_domain::Lift;
@@ -482,10 +481,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
             let len: u64 = match base_ty.kind() {
                 ty::Array(_, size) => {
-                    let length = size.eval_usize(self.builder.tcx, self.builder.param_env);
+                    let length: u64 = size.eval_usize(self.builder.tcx, self.builder.param_env);
                     length
-                        .try_into()
-                        .expect("slice pattern of array with more than u32::MAX elements")
                 }
                 _ => bug!("from_end: false slice pattern of non-array type"),
             };
diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs
index 9e16063bd21af..3b22eb5d98719 100644
--- a/compiler/rustc_mir/src/interpret/place.rs
+++ b/compiler/rustc_mir/src/interpret/place.rs
@@ -551,7 +551,7 @@ where
                 let n = base.len(self)?;
                 if n < min_length {
                     // This can only be reached in ConstProp and non-rustc-MIR.
-                    throw_ub!(BoundsCheckFailed { len: min_length.into(), index: n });
+                    throw_ub!(BoundsCheckFailed { len: min_length, index: n });
                 }
 
                 let index = if from_end {
@@ -565,9 +565,7 @@ where
                 self.mplace_index(base, index)?
             }
 
-            Subslice { from, to, from_end } => {
-                self.mplace_subslice(base, u64::from(from), u64::from(to), from_end)?
-            }
+            Subslice { from, to, from_end } => self.mplace_subslice(base, from, to, from_end)?,
         })
     }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index d6e828c966a95..4ef88c25cadf3 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -33,7 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let tcx = self.hir.tcx();
         let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() {
             ty::Array(_, length) => {
-                (length.eval_usize(tcx, self.hir.param_env).try_into().unwrap(), true)
+                (length.eval_usize(tcx, self.hir.param_env), true)
             }
             _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
         };

From de0d55cb3c197b13d90922c8998bf90399f3b8a2 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 08:42:39 -0700
Subject: [PATCH 16/32] library/panic_unwind: Add UNWIND_DATA_REG for RISC-V
 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/panic_unwind/src/gcc.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 85a2a18947db2..81b7b556eb4f0 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -123,6 +123,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
 #[cfg(target_arch = "riscv64")]
 const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
 
+#[cfg(target_arch = "riscv32")]
+const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
+
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c

From 84fe26c4d33924d2195af4324f036b64709baba2 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 08:43:54 -0700
Subject: [PATCH 17/32] library/std: linux: Add support for RISC-V 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/std/src/os/linux/raw.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index a007fd2b6be04..4ff3a6e578984 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -234,7 +234,8 @@ mod arch {
     target_arch = "mips64",
     target_arch = "s390x",
     target_arch = "sparc64",
-    target_arch = "riscv64"
+    target_arch = "riscv64",
+    target_arch = "riscv32"
 ))]
 mod arch {
     pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t};

From cd066c9debeace035d02867a5b5b2d72197f1831 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 08:44:35 -0700
Subject: [PATCH 18/32] library/std: raw: Add support for RISC-V 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/std/src/os/raw/mod.rs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs
index 83e8853fe7923..16272aa05712f 100644
--- a/library/std/src/os/raw/mod.rs
+++ b/library/std/src/os/raw/mod.rs
@@ -22,7 +22,8 @@ mod tests;
             target_arch = "powerpc",
             target_arch = "powerpc64",
             target_arch = "s390x",
-            target_arch = "riscv64"
+            target_arch = "riscv64",
+            target_arch = "riscv32"
         )
     ),
     all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
@@ -65,7 +66,8 @@ pub type c_char = u8;
             target_arch = "powerpc",
             target_arch = "powerpc64",
             target_arch = "s390x",
-            target_arch = "riscv64"
+            target_arch = "riscv64",
+            target_arch = "riscv32"
         )
     ),
     all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),

From cf075355da15c9fb0b1c975649dd13759a78a2bd Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 08:45:08 -0700
Subject: [PATCH 19/32] library/std: sys_common: Add support for RISC-V 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/std/src/sys_common/alloc.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys_common/alloc.rs b/library/std/src/sys_common/alloc.rs
index c669410078592..f22476be32560 100644
--- a/library/std/src/sys_common/alloc.rs
+++ b/library/std/src/sys_common/alloc.rs
@@ -14,7 +14,8 @@ use crate::ptr;
     target_arch = "powerpc64",
     target_arch = "asmjs",
     target_arch = "wasm32",
-    target_arch = "hexagon"
+    target_arch = "hexagon",
+    target_arch = "riscv32"
 )))]
 pub const MIN_ALIGN: usize = 8;
 #[cfg(all(any(

From 0f3ccbd662977d9434f8478a379f292c5bb72a8c Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 08:45:49 -0700
Subject: [PATCH 20/32] library/unwind: Add support for RISC-V 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/unwind/src/libunwind.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 0c57861f70a82..2d65ded390916 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -57,6 +57,9 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_arch = "riscv64")]
 pub const unwinder_private_data_size: usize = 2;
 
+#[cfg(target_arch = "riscv32")]
+pub const unwinder_private_data_size: usize = 2;
+
 #[cfg(target_os = "emscripten")]
 pub const unwinder_private_data_size: usize = 20;
 

From be372657089da3b7e88c2baaa44b0b833f3a31d3 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Wed, 16 Sep 2020 12:00:56 -0400
Subject: [PATCH 21/32] Give a better error message when x.py uses the wrong
 stage for CI

---
 src/bootstrap/config.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 30c9e012cd6f5..913104ff9e3dc 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -616,7 +616,13 @@ impl Config {
                 | Subcommand::Build { .. }
                 | Subcommand::Bench { .. }
                 | Subcommand::Dist { .. }
-                | Subcommand::Install { .. } => assert_eq!(config.stage, 2),
+                | Subcommand::Install { .. } => {
+                    assert_eq!(
+                        config.stage, 2,
+                        "x.py should be run with `--stage 2` on CI, but was run with `--stage {}`",
+                        config.stage,
+                    );
+                }
                 Subcommand::Clean { .. }
                 | Subcommand::Check { .. }
                 | Subcommand::Clippy { .. }

From 3e942958536aad794cec08a2d2b8d6f125e36bb4 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 09:37:00 -0700
Subject: [PATCH 22/32] tools/build-manifest: Add support for RISC-V 32-bit

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 src/tools/build-manifest/src/main.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 58022484fa6cc..1e86f7a4737cc 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -110,6 +110,7 @@ static TARGETS: &[&str] = &[
     "riscv32i-unknown-none-elf",
     "riscv32imc-unknown-none-elf",
     "riscv32imac-unknown-none-elf",
+    "riscv32gc-unknown-linux-gnu",
     "riscv64imac-unknown-none-elf",
     "riscv64gc-unknown-none-elf",
     "riscv64gc-unknown-linux-gnu",

From 1d930483247bac3dd7df3470abd5432d198fe755 Mon Sep 17 00:00:00 2001
From: Gus Wynn <guswynn@gmail.com>
Date: Tue, 15 Sep 2020 09:56:17 -0700
Subject: [PATCH 23/32] give better suggestion when matching a const range

---
 compiler/rustc_typeck/src/check/pat.rs | 53 +++++++++++++++++++++-----
 src/test/ui/issues/issue-76191.rs      |  5 +++
 src/test/ui/issues/issue-76191.stderr  | 26 ++++++++++++-
 3 files changed, 73 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 6be2fdf9f1904..3b1559dfcf5ef 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -772,12 +772,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         );
                     }
                     _ => {
-                        let const_def_id = match pat_ty.kind() {
+                        let (type_def_id, item_def_id) = match pat_ty.kind() {
                             Adt(def, _) => match res {
-                                Res::Def(DefKind::Const, _) => Some(def.did),
-                                _ => None,
+                                Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)),
+                                _ => (None, None),
                             },
-                            _ => None,
+                            _ => (None, None),
                         };
 
                         let ranges = &[
@@ -788,11 +788,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.tcx.lang_items().range_inclusive_struct(),
                             self.tcx.lang_items().range_to_inclusive_struct(),
                         ];
-                        if const_def_id != None && ranges.contains(&const_def_id) {
-                            let msg = "constants only support matching by type, \
-                                if you meant to match against a range of values, \
-                                consider using a range pattern like `min ..= max` in the match block";
-                            e.note(msg);
+                        if type_def_id != None && ranges.contains(&type_def_id) {
+                            let generic_message = match item_def_id {
+                                Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
+                                    Some(hir::Node::Item(hir::Item {
+                                        kind: hir::ItemKind::Const(_, body_id),
+                                        ..
+                                    })) => match self.tcx.hir().get(body_id.hir_id) {
+                                        hir::Node::Expr(expr) => {
+                                            if hir::is_range_literal(expr) {
+                                                let span = self.tcx.hir().span(body_id.hir_id);
+                                                if let Ok(snip) =
+                                                    self.tcx.sess.source_map().span_to_snippet(span)
+                                                {
+                                                    e.span_suggestion_verbose(
+                                                    span,
+                                                    "you may want to move the range into the match block", 
+                                                    snip,
+                                                    Applicability::MachineApplicable
+                                                );
+                                                    false
+                                                } else {
+                                                    true
+                                                }
+                                            } else {
+                                                true
+                                            }
+                                        }
+                                        _ => true,
+                                    },
+                                    _ => true,
+                                },
+                                _ => true,
+                            };
+
+                            if generic_message {
+                                let msg = "constants only support matching by type, \
+                                    if you meant to match against a range of values, \
+                                    consider using a range pattern like `min ..= max` in the match block";
+                                e.note(msg);
+                            }
                         } else {
                             let msg = "introduce a new binding instead";
                             let sugg = format!("other_{}", ident.as_str().to_lowercase());
diff --git a/src/test/ui/issues/issue-76191.rs b/src/test/ui/issues/issue-76191.rs
index bc327123c6fe9..d9790d2b56e28 100644
--- a/src/test/ui/issues/issue-76191.rs
+++ b/src/test/ui/issues/issue-76191.rs
@@ -2,13 +2,18 @@
 #![allow(non_snake_case)]
 
 use std::ops::RangeInclusive;
+
 const RANGE: RangeInclusive<i32> = 0..=255;
 
+const RANGE2: RangeInclusive<i32> = panic!();
+
 fn main() {
     let n: i32 = 1;
     match n {
         RANGE => {}
         //~^ ERROR mismatched types
+        RANGE2 => {}
+        //~^ ERROR mismatched types
         _ => {}
     }
 }
diff --git a/src/test/ui/issues/issue-76191.stderr b/src/test/ui/issues/issue-76191.stderr
index a5544d9e9da40..61f4be81f43a4 100644
--- a/src/test/ui/issues/issue-76191.stderr
+++ b/src/test/ui/issues/issue-76191.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-76191.rs:10:9
+  --> $DIR/issue-76191.rs:13:9
    |
 LL | const RANGE: RangeInclusive<i32> = 0..=255;
    | ------------------------------------------- constant defined here
@@ -14,8 +14,30 @@ LL |         RANGE => {}
    |
    = note: expected type `i32`
             found struct `RangeInclusive<i32>`
+help: you may want to move the range into the match block
+   |
+LL | const RANGE: RangeInclusive<i32> = 0..=255;
+   |                                    ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-76191.rs:15:9
+   |
+LL | const RANGE2: RangeInclusive<i32> = panic!();
+   | --------------------------------------------- constant defined here
+...
+LL |     match n {
+   |           - this expression has type `i32`
+...
+LL |         RANGE2 => {}
+   |         ^^^^^^
+   |         |
+   |         expected `i32`, found struct `RangeInclusive`
+   |         `RANGE2` is interpreted as a constant, not a new binding
+   |
+   = note: expected type `i32`
+            found struct `RangeInclusive<i32>`
    = note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.

From 230355f25f10306211a80040bec1561545715383 Mon Sep 17 00:00:00 2001
From: Gus Wynn <guswynn@gmail.com>
Date: Wed, 16 Sep 2020 12:32:10 -0700
Subject: [PATCH 24/32] comments and factor to own method

---
 compiler/rustc_typeck/src/check/pat.rs | 70 +++++++++++++-------------
 src/test/ui/issues/issue-76191.stderr  |  4 +-
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 3b1559dfcf5ef..713717cfe1a54 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1,5 +1,6 @@
 use crate::check::FnCtxt;
 use rustc_ast as ast;
+
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
@@ -740,6 +741,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_ty
     }
 
+    fn maybe_suggest_range_literal(
+        &self,
+        e: &mut DiagnosticBuilder<'_>,
+        opt_def_id: Option<hir::def_id::DefId>,
+        ident: Ident,
+    ) -> bool {
+        match opt_def_id {
+            Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
+                Some(hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Const(_, body_id), ..
+                })) => match self.tcx.hir().get(body_id.hir_id) {
+                    hir::Node::Expr(expr) => {
+                        if hir::is_range_literal(expr) {
+                            let span = self.tcx.hir().span(body_id.hir_id);
+                            if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
+                                e.span_suggestion_verbose(
+                                    ident.span,
+                                    "you may want to move the range into the match block",
+                                    snip,
+                                    Applicability::MachineApplicable,
+                                );
+                                return true;
+                            }
+                        }
+                    }
+                    _ => (),
+                },
+                _ => (),
+            },
+            _ => (),
+        }
+        false
+    }
+
     fn emit_bad_pat_path(
         &self,
         mut e: DiagnosticBuilder<'_>,
@@ -789,40 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.tcx.lang_items().range_to_inclusive_struct(),
                         ];
                         if type_def_id != None && ranges.contains(&type_def_id) {
-                            let generic_message = match item_def_id {
-                                Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
-                                    Some(hir::Node::Item(hir::Item {
-                                        kind: hir::ItemKind::Const(_, body_id),
-                                        ..
-                                    })) => match self.tcx.hir().get(body_id.hir_id) {
-                                        hir::Node::Expr(expr) => {
-                                            if hir::is_range_literal(expr) {
-                                                let span = self.tcx.hir().span(body_id.hir_id);
-                                                if let Ok(snip) =
-                                                    self.tcx.sess.source_map().span_to_snippet(span)
-                                                {
-                                                    e.span_suggestion_verbose(
-                                                    span,
-                                                    "you may want to move the range into the match block", 
-                                                    snip,
-                                                    Applicability::MachineApplicable
-                                                );
-                                                    false
-                                                } else {
-                                                    true
-                                                }
-                                            } else {
-                                                true
-                                            }
-                                        }
-                                        _ => true,
-                                    },
-                                    _ => true,
-                                },
-                                _ => true,
-                            };
-
-                            if generic_message {
+                            if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
                                 let msg = "constants only support matching by type, \
                                     if you meant to match against a range of values, \
                                     consider using a range pattern like `min ..= max` in the match block";
diff --git a/src/test/ui/issues/issue-76191.stderr b/src/test/ui/issues/issue-76191.stderr
index 61f4be81f43a4..bdcd2fe1adc5a 100644
--- a/src/test/ui/issues/issue-76191.stderr
+++ b/src/test/ui/issues/issue-76191.stderr
@@ -16,8 +16,8 @@ LL |         RANGE => {}
             found struct `RangeInclusive<i32>`
 help: you may want to move the range into the match block
    |
-LL | const RANGE: RangeInclusive<i32> = 0..=255;
-   |                                    ^^^^^^^
+LL |         0..=255 => {}
+   |         ^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-76191.rs:15:9

From fd762681666d7fe229acf82a1b7b23476fd96148 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 14:31:42 -0700
Subject: [PATCH 25/32] library/panic_unwind: Consolidate RV32 and RV64

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/panic_unwind/src/gcc.rs | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 81b7b556eb4f0..1cfd527b5841a 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -120,10 +120,7 @@ const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1
 #[cfg(target_arch = "hexagon")]
 const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
 
-#[cfg(target_arch = "riscv64")]
-const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
-
-#[cfg(target_arch = "riscv32")]
+#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
 const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
 
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:

From 57b2da808c36fa2acf991379cd971639091122f7 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Wed, 16 Sep 2020 15:19:13 -0700
Subject: [PATCH 26/32] library/unwind: Consolidate RV32 and RV64

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/unwind/src/libunwind.rs | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 2d65ded390916..677843e12e1be 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -54,10 +54,7 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_arch = "sparc64")]
 pub const unwinder_private_data_size: usize = 2;
 
-#[cfg(target_arch = "riscv64")]
-pub const unwinder_private_data_size: usize = 2;
-
-#[cfg(target_arch = "riscv32")]
+#[cfg(any(target_arch = "riscv64", target_arch = "riscv32")]
 pub const unwinder_private_data_size: usize = 2;
 
 #[cfg(target_os = "emscripten")]

From 0e3414248a683aa4490c84500cba772c3d920c2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Tue, 15 Sep 2020 23:10:24 +0200
Subject: [PATCH 27/32] don't lazily evaulate some trivial values for
 Option::None replacements (clippy::unnecessary_lazy_evaluations)

---
 compiler/rustc_lint/src/builtin.rs                    | 2 +-
 compiler/rustc_metadata/src/native_libs.rs            | 4 ++--
 compiler/rustc_mir/src/dataflow/move_paths/builder.rs | 5 +----
 3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index efdb7489ba5b0..5b5dbcf192ca1 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -961,7 +961,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
             continue;
         }
 
-        let span = sugared_span.take().unwrap_or_else(|| attr.span);
+        let span = sugared_span.take().unwrap_or(attr.span);
 
         if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) {
             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 3976475cb063e..e76c2cb356f3f 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -170,7 +170,7 @@ impl Collector<'tcx> {
             feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::static_nobundle,
-                span.unwrap_or_else(|| rustc_span::DUMMY_SP),
+                span.unwrap_or(rustc_span::DUMMY_SP),
                 "kind=\"static-nobundle\" is unstable",
             )
             .emit();
@@ -179,7 +179,7 @@ impl Collector<'tcx> {
             feature_err(
                 &self.tcx.sess.parse_sess,
                 sym::raw_dylib,
-                span.unwrap_or_else(|| rustc_span::DUMMY_SP),
+                span.unwrap_or(rustc_span::DUMMY_SP),
                 "kind=\"raw-dylib\" is unstable",
             )
             .emit();
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index eb92461672259..5c3e353840180 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -480,10 +480,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             };
             let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
             let len: u64 = match base_ty.kind() {
-                ty::Array(_, size) => {
-                    let length: u64 = size.eval_usize(self.builder.tcx, self.builder.param_env);
-                    length
-                }
+                ty::Array(_, size) => size.eval_usize(self.builder.tcx, self.builder.param_env),
                 _ => bug!("from_end: false slice pattern of non-array type"),
             };
             for offset in from..to {

From 3d1b6d6cc29587ace6895814fa32ec38a49d8a68 Mon Sep 17 00:00:00 2001
From: Alistair Francis <alistair.francis@wdc.com>
Date: Thu, 17 Sep 2020 07:10:10 -0700
Subject: [PATCH 28/32] library/unwind: Add missing )

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
 library/unwind/src/libunwind.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 677843e12e1be..dcf4fcd4e5aab 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -54,7 +54,7 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_arch = "sparc64")]
 pub const unwinder_private_data_size: usize = 2;
 
-#[cfg(any(target_arch = "riscv64", target_arch = "riscv32")]
+#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
 pub const unwinder_private_data_size: usize = 2;
 
 #[cfg(target_os = "emscripten")]

From 3f68ae47df90d2803c849503a4cbdb2bb3dbb9a6 Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Tue, 8 Sep 2020 20:17:23 +0200
Subject: [PATCH 29/32] Add `BITS` associated constant to all integer types.

---
 library/core/src/num/mod.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 050c187e55576..33bcf93676b2a 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -348,6 +348,10 @@ $EndFeature, "
             pub const MAX: Self = !Self::MIN;
         }
 
+        /// The size of this integer type in bits.
+        #[unstable(feature = "int_bits_const", issue = "none")]
+        pub const BITS: u32 = $BITS;
+
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.
 
@@ -2601,6 +2605,10 @@ $EndFeature, "
             pub const MAX: Self = !0;
         }
 
+        /// The size of this integer type in bits.
+        #[unstable(feature = "int_bits_const", issue = "none")]
+        pub const BITS: u32 = $BITS;
+
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.
 

From 5c30a16fa03efaf87241b363f4323743746c12b0 Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Tue, 8 Sep 2020 20:24:55 +0200
Subject: [PATCH 30/32] Add example/test to <int types>::BITS.

---
 library/core/src/num/mod.rs | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 33bcf93676b2a..5df67a5f53df7 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -348,9 +348,19 @@ $EndFeature, "
             pub const MAX: Self = !Self::MIN;
         }
 
-        /// The size of this integer type in bits.
-        #[unstable(feature = "int_bits_const", issue = "none")]
-        pub const BITS: u32 = $BITS;
+        doc_comment! {
+            concat!("The size of this integer type in bits.
+
+# Examples
+
+```
+", $Feature, "#![feature(int_bits_const)]
+assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
+$EndFeature, "
+```"),
+            #[unstable(feature = "int_bits_const", issue = "none")]
+            pub const BITS: u32 = $BITS;
+        }
 
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.
@@ -2605,9 +2615,19 @@ $EndFeature, "
             pub const MAX: Self = !0;
         }
 
-        /// The size of this integer type in bits.
-        #[unstable(feature = "int_bits_const", issue = "none")]
-        pub const BITS: u32 = $BITS;
+        doc_comment! {
+            concat!("The size of this integer type in bits.
+
+# Examples
+
+```
+", $Feature, "#![feature(int_bits_const)]
+assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
+$EndFeature, "
+```"),
+            #[unstable(feature = "int_bits_const", issue = "none")]
+            pub const BITS: u32 = $BITS;
+        }
 
         doc_comment! {
             concat!("Converts a string slice in a given base to an integer.

From 1e2dba1e7cf15442257f2cd3ddfe5d0462ee9102 Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Tue, 8 Sep 2020 21:39:13 +0200
Subject: [PATCH 31/32] Use `T::BITS` instead of `size_of::<T> * 8`.

---
 compiler/rustc_data_structures/src/lib.rs     |  1 +
 .../src/tagged_ptr/copy.rs                    |  2 +-
 library/alloc/src/collections/binary_heap.rs  |  4 +--
 library/alloc/src/lib.rs                      |  1 +
 library/alloc/src/raw_vec.rs                  |  2 +-
 library/alloc/tests/lib.rs                    |  1 +
 library/alloc/tests/string.rs                 |  5 ++-
 library/alloc/tests/vec.rs                    |  2 +-
 library/core/src/fmt/mod.rs                   |  2 +-
 library/core/src/num/bignum.rs                | 34 +++++--------------
 library/core/src/slice/sort.rs                |  6 ++--
 library/core/tests/iter.rs                    |  2 +-
 library/core/tests/lib.rs                     |  1 +
 library/core/tests/num/int_macros.rs          | 20 +++++------
 library/core/tests/num/uint_macros.rs         | 20 +++++------
 library/panic_unwind/src/dwarf/mod.rs         |  4 +--
 library/panic_unwind/src/lib.rs               |  1 +
 17 files changed, 44 insertions(+), 64 deletions(-)

diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 88c160e93b66a..06718cc980312 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -14,6 +14,7 @@
 #![feature(generators)]
 #![feature(generator_trait)]
 #![feature(fn_traits)]
+#![feature(int_bits_const)]
 #![feature(min_specialization)]
 #![feature(optin_builtin_traits)]
 #![feature(nll)]
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
index d39d146db318f..d63bcdb3c2b04 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
@@ -48,7 +48,7 @@ where
     P: Pointer,
     T: Tag,
 {
-    const TAG_BIT_SHIFT: usize = (8 * std::mem::size_of::<usize>()) - T::BITS;
+    const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
     const ASSERTION: () = {
         assert!(T::BITS <= P::BITS);
         // Used for the transmute_copy's below
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 24d17fdd880ba..8a7dd9d4249a8 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -146,7 +146,7 @@
 
 use core::fmt;
 use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
-use core::mem::{self, size_of, swap, ManuallyDrop};
+use core::mem::{self, swap, ManuallyDrop};
 use core::ops::{Deref, DerefMut};
 use core::ptr;
 
@@ -617,7 +617,7 @@ impl<T: Ord> BinaryHeap<T> {
 
         #[inline(always)]
         fn log2_fast(x: usize) -> usize {
-            8 * size_of::<usize>() - (x.leading_zeros() as usize) - 1
+            (usize::BITS - x.leading_zeros() - 1) as usize
         }
 
         // `rebuild` takes O(len1 + len2) operations
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 7881c101f9f60..f3c1eee47c721 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -101,6 +101,7 @@
 #![feature(fn_traits)]
 #![feature(fundamental)]
 #![feature(inplace_iteration)]
+#![feature(int_bits_const)]
 #![feature(lang_items)]
 #![feature(layout_for_ptr)]
 #![feature(libc)]
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 05382d0b5594e..62675665f037f 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -528,7 +528,7 @@ unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
 
 #[inline]
 fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
-    if mem::size_of::<usize>() < 8 && alloc_size > isize::MAX as usize {
+    if usize::BITS < 64 && alloc_size > isize::MAX as usize {
         Err(CapacityOverflow)
     } else {
         Ok(())
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 03737e1ef1f4d..3ee0cfbe74759 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -18,6 +18,7 @@
 #![feature(deque_range)]
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
+#![feature(int_bits_const)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs
index 4e6043541226f..a6e41b21b618c 100644
--- a/library/alloc/tests/string.rs
+++ b/library/alloc/tests/string.rs
@@ -1,6 +1,5 @@
 use std::borrow::Cow;
 use std::collections::TryReserveError::*;
-use std::mem::size_of;
 use std::ops::Bound::*;
 
 pub trait IntoCow<'a, B: ?Sized>
@@ -605,7 +604,7 @@ fn test_try_reserve() {
     // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
     // Any platform that succeeds for these requests is technically broken with
     // ptr::offset because LLVM is the worst.
-    let guards_against_isize = size_of::<usize>() < 8;
+    let guards_against_isize = usize::BITS < 64;
 
     {
         // Note: basic stuff is checked by test_reserve
@@ -686,7 +685,7 @@ fn test_try_reserve_exact() {
     const MAX_CAP: usize = isize::MAX as usize;
     const MAX_USIZE: usize = usize::MAX;
 
-    let guards_against_isize = size_of::<usize>() < 8;
+    let guards_against_isize = usize::BITS < 64;
 
     {
         let mut empty_string: String = String::new();
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 368ca4c543219..a49ca7c256a75 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1341,7 +1341,7 @@ fn test_try_reserve() {
     // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
     // Any platform that succeeds for these requests is technically broken with
     // ptr::offset because LLVM is the worst.
-    let guards_against_isize = size_of::<usize>() < 8;
+    let guards_against_isize = usize::BITS < 64;
 
     {
         // Note: basic stuff is checked by test_reserve
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 48b7f2739eeb2..8558cb5a5e8a3 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -2086,7 +2086,7 @@ impl<T: ?Sized> Pointer for *const T {
             f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
 
             if f.width.is_none() {
-                f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2);
+                f.width = Some((usize::BITS / 4) as usize + 2);
             }
         }
         f.flags |= 1 << (FlagV1::Alternate as u32);
diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs
index 6f16b93d0488a..6a1a1e1976160 100644
--- a/library/core/src/num/bignum.rs
+++ b/library/core/src/num/bignum.rs
@@ -20,7 +20,6 @@
 #![macro_use]
 
 use crate::intrinsics;
-use crate::mem;
 
 /// Arithmetic operations required by bignums.
 pub trait FullOps: Sized {
@@ -58,25 +57,22 @@ macro_rules! impl_full_ops {
                     // This cannot overflow;
                     // the output is between `0` and `2^nbits * (2^nbits - 1)`.
                     // FIXME: will LLVM optimize this into ADC or similar?
-                    let nbits = mem::size_of::<$ty>() * 8;
                     let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
-                    ((v >> nbits) as $ty, v as $ty)
+                    ((v >> <$ty>::BITS) as $ty, v as $ty)
                 }
 
                 fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
                     // This cannot overflow;
                     // the output is between `0` and `2^nbits * (2^nbits - 1)`.
-                    let nbits = mem::size_of::<$ty>() * 8;
                     let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
                             (carry as $bigty);
-                    ((v >> nbits) as $ty, v as $ty)
+                    ((v >> <$ty>::BITS) as $ty, v as $ty)
                 }
 
                 fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
                     debug_assert!(borrow < other);
                     // This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`.
-                    let nbits = mem::size_of::<$ty>() * 8;
-                    let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
+                    let lhs = ((borrow as $bigty) << <$ty>::BITS) | (self as $bigty);
                     let rhs = other as $bigty;
                     ((lhs / rhs) as $ty, (lhs % rhs) as $ty)
                 }
@@ -128,13 +124,11 @@ macro_rules! define_bignum {
 
             /// Makes a bignum from `u64` value.
             pub fn from_u64(mut v: u64) -> $name {
-                use crate::mem;
-
                 let mut base = [0; $n];
                 let mut sz = 0;
                 while v > 0 {
                     base[sz] = v as $ty;
-                    v >>= mem::size_of::<$ty>() * 8;
+                    v >>= <$ty>::BITS;
                     sz += 1;
                 }
                 $name { size: sz, base: base }
@@ -150,9 +144,7 @@ macro_rules! define_bignum {
             /// Returns the `i`-th bit where bit 0 is the least significant one.
             /// In other words, the bit with weight `2^i`.
             pub fn get_bit(&self, i: usize) -> u8 {
-                use crate::mem;
-
-                let digitbits = mem::size_of::<$ty>() * 8;
+                let digitbits = <$ty>::BITS as usize;
                 let d = i / digitbits;
                 let b = i % digitbits;
                 ((self.base[d] >> b) & 1) as u8
@@ -166,8 +158,6 @@ macro_rules! define_bignum {
             /// Returns the number of bits necessary to represent this value. Note that zero
             /// is considered to need 0 bits.
             pub fn bit_length(&self) -> usize {
-                use crate::mem;
-
                 // Skip over the most significant digits which are zero.
                 let digits = self.digits();
                 let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
@@ -180,7 +170,7 @@ macro_rules! define_bignum {
                 }
                 // This could be optimized with leading_zeros() and bit shifts, but that's
                 // probably not worth the hassle.
-                let digitbits = mem::size_of::<$ty>() * 8;
+                let digitbits = <$ty>::BITS as usize;
                 let mut i = nonzero.len() * digitbits - 1;
                 while self.get_bit(i) == 0 {
                     i -= 1;
@@ -265,9 +255,7 @@ macro_rules! define_bignum {
 
             /// Multiplies itself by `2^bits` and returns its own mutable reference.
             pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
-                use crate::mem;
-
-                let digitbits = mem::size_of::<$ty>() * 8;
+                let digitbits = <$ty>::BITS as usize;
                 let digits = bits / digitbits;
                 let bits = bits % digitbits;
 
@@ -393,13 +381,11 @@ macro_rules! define_bignum {
             /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
             /// remainder.
             pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
-                use crate::mem;
-
                 // Stupid slow base-2 long division taken from
                 // https://en.wikipedia.org/wiki/Division_algorithm
                 // FIXME use a greater base ($ty) for the long division.
                 assert!(!d.is_zero());
-                let digitbits = mem::size_of::<$ty>() * 8;
+                let digitbits = <$ty>::BITS as usize;
                 for digit in &mut q.base[..] {
                     *digit = 0;
                 }
@@ -462,10 +448,8 @@ macro_rules! define_bignum {
 
         impl crate::fmt::Debug for $name {
             fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
-                use crate::mem;
-
                 let sz = if self.size < 1 { 1 } else { self.size };
-                let digitlen = mem::size_of::<$ty>() * 2;
+                let digitlen = <$ty>::BITS as usize / 4;
 
                 write!(f, "{:#x}", self.base[sz - 1])?;
                 for &v in self.base[..sz - 1].iter().rev() {
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 8c14651bd826c..71d2c2c9b2f4c 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -565,7 +565,7 @@ fn break_patterns<T>(v: &mut [T]) {
             random
         };
         let mut gen_usize = || {
-            if mem::size_of::<usize>() <= 4 {
+            if usize::BITS <= 32 {
                 gen_u32() as usize
             } else {
                 (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
@@ -667,7 +667,7 @@ where
 ///
 /// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,
 /// this function will immediately switch to heapsort.
-fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize)
+fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: u32)
 where
     F: FnMut(&T, &T) -> bool,
 {
@@ -763,7 +763,7 @@ where
     }
 
     // Limit the number of imbalanced partitions to `floor(log2(len)) + 1`.
-    let limit = mem::size_of::<usize>() * 8 - v.len().leading_zeros() as usize;
+    let limit = usize::BITS - v.len().leading_zeros();
 
     recurse(v, &mut is_less, None, limit);
 }
diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs
index 00e3972c42f9d..0eb9af3f454e9 100644
--- a/library/core/tests/iter.rs
+++ b/library/core/tests/iter.rs
@@ -474,7 +474,7 @@ fn test_iterator_step_by_nth_overflow() {
     }
 
     let mut it = Test(0);
-    let root = usize::MAX >> (::std::mem::size_of::<usize>() * 8 / 2);
+    let root = usize::MAX >> (usize::BITS / 2);
     let n = root + 20;
     (&mut it).step_by(n).nth(n);
     assert_eq!(it.0, n as Bigger * n as Bigger);
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index a5b1b51e06c64..4db391f3e567e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -52,6 +52,7 @@
 #![feature(partition_point)]
 #![feature(once_cell)]
 #![feature(unsafe_block_in_unsafe_fn)]
+#![feature(int_bits_const)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 58a585669122c..27e6760e7cbb9 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -2,7 +2,6 @@ macro_rules! int_module {
     ($T:ident, $T_i:ident) => {
         #[cfg(test)]
         mod tests {
-            use core::mem;
             use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
             use core::$T_i::*;
 
@@ -82,30 +81,27 @@ macro_rules! int_module {
 
             #[test]
             fn test_count_zeros() {
-                let bits = mem::size_of::<$T>() * 8;
-                assert_eq!(A.count_zeros(), bits as u32 - 3);
-                assert_eq!(B.count_zeros(), bits as u32 - 2);
-                assert_eq!(C.count_zeros(), bits as u32 - 5);
+                assert_eq!(A.count_zeros(), $T::BITS - 3);
+                assert_eq!(B.count_zeros(), $T::BITS - 2);
+                assert_eq!(C.count_zeros(), $T::BITS - 5);
             }
 
             #[test]
             fn test_leading_trailing_ones() {
-                let bits = (mem::size_of::<$T>() * 8) as u32;
-
                 let a: $T = 0b0101_1111;
                 assert_eq!(a.trailing_ones(), 5);
-                assert_eq!((!a).leading_ones(), bits - 7);
+                assert_eq!((!a).leading_ones(), $T::BITS - 7);
 
                 assert_eq!(a.reverse_bits().leading_ones(), 5);
 
-                assert_eq!(_1.leading_ones(), bits);
-                assert_eq!(_1.trailing_ones(), bits);
+                assert_eq!(_1.leading_ones(), $T::BITS);
+                assert_eq!(_1.trailing_ones(), $T::BITS);
 
                 assert_eq!((_1 << 1).trailing_ones(), 0);
                 assert_eq!(MAX.leading_ones(), 0);
 
-                assert_eq!((_1 << 1).leading_ones(), bits - 1);
-                assert_eq!(MAX.trailing_ones(), bits - 1);
+                assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1);
+                assert_eq!(MAX.trailing_ones(), $T::BITS - 1);
 
                 assert_eq!(_0.leading_ones(), 0);
                 assert_eq!(_0.trailing_ones(), 0);
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index b84a8a7d9f88b..952ec188dc138 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -4,7 +4,6 @@ macro_rules! uint_module {
         mod tests {
             use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
             use core::$T_i::*;
-            use std::mem;
             use std::str::FromStr;
 
             use crate::num;
@@ -47,30 +46,27 @@ macro_rules! uint_module {
 
             #[test]
             fn test_count_zeros() {
-                let bits = mem::size_of::<$T>() * 8;
-                assert!(A.count_zeros() == bits as u32 - 3);
-                assert!(B.count_zeros() == bits as u32 - 2);
-                assert!(C.count_zeros() == bits as u32 - 5);
+                assert!(A.count_zeros() == $T::BITS - 3);
+                assert!(B.count_zeros() == $T::BITS - 2);
+                assert!(C.count_zeros() == $T::BITS - 5);
             }
 
             #[test]
             fn test_leading_trailing_ones() {
-                let bits = (mem::size_of::<$T>() * 8) as u32;
-
                 let a: $T = 0b0101_1111;
                 assert_eq!(a.trailing_ones(), 5);
-                assert_eq!((!a).leading_ones(), bits - 7);
+                assert_eq!((!a).leading_ones(), $T::BITS - 7);
 
                 assert_eq!(a.reverse_bits().leading_ones(), 5);
 
-                assert_eq!(_1.leading_ones(), bits);
-                assert_eq!(_1.trailing_ones(), bits);
+                assert_eq!(_1.leading_ones(), $T::BITS);
+                assert_eq!(_1.trailing_ones(), $T::BITS);
 
                 assert_eq!((_1 << 1).trailing_ones(), 0);
                 assert_eq!((_1 >> 1).leading_ones(), 0);
 
-                assert_eq!((_1 << 1).leading_ones(), bits - 1);
-                assert_eq!((_1 >> 1).trailing_ones(), bits - 1);
+                assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1);
+                assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1);
 
                 assert_eq!(_0.leading_ones(), 0);
                 assert_eq!(_0.trailing_ones(), 0);
diff --git a/library/panic_unwind/src/dwarf/mod.rs b/library/panic_unwind/src/dwarf/mod.rs
index 649bbce52a364..652fbe95a14d1 100644
--- a/library/panic_unwind/src/dwarf/mod.rs
+++ b/library/panic_unwind/src/dwarf/mod.rs
@@ -53,7 +53,7 @@ impl DwarfReader {
     }
 
     pub unsafe fn read_sleb128(&mut self) -> i64 {
-        let mut shift: usize = 0;
+        let mut shift: u32 = 0;
         let mut result: u64 = 0;
         let mut byte: u8;
         loop {
@@ -65,7 +65,7 @@ impl DwarfReader {
             }
         }
         // sign-extend
-        if shift < 8 * mem::size_of::<u64>() && (byte & 0x40) != 0 {
+        if shift < u64::BITS && (byte & 0x40) != 0 {
             result |= (!0 as u64) << shift;
         }
         result as i64
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 6f31e6dcae70d..162f0386b6692 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -18,6 +18,7 @@
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
 )]
 #![feature(core_intrinsics)]
+#![feature(int_bits_const)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(nll)]

From 1bfe5efe8f635268646da91f1f4f6e616104b71f Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Sat, 19 Sep 2020 08:14:41 +0200
Subject: [PATCH 32/32] Add tracking issue number for int_bits_const.

---
 library/core/src/num/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 5df67a5f53df7..eec149cc3e801 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -358,7 +358,7 @@ $EndFeature, "
 assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "int_bits_const", issue = "none")]
+            #[unstable(feature = "int_bits_const", issue = "76904")]
             pub const BITS: u32 = $BITS;
         }
 
@@ -2625,7 +2625,7 @@ $EndFeature, "
 assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
 $EndFeature, "
 ```"),
-            #[unstable(feature = "int_bits_const", issue = "none")]
+            #[unstable(feature = "int_bits_const", issue = "76904")]
             pub const BITS: u32 = $BITS;
         }