diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index faeb727202cd6..87d539f748c6b 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1333,9 +1333,6 @@ fn add_late_link_args(
     crate_type: CrateType,
     codegen_results: &CodegenResults,
 ) {
-    if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
-        cmd.args(args);
-    }
     let any_dynamic_crate = crate_type == CrateType::Dylib
         || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
             *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
@@ -1349,6 +1346,9 @@ fn add_late_link_args(
             cmd.args(args);
         }
     }
+    if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
+        cmd.args(args);
+    }
 }
 
 /// Add arbitrary "post-link" args defined by the target spec.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 492afa54445bc..d6cf68a900ce0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -682,25 +682,31 @@ pub enum BorrowKind {
     /// implicit closure bindings. It is needed when the closure
     /// is borrowing or mutating a mutable referent, e.g.:
     ///
-    ///    let x: &mut isize = ...;
-    ///    let y = || *x += 5;
+    /// ```
+    /// let x: &mut isize = ...;
+    /// let y = || *x += 5;
+    /// ```
     ///
     /// If we were to try to translate this closure into a more explicit
     /// form, we'd encounter an error with the code as written:
     ///
-    ///    struct Env { x: & &mut isize }
-    ///    let x: &mut isize = ...;
-    ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
-    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
+    /// struct Env { x: & &mut isize }
+    /// let x: &mut isize = ...;
+    /// let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
+    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
     ///
     /// This is then illegal because you cannot mutate a `&mut` found
     /// in an aliasable location. To solve, you'd have to translate with
     /// an `&mut` borrow:
     ///
-    ///    struct Env { x: & &mut isize }
-    ///    let x: &mut isize = ...;
-    ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
-    ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
+    /// struct Env { x: & &mut isize }
+    /// let x: &mut isize = ...;
+    /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
+    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
+    /// ```
     ///
     /// Now the assignment to `**env.x` is legal, but creating a
     /// mutable pointer to `x` is not because `x` is not mutable. We
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index aa88719c26a49..0f04ead94dd33 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -1046,9 +1046,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
         self.super_operand(operand, location);
 
-        // Only const prop copies and moves on `mir_opt_level=3` as doing so
-        // currently increases compile time.
-        if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 {
+        // Only const prop copies and moves on `mir_opt_level=2` as doing so
+        // currently slightly increases compile time in some cases.
+        if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
             self.propagate_operand(operand)
         }
     }
@@ -1246,8 +1246,8 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
             | TerminatorKind::InlineAsm { .. } => {}
             // Every argument in our function calls have already been propagated in `visit_operand`.
             //
-            // NOTE: because LLVM codegen gives performance regressions with it, so this is gated
-            // on `mir_opt_level=3`.
+            // NOTE: because LLVM codegen gives slight performance regressions with it, so this is
+            // gated on `mir_opt_level=2`.
             TerminatorKind::Call { .. } => {}
         }
 
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index a622de9a8af3e..850cafcf89811 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -36,7 +36,6 @@ pub mod match_branches;
 pub mod no_landing_pads;
 pub mod nrvo;
 pub mod promote_consts;
-pub mod qualify_min_const_fn;
 pub mod remove_noop_landing_pads;
 pub mod remove_unneeded_drops;
 pub mod required_consts;
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 21bbdc9ba8dce..d59dd4016a9f9 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -7,7 +7,7 @@
 #![feature(or_patterns)]
 
 use rustc_ast as ast;
-use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{self, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
@@ -299,7 +299,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // FIXME(#43081): Avoid this pretty-print + reparse hack
     let source = pprust::nonterminal_to_string(nt);
     let filename = FileName::macro_expansion_source_code(&source);
-    let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span));
+    let reparsed_tokens = parse_stream_from_source_str(filename, source, sess, Some(span));
 
     // During early phases of the compiler the AST could get modified
     // directly (e.g., attributes added or removed) and the internal cache
@@ -325,7 +325,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // modifications, including adding/removing typically non-semantic
     // tokens such as extra braces and commas, don't happen.
     if let Some(tokens) = tokens {
-        if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real, sess) {
+        if tokenstream_probably_equal_for_proc_macro(&tokens, &reparsed_tokens, sess) {
             return tokens;
         }
         info!(
@@ -333,9 +333,9 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
                 going with stringified version"
         );
         info!("cached tokens: {:?}", tokens);
-        info!("reparsed tokens: {:?}", tokens_for_real);
+        info!("reparsed tokens: {:?}", reparsed_tokens);
     }
-    tokens_for_real
+    reparsed_tokens
 }
 
 // See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -344,8 +344,8 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
 // This is otherwise the same as `eq_unspanned`, only recursing with a
 // different method.
 pub fn tokenstream_probably_equal_for_proc_macro(
-    first: &TokenStream,
-    other: &TokenStream,
+    tokens: &TokenStream,
+    reparsed_tokens: &TokenStream,
     sess: &ParseSess,
 ) -> bool {
     // When checking for `probably_eq`, we ignore certain tokens that aren't
@@ -359,9 +359,6 @@ pub fn tokenstream_probably_equal_for_proc_macro(
                 // The pretty printer tends to add trailing commas to
                 // everything, and in particular, after struct fields.
                 | token::Comma
-                // The pretty printer emits `NoDelim` as whitespace.
-                | token::OpenDelim(DelimToken::NoDelim)
-                | token::CloseDelim(DelimToken::NoDelim)
                 // The pretty printer collapses many semicolons into one.
                 | token::Semi
                 // We don't preserve leading `|` tokens in patterns, so
@@ -460,10 +457,11 @@ pub fn tokenstream_probably_equal_for_proc_macro(
 
     // Break tokens after we expand any nonterminals, so that we break tokens
     // that are produced as a result of nonterminal expansion.
-    let t1 = first.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
-    let t2 = other.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
+    let tokens = tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
+    let reparsed_tokens =
+        reparsed_tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
 
-    t1.eq_by(t2, |t1, t2| tokentree_probably_equal_for_proc_macro(&t1, &t2, sess))
+    tokens.eq_by(reparsed_tokens, |t, rt| tokentree_probably_equal_for_proc_macro(&t, &rt, sess))
 }
 
 // See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -472,16 +470,20 @@ pub fn tokenstream_probably_equal_for_proc_macro(
 // This is otherwise the same as `eq_unspanned`, only recursing with a
 // different method.
 pub fn tokentree_probably_equal_for_proc_macro(
-    first: &TokenTree,
-    other: &TokenTree,
+    token: &TokenTree,
+    reparsed_token: &TokenTree,
     sess: &ParseSess,
 ) -> bool {
-    match (first, other) {
-        (TokenTree::Token(token), TokenTree::Token(token2)) => {
-            token_probably_equal_for_proc_macro(token, token2)
+    match (token, reparsed_token) {
+        (TokenTree::Token(token), TokenTree::Token(reparsed_token)) => {
+            token_probably_equal_for_proc_macro(token, reparsed_token)
         }
-        (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
-            delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2, sess)
+        (
+            TokenTree::Delimited(_, delim, tokens),
+            TokenTree::Delimited(_, reparsed_delim, reparsed_tokens),
+        ) => {
+            delim == reparsed_delim
+                && tokenstream_probably_equal_for_proc_macro(tokens, reparsed_tokens, sess)
         }
         _ => false,
     }
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index a864918655fb8..0234ff55f0118 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
         "-lmsvcrt".to_string(),
         "-lmingwex".to_string(),
         "-lmingw32".to_string(),
+        "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
         // mingw's msvcrt is a weird hybrid import library and static library.
         // And it seems that the linker fails to use import symbols from msvcrt
         // that are required from functions in msvcrt in certain cases. For example
@@ -41,8 +42,6 @@ pub fn opts() -> TargetOptions {
         // the shared libgcc_s-dw2-1.dll. This is required to support
         // unwinding across DLL boundaries.
         "-lgcc_s".to_string(),
-        "-lgcc".to_string(),
-        "-lkernel32".to_string(),
     ];
     late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
     late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
@@ -54,10 +53,6 @@ pub fn opts() -> TargetOptions {
         // boundaries when unwinding across FFI boundaries.
         "-lgcc_eh".to_string(),
         "-l:libpthread.a".to_string(),
-        "-lgcc".to_string(),
-        // libpthread depends on libmsvcrt, so we need to link it *again*.
-        "-lmsvcrt".to_string(),
-        "-lkernel32".to_string(),
     ];
     late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
     late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index 687efa8e9e777..789ae3a20eabf 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -1,4 +1,4 @@
-use rand::prelude::*;
+use rand::RngCore;
 use std::iter::{repeat, FromIterator};
 use test::{black_box, Bencher};
 
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index dd72a33996f17..2792181acc352 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -108,3 +108,32 @@ fn write_str_macro_debug(bh: &mut Bencher) {
         }
     });
 }
+
+#[bench]
+fn write_u128_max(bh: &mut Bencher) {
+    bh.iter(|| {
+        std::hint::black_box(format!("{}", u128::MAX));
+    });
+}
+
+#[bench]
+fn write_u128_min(bh: &mut Bencher) {
+    bh.iter(|| {
+        let s = format!("{}", 0u128);
+        std::hint::black_box(s);
+    });
+}
+
+#[bench]
+fn write_u64_max(bh: &mut Bencher) {
+    bh.iter(|| {
+        std::hint::black_box(format!("{}", u64::MAX));
+    });
+}
+
+#[bench]
+fn write_u64_min(bh: &mut Bencher) {
+    bh.iter(|| {
+        std::hint::black_box(format!("{}", 0u64));
+    });
+}
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index ae3d0ddd46beb..a728eed76adf1 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -9,7 +9,7 @@ use crate::slice;
 use crate::str;
 
 #[doc(hidden)]
-trait Int:
+trait DisplayInt:
     PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
 {
     fn zero() -> Self;
@@ -21,22 +21,39 @@ trait Int:
     fn to_u128(&self) -> u128;
 }
 
-macro_rules! doit {
-    ($($t:ident)*) => ($(impl Int for $t {
-        fn zero() -> Self { 0 }
-        fn from_u8(u: u8) -> Self { u as Self }
-        fn to_u8(&self) -> u8 { *self as u8 }
-        fn to_u16(&self) -> u16 { *self as u16 }
-        fn to_u32(&self) -> u32 { *self as u32 }
-        fn to_u64(&self) -> u64 { *self as u64 }
-        fn to_u128(&self) -> u128 { *self as u128 }
-    })*)
+macro_rules! impl_int {
+    ($($t:ident)*) => (
+      $(impl DisplayInt for $t {
+          fn zero() -> Self { 0 }
+          fn from_u8(u: u8) -> Self { u as Self }
+          fn to_u8(&self) -> u8 { *self as u8 }
+          fn to_u16(&self) -> u16 { *self as u16 }
+          fn to_u32(&self) -> u32 { *self as u32 }
+          fn to_u64(&self) -> u64 { *self as u64 }
+          fn to_u128(&self) -> u128 { *self as u128 }
+      })*
+    )
 }
-doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
+macro_rules! impl_uint {
+    ($($t:ident)*) => (
+      $(impl DisplayInt for $t {
+          fn zero() -> Self { 0 }
+          fn from_u8(u: u8) -> Self { u as Self }
+          fn to_u8(&self) -> u8 { *self as u8 }
+          fn to_u16(&self) -> u16 { *self as u16 }
+          fn to_u32(&self) -> u32 { *self as u32 }
+          fn to_u64(&self) -> u64 { *self as u64 }
+          fn to_u128(&self) -> u128 { *self as u128 }
+      })*
+    )
+}
+
+impl_int! { i8 i16 i32 i64 i128 isize }
+impl_uint! { u8 u16 u32 u64 u128 usize }
 
 /// A type that represents a specific radix
 #[doc(hidden)]
-trait GenericRadix {
+trait GenericRadix: Sized {
     /// The number of digits.
     const BASE: u8;
 
@@ -47,7 +64,7 @@ trait GenericRadix {
     fn digit(x: u8) -> u8;
 
     /// Format an integer using the radix using a formatter.
-    fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // The radix can be as low as 2, so we need a buffer of at least 128
         // characters for a base 2 number.
         let zero = T::zero();
@@ -127,13 +144,11 @@ macro_rules! radix {
 
 radix! { Binary,    2, "0b", x @  0 ..=  1 => b'0' + x }
 radix! { Octal,     8, "0o", x @  0 ..=  7 => b'0' + x }
-radix! { LowerHex, 16, "0x", x @  0 ..=  9 => b'0' + x,
-x @ 10 ..= 15 => b'a' + (x - 10) }
-radix! { UpperHex, 16, "0x", x @  0 ..=  9 => b'0' + x,
-x @ 10 ..= 15 => b'A' + (x - 10) }
+radix! { LowerHex, 16, "0x", x @  0 ..=  9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) }
+radix! { UpperHex, 16, "0x", x @  0 ..=  9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
 
 macro_rules! int_base {
-    ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
+    (fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::$Trait for $T {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -143,8 +158,27 @@ macro_rules! int_base {
     };
 }
 
+macro_rules! integer {
+    ($Int:ident, $Uint:ident) => {
+        int_base! { fmt::Binary   for $Int as $Uint  -> Binary }
+        int_base! { fmt::Octal    for $Int as $Uint  -> Octal }
+        int_base! { fmt::LowerHex for $Int as $Uint  -> LowerHex }
+        int_base! { fmt::UpperHex for $Int as $Uint  -> UpperHex }
+
+        int_base! { fmt::Binary   for $Uint as $Uint -> Binary }
+        int_base! { fmt::Octal    for $Uint as $Uint -> Octal }
+        int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
+        int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
+    };
+}
+integer! { isize, usize }
+integer! { i8, u8 }
+integer! { i16, u16 }
+integer! { i32, u32 }
+integer! { i64, u64 }
+integer! { i128, u128 }
 macro_rules! debug {
-    ($T:ident) => {
+    ($($T:ident)*) => {$(
         #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Debug for $T {
             #[inline]
@@ -158,31 +192,14 @@ macro_rules! debug {
                 }
             }
         }
-    };
+    )*};
 }
-
-macro_rules! integer {
-    ($Int:ident, $Uint:ident) => {
-        int_base! { Binary   for $Int as $Uint  -> Binary }
-        int_base! { Octal    for $Int as $Uint  -> Octal }
-        int_base! { LowerHex for $Int as $Uint  -> LowerHex }
-        int_base! { UpperHex for $Int as $Uint  -> UpperHex }
-        debug! { $Int }
-
-        int_base! { Binary   for $Uint as $Uint -> Binary }
-        int_base! { Octal    for $Uint as $Uint -> Octal }
-        int_base! { LowerHex for $Uint as $Uint -> LowerHex }
-        int_base! { UpperHex for $Uint as $Uint -> UpperHex }
-        debug! { $Uint }
-    };
+debug! {
+  i8 i16 i32 i64 i128 isize
+  u8 u16 u32 u64 u128 usize
 }
-integer! { isize, usize }
-integer! { i8, u8 }
-integer! { i16, u16 }
-integer! { i32, u32 }
-integer! { i64, u64 }
-integer! { i128, u128 }
 
+// 2 digit decimal look up table
 static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
       2021222324252627282930313233343536373839\
       4041424344454647484950515253545556575859\
@@ -256,21 +273,20 @@ macro_rules! impl_Display {
             f.pad_integral(is_nonnegative, "", buf_slice)
         }
 
-        $(
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl fmt::Display for $t {
-                #[allow(unused_comparisons)]
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    let is_nonnegative = *self >= 0;
-                    let n = if is_nonnegative {
-                        self.$conv_fn()
-                    } else {
-                        // convert the negative num to positive by summing 1 to it's 2 complement
-                        (!self.$conv_fn()).wrapping_add(1)
-                    };
-                    $name(n, is_nonnegative, f)
-                }
-            })*
+        $(#[stable(feature = "rust1", since = "1.0.0")]
+        impl fmt::Display for $t {
+            #[allow(unused_comparisons)]
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let is_nonnegative = *self >= 0;
+                let n = if is_nonnegative {
+                    self.$conv_fn()
+                } else {
+                    // convert the negative num to positive by summing 1 to it's 2 complement
+                    (!self.$conv_fn()).wrapping_add(1)
+                };
+                $name(n, is_nonnegative, f)
+            }
+        })*
     };
 }
 
@@ -461,6 +477,185 @@ mod imp {
     impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
     impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
 }
-
-impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128);
 impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
+
+/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
+fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut isize) {
+    let buf_ptr = MaybeUninit::first_ptr_mut(buf);
+    let lut_ptr = DEC_DIGITS_LUT.as_ptr();
+    assert!(*curr > 19);
+
+    // SAFETY:
+    // Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most
+    // 198, so will never OOB. There is a check above that there are at least 19 characters
+    // remaining.
+    unsafe {
+        if n >= 1e16 as u64 {
+            let to_parse = n % 1e16 as u64;
+            n /= 1e16 as u64;
+
+            // Some of these are nops but it looks more elegant this way.
+            let d1 = ((to_parse / 1e14 as u64) % 100) << 1;
+            let d2 = ((to_parse / 1e12 as u64) % 100) << 1;
+            let d3 = ((to_parse / 1e10 as u64) % 100) << 1;
+            let d4 = ((to_parse / 1e8 as u64) % 100) << 1;
+            let d5 = ((to_parse / 1e6 as u64) % 100) << 1;
+            let d6 = ((to_parse / 1e4 as u64) % 100) << 1;
+            let d7 = ((to_parse / 1e2 as u64) % 100) << 1;
+            let d8 = ((to_parse / 1e0 as u64) % 100) << 1;
+
+            *curr -= 16;
+
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2);
+        }
+        if n >= 1e8 as u64 {
+            let to_parse = n % 1e8 as u64;
+            n /= 1e8 as u64;
+
+            // Some of these are nops but it looks more elegant this way.
+            let d1 = ((to_parse / 1e6 as u64) % 100) << 1;
+            let d2 = ((to_parse / 1e4 as u64) % 100) << 1;
+            let d3 = ((to_parse / 1e2 as u64) % 100) << 1;
+            let d4 = ((to_parse / 1e0 as u64) % 100) << 1;
+            *curr -= 8;
+
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
+        }
+        // `n` < 1e8 < (1 << 32)
+        let mut n = n as u32;
+        if n >= 1e4 as u32 {
+            let to_parse = n % 1e4 as u32;
+            n /= 1e4 as u32;
+
+            let d1 = (to_parse / 100) << 1;
+            let d2 = (to_parse % 100) << 1;
+            *curr -= 4;
+
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+        }
+
+        // `n` < 1e4 < (1 << 16)
+        let mut n = n as u16;
+        if n >= 100 {
+            let d1 = (n % 100) << 1;
+            n /= 100;
+            *curr -= 2;
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+        }
+
+        // decode last 1 or 2 chars
+        if n < 10 {
+            *curr -= 1;
+            *buf_ptr.offset(*curr) = (n as u8) + b'0';
+        } else {
+            let d1 = n << 1;
+            *curr -= 2;
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for u128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt_u128(*self, true, f)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for i128 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let is_nonnegative = *self >= 0;
+        let n = if is_nonnegative {
+            self.to_u128()
+        } else {
+            // convert the negative num to positive by summing 1 to it's 2 complement
+            (!self.to_u128()).wrapping_add(1)
+        };
+        fmt_u128(n, is_nonnegative, f)
+    }
+}
+
+/// Specialized optimization for u128. Instead of taking two items at a time, it splits
+/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
+/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
+/// 10^20 > 2^64 > 10^19.
+fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    // 2^128 is about 3*10^38, so 39 gives an extra byte of space
+    let mut buf = [MaybeUninit::<u8>::uninit(); 39];
+    let mut curr = buf.len() as isize;
+    let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
+
+    let (n, rem) = udiv_1e19(n);
+    parse_u64_into(rem, &mut buf, &mut curr);
+
+    if n != 0 {
+        // 0 pad up to point
+        let target = (buf.len() - 19) as isize;
+        // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
+        // remaining since it has length 39
+        unsafe {
+            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
+        }
+        curr = target;
+
+        let (n, rem) = udiv_1e19(n);
+        parse_u64_into(rem, &mut buf, &mut curr);
+        // Should this following branch be annotated with unlikely?
+        if n != 0 {
+            let target = (buf.len() - 38) as isize;
+            // SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
+            // There can only be at most 1 digit remaining.
+            unsafe {
+                ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
+                curr = target - 1;
+                *buf_ptr.offset(curr) = (n as u8) + b'0';
+            }
+        }
+    }
+
+    // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
+    // UTF-8 since `DEC_DIGITS_LUT` is
+    let buf_slice = unsafe {
+        str::from_utf8_unchecked(slice::from_raw_parts(
+            buf_ptr.offset(curr),
+            buf.len() - curr as usize,
+        ))
+    };
+    f.pad_integral(is_nonnegative, "", buf_slice)
+}
+
+/// Partition of `n` into n > 1e19 and rem <= 1e19
+fn udiv_1e19(n: u128) -> (u128, u64) {
+    const DIV: u64 = 1e19 as u64;
+    let high = (n >> 64) as u64;
+    if high == 0 {
+        let low = n as u64;
+        return ((low / DIV) as u128, low % DIV);
+    }
+    let sr = 65 - high.leading_zeros();
+    let mut q = n << (128 - sr);
+    let mut r = n >> sr;
+    let mut carry = 0;
+
+    for _ in 0..sr {
+        r = (r << 1) | (q >> 127);
+        q = (q << 1) | carry as u128;
+
+        let s = (DIV as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
+        carry = (s & 1) as u64;
+        r -= (DIV as u128) & s as u128;
+    }
+    ((q << 1) | carry as u128, r as u64)
+}
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 27a358bddaf4f..ed26c59c17c43 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -268,12 +268,14 @@ where
 }
 
 impl SliceContains for u8 {
+    #[inline]
     fn slice_contains(&self, x: &[Self]) -> bool {
         memchr::memchr(*self, x).is_some()
     }
 }
 
 impl SliceContains for i8 {
+    #[inline]
     fn slice_contains(&self, x: &[Self]) -> bool {
         let byte = *self as u8;
         // SAFETY: `i8` and `u8` have the same memory layout, thus casting `x.as_ptr()`
diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs
index 3b13ed5fed396..ce9c1a6df5044 100644
--- a/library/core/src/slice/memchr.rs
+++ b/library/core/src/slice/memchr.rs
@@ -12,6 +12,7 @@ const HI_U64: u64 = 0x8080808080808080;
 // Use truncation.
 const LO_USIZE: usize = LO_U64 as usize;
 const HI_USIZE: usize = HI_U64 as usize;
+const USIZE_BYTES: usize = mem::size_of::<usize>();
 
 /// Returns `true` if `x` contains any zero byte.
 ///
@@ -38,19 +39,30 @@ fn repeat_byte(b: u8) -> usize {
 }
 
 /// Returns the first index matching the byte `x` in `text`.
+#[inline]
 pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
+    // Fast path for small slices
+    if text.len() < 2 * USIZE_BYTES {
+        return text.iter().position(|elt| *elt == x);
+    }
+
+    memchr_general_case(x, text)
+}
+
+#[inline(never)]
+fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
     // Scan for a single byte value by reading two `usize` words at a time.
     //
     // Split `text` in three parts
     // - unaligned initial part, before the first word aligned address in text
     // - body, scan by 2 words at a time
     // - the last remaining part, < 2 word size
+
+    // search up to an aligned boundary
     let len = text.len();
     let ptr = text.as_ptr();
-    let usize_bytes = mem::size_of::<usize>();
+    let mut offset = ptr.align_offset(USIZE_BYTES);
 
-    // search up to an aligned boundary
-    let mut offset = ptr.align_offset(usize_bytes);
     if offset > 0 {
         offset = cmp::min(offset, len);
         if let Some(index) = text[..offset].iter().position(|elt| *elt == x) {
@@ -60,22 +72,19 @@ pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
 
     // search the body of the text
     let repeated_x = repeat_byte(x);
+    while offset <= len - 2 * USIZE_BYTES {
+        unsafe {
+            let u = *(ptr.add(offset) as *const usize);
+            let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
 
-    if len >= 2 * usize_bytes {
-        while offset <= len - 2 * usize_bytes {
-            unsafe {
-                let u = *(ptr.add(offset) as *const usize);
-                let v = *(ptr.add(offset + usize_bytes) as *const usize);
-
-                // break if there is a matching byte
-                let zu = contains_zero_byte(u ^ repeated_x);
-                let zv = contains_zero_byte(v ^ repeated_x);
-                if zu || zv {
-                    break;
-                }
+            // break if there is a matching byte
+            let zu = contains_zero_byte(u ^ repeated_x);
+            let zv = contains_zero_byte(v ^ repeated_x);
+            if zu || zv {
+                break;
             }
-            offset += usize_bytes * 2;
         }
+        offset += USIZE_BYTES * 2;
     }
 
     // Find the byte after the point the body loop stopped.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 12dcd6c6ba8d0..4192632fe5781 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1636,6 +1636,7 @@ impl<T> [T] {
     /// assert!(!v.iter().any(|e| e == "hi"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn contains(&self, x: &T) -> bool
     where
         T: PartialEq,
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 939f1325c8499..378c8af344b59 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -634,14 +634,18 @@ assume_usize_width! {
 macro_rules! test_float {
     ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => {
         mod $modname {
-            // FIXME(nagisa): these tests should test for sign of -0.0
             #[test]
             fn min() {
                 assert_eq!((0.0 as $fty).min(0.0), 0.0);
+                assert!((0.0 as $fty).min(0.0).is_sign_positive());
                 assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
+                assert!((-0.0 as $fty).min(-0.0).is_sign_negative());
                 assert_eq!((9.0 as $fty).min(9.0), 9.0);
                 assert_eq!((-9.0 as $fty).min(0.0), -9.0);
                 assert_eq!((0.0 as $fty).min(9.0), 0.0);
+                assert!((0.0 as $fty).min(9.0).is_sign_positive());
+                assert_eq!((-0.0 as $fty).min(9.0), -0.0);
+                assert!((-0.0 as $fty).min(9.0).is_sign_negative());
                 assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
                 assert_eq!(($inf as $fty).min(9.0), 9.0);
                 assert_eq!((9.0 as $fty).min($inf), 9.0);
@@ -660,11 +664,19 @@ macro_rules! test_float {
             #[test]
             fn max() {
                 assert_eq!((0.0 as $fty).max(0.0), 0.0);
+                assert!((0.0 as $fty).max(0.0).is_sign_positive());
                 assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
+                assert!((-0.0 as $fty).max(-0.0).is_sign_negative());
                 assert_eq!((9.0 as $fty).max(9.0), 9.0);
                 assert_eq!((-9.0 as $fty).max(0.0), 0.0);
+                assert!((-9.0 as $fty).max(0.0).is_sign_positive());
+                assert_eq!((-9.0 as $fty).max(-0.0), -0.0);
+                assert!((-9.0 as $fty).max(-0.0).is_sign_negative());
                 assert_eq!((0.0 as $fty).max(9.0), 9.0);
+                assert_eq!((0.0 as $fty).max(-9.0), 0.0);
+                assert!((0.0 as $fty).max(-9.0).is_sign_positive());
                 assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
+                assert!((-0.0 as $fty).max(-9.0).is_sign_negative());
                 assert_eq!(($inf as $fty).max(9.0), $inf);
                 assert_eq!((9.0 as $fty).max($inf), $inf);
                 assert_eq!(($inf as $fty).max(-9.0), $inf);
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 61d71d55d6593..1bb835e1eada1 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1102,6 +1102,16 @@ where
 /// documentation for more.
 ///
 /// [`iter`]: HashMap::iter
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter = map.iter();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     base: base::Iter<'a, K, V>,
@@ -1129,6 +1139,16 @@ impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
 /// documentation for more.
 ///
 /// [`iter_mut`]: HashMap::iter_mut
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter = map.iter_mut();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     base: base::IterMut<'a, K, V>,
@@ -1148,6 +1168,16 @@ impl<'a, K, V> IterMut<'a, K, V> {
 /// (provided by the `IntoIterator` trait). See its documentation for more.
 ///
 /// [`into_iter`]: IntoIterator::into_iter
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter = map.into_iter();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
     base: base::IntoIter<K, V>,
@@ -1167,6 +1197,16 @@ impl<K, V> IntoIter<K, V> {
 /// documentation for more.
 ///
 /// [`keys`]: HashMap::keys
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter_keys = map.keys();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -1194,6 +1234,16 @@ impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
 /// documentation for more.
 ///
 /// [`values`]: HashMap::values
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter_values = map.values();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
@@ -1221,6 +1271,16 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
 /// documentation for more.
 ///
 /// [`drain`]: HashMap::drain
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter = map.drain();
+/// ```
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, K: 'a, V: 'a> {
     base: base::Drain<'a, K, V>,
@@ -1239,6 +1299,18 @@ impl<'a, K, V> Drain<'a, K, V> {
 /// This `struct` is created by the [`drain_filter`] method on [`HashMap`].
 ///
 /// [`drain_filter`]: HashMap::drain_filter
+///
+/// # Example
+///
+/// ```
+/// #![feature(hash_drain_filter)]
+///
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter = map.drain_filter(|_k, v| *v % 2 == 0);
+/// ```
 #[unstable(feature = "hash_drain_filter", issue = "59618")]
 pub struct DrainFilter<'a, K, V, F>
 where
@@ -1253,6 +1325,16 @@ where
 /// documentation for more.
 ///
 /// [`values_mut`]: HashMap::values_mut
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter_values = map.values_mut();
+/// ```
 #[stable(feature = "map_values_mut", since = "1.10.0")]
 pub struct ValuesMut<'a, K: 'a, V: 'a> {
     inner: IterMut<'a, K, V>,
@@ -1264,6 +1346,18 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
 /// See its documentation for more.
 ///
 /// [`into_keys`]: HashMap::into_keys
+///
+/// # Example
+///
+/// ```
+/// #![feature(map_into_keys_values)]
+///
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter_keys = map.into_keys();
+/// ```
 #[unstable(feature = "map_into_keys_values", issue = "75294")]
 pub struct IntoKeys<K, V> {
     inner: IntoIter<K, V>,
@@ -1275,6 +1369,18 @@ pub struct IntoKeys<K, V> {
 /// See its documentation for more.
 ///
 /// [`into_values`]: HashMap::into_values
+///
+/// # Example
+///
+/// ```
+/// #![feature(map_into_keys_values)]
+///
+/// use std::collections::HashMap;
+///
+/// let mut map = HashMap::new();
+/// map.insert("a", 1);
+/// let iter_keys = map.into_values();
+/// ```
 #[unstable(feature = "map_into_keys_values", issue = "75294")]
 pub struct IntoValues<K, V> {
     inner: IntoIter<K, V>,
@@ -1285,7 +1391,6 @@ pub struct IntoValues<K, V> {
 /// See the [`HashMap::raw_entry_mut`] docs for usage examples.
 ///
 /// [`HashMap::raw_entry_mut`]: HashMap::raw_entry_mut
-
 #[unstable(feature = "hash_raw_entry", issue = "56167")]
 pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
     map: &'a mut HashMap<K, V, S>,
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 9f3796e11ed1a..3d238b7f764ef 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -110,6 +110,8 @@ use crate::path::Path;
 use crate::str;
 use crate::sys::pipe::{read2, AnonPipe};
 use crate::sys::process as imp;
+#[unstable(feature = "command_access", issue = "44434")]
+pub use crate::sys_common::process::CommandEnvs;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
 /// Representation of a running or exited child process.
@@ -894,6 +896,98 @@ impl Command {
             .map(Child::from_inner)
             .and_then(|mut p| p.wait())
     }
+
+    /// Returns the path to the program that was given to [`Command::new`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(command_access)]
+    /// use std::process::Command;
+    ///
+    /// let cmd = Command::new("echo");
+    /// assert_eq!(cmd.get_program(), "echo");
+    /// ```
+    #[unstable(feature = "command_access", issue = "44434")]
+    pub fn get_program(&self) -> &OsStr {
+        self.inner.get_program()
+    }
+
+    /// Returns an iterator of the arguments that will be passed to the program.
+    ///
+    /// This does not include the path to the program as the first argument;
+    /// it only includes the arguments specified with [`Command::arg`] and
+    /// [`Command::args`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(command_access)]
+    /// use std::ffi::OsStr;
+    /// use std::process::Command;
+    ///
+    /// let mut cmd = Command::new("echo");
+    /// cmd.arg("first").arg("second");
+    /// let args: Vec<&OsStr> = cmd.get_args().collect();
+    /// assert_eq!(args, &["first", "second"]);
+    /// ```
+    #[unstable(feature = "command_access", issue = "44434")]
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        CommandArgs { inner: self.inner.get_args() }
+    }
+
+    /// Returns an iterator of the environment variables that will be set when
+    /// the process is spawned.
+    ///
+    /// Each element is a tuple `(&OsStr, Option<&OsStr>)`, where the first
+    /// value is the key, and the second is the value, which is [`None`] if
+    /// the environment variable is to be explicitly removed.
+    ///
+    /// This only includes environment variables explicitly set with
+    /// [`Command::env`], [`Command::envs`], and [`Command::env_remove`]. It
+    /// does not include environment variables that will be inherited by the
+    /// child process.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(command_access)]
+    /// use std::ffi::OsStr;
+    /// use std::process::Command;
+    ///
+    /// let mut cmd = Command::new("ls");
+    /// cmd.env("TERM", "dumb").env_remove("TZ");
+    /// let envs: Vec<(&OsStr, Option<&OsStr>)> = cmd.get_envs().collect();
+    /// assert_eq!(envs, &[
+    ///     (OsStr::new("TERM"), Some(OsStr::new("dumb"))),
+    ///     (OsStr::new("TZ"), None)
+    /// ]);
+    /// ```
+    #[unstable(feature = "command_access", issue = "44434")]
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        self.inner.get_envs()
+    }
+
+    /// Returns the working directory for the child process.
+    ///
+    /// This returns [`None`] if the working directory will not be changed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(command_access)]
+    /// use std::path::Path;
+    /// use std::process::Command;
+    ///
+    /// let mut cmd = Command::new("ls");
+    /// assert_eq!(cmd.get_current_dir(), None);
+    /// cmd.current_dir("/bin");
+    /// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin")));
+    /// ```
+    #[unstable(feature = "command_access", issue = "44434")]
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        self.inner.get_current_dir()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -918,6 +1012,37 @@ impl AsInnerMut<imp::Command> for Command {
     }
 }
 
+/// An iterator over the command arguments.
+///
+/// This struct is created by [`Command::get_args`]. See its documentation for
+/// more.
+#[unstable(feature = "command_access", issue = "44434")]
+#[derive(Debug)]
+pub struct CommandArgs<'a> {
+    inner: imp::CommandArgs<'a>,
+}
+
+#[unstable(feature = "command_access", issue = "44434")]
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+    fn next(&mut self) -> Option<&'a OsStr> {
+        self.inner.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
+    }
+}
+
+#[unstable(feature = "command_access", issue = "44434")]
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.inner.is_empty()
+    }
+}
+
 /// The output of a finished process.
 ///
 /// This is returned in a Result by either the [`output`] method of a
diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs
index 553e980f08e97..1b7b93f9d4a5f 100644
--- a/library/std/src/sys/unix/process/mod.rs
+++ b/library/std/src/sys/unix/process/mod.rs
@@ -1,6 +1,7 @@
-pub use self::process_common::{Command, ExitCode, Stdio, StdioPipes};
+pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes};
 pub use self::process_inner::{ExitStatus, Process};
 pub use crate::ffi::OsString as EnvKey;
+pub use crate::sys_common::process::CommandEnvs;
 
 mod process_common;
 #[cfg(not(target_os = "fuchsia"))]
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index f8666485eeccb..9ddd4ad4000ef 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -7,11 +7,12 @@ use crate::collections::BTreeMap;
 use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::fmt;
 use crate::io;
+use crate::path::Path;
 use crate::ptr;
 use crate::sys::fd::FileDesc;
 use crate::sys::fs::File;
 use crate::sys::pipe::{self, AnonPipe};
-use crate::sys_common::process::CommandEnv;
+use crate::sys_common::process::{CommandEnv, CommandEnvs};
 
 #[cfg(not(target_os = "fuchsia"))]
 use crate::sys::fs::OpenOptions;
@@ -184,11 +185,30 @@ impl Command {
     pub fn saw_nul(&self) -> bool {
         self.saw_nul
     }
+
+    pub fn get_program(&self) -> &OsStr {
+        OsStr::from_bytes(self.program.as_bytes())
+    }
+
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        let mut iter = self.args.iter();
+        iter.next();
+        CommandArgs { iter }
+    }
+
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        self.env.iter()
+    }
+
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        self.cwd.as_ref().map(|cs| Path::new(OsStr::from_bytes(cs.as_bytes())))
+    }
+
     pub fn get_argv(&self) -> &Vec<*const c_char> {
         &self.argv.0
     }
 
-    pub fn get_program(&self) -> &CStr {
+    pub fn get_program_cstr(&self) -> &CStr {
         &*self.program
     }
 
@@ -402,3 +422,32 @@ impl ExitCode {
         self.0 as i32
     }
 }
+
+pub struct CommandArgs<'a> {
+    iter: crate::slice::Iter<'a, CString>,
+}
+
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+    fn next(&mut self) -> Option<&'a OsStr> {
+        self.iter.next().map(|cs| OsStr::from_bytes(cs.as_bytes()))
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+impl<'a> fmt::Debug for CommandArgs<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter.clone()).finish()
+    }
+}
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 08efe154e4c3b..50f5e78cf2a88 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -245,7 +245,7 @@ impl Command {
             *sys::os::environ() = envp.as_ptr();
         }
 
-        libc::execvp(self.get_program().as_ptr(), self.get_argv().as_ptr());
+        libc::execvp(self.get_program_cstr().as_ptr(), self.get_argv().as_ptr());
         Err(io::Error::last_os_error())
     }
 
@@ -383,7 +383,7 @@ impl Command {
             let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
             let ret = libc::posix_spawnp(
                 &mut p.pid,
-                self.get_program().as_ptr(),
+                self.get_program_cstr().as_ptr(),
                 file_actions.0.as_ptr(),
                 attrs.0.as_ptr(),
                 self.get_argv().as_ptr() as *const _,
diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs
index 7156c9ab92f2b..3ede2291d5a91 100644
--- a/library/std/src/sys/unsupported/process.rs
+++ b/library/std/src/sys/unsupported/process.rs
@@ -1,10 +1,12 @@
 use crate::ffi::OsStr;
 use crate::fmt;
 use crate::io;
+use crate::marker::PhantomData;
+use crate::path::Path;
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
+use crate::sys_common::process::{CommandEnv, CommandEnvs};
 
 pub use crate::ffi::OsString as EnvKey;
 
@@ -49,6 +51,22 @@ impl Command {
 
     pub fn stderr(&mut self, _stderr: Stdio) {}
 
+    pub fn get_program(&self) -> &OsStr {
+        panic!("unsupported")
+    }
+
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        CommandArgs { _p: PhantomData }
+    }
+
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        self.env.iter()
+    }
+
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        None
+    }
+
     pub fn spawn(
         &mut self,
         _default: Stdio,
@@ -147,3 +165,22 @@ impl Process {
         match self.0 {}
     }
 }
+
+pub struct CommandArgs<'a> {
+    _p: PhantomData<&'a ()>,
+}
+
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+    fn next(&mut self) -> Option<&'a OsStr> {
+        None
+    }
+}
+
+impl<'a> ExactSizeIterator for CommandArgs<'a> {}
+
+impl<'a> fmt::Debug for CommandArgs<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().finish()
+    }
+}
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index e18521bb30d91..243065b94b125 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -22,7 +22,7 @@ use crate::sys::handle::Handle;
 use crate::sys::mutex::Mutex;
 use crate::sys::pipe::{self, AnonPipe};
 use crate::sys::stdio;
-use crate::sys_common::process::CommandEnv;
+use crate::sys_common::process::{CommandEnv, CommandEnvs};
 use crate::sys_common::AsInner;
 
 use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
@@ -134,6 +134,23 @@ impl Command {
         self.flags = flags;
     }
 
+    pub fn get_program(&self) -> &OsStr {
+        &self.program
+    }
+
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        let iter = self.args.iter();
+        CommandArgs { iter }
+    }
+
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        self.env.iter()
+    }
+
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        self.cwd.as_ref().map(|cwd| Path::new(cwd))
+    }
+
     pub fn spawn(
         &mut self,
         default: Stdio,
@@ -529,3 +546,32 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> {
         None => Ok((ptr::null(), Vec::new())),
     }
 }
+
+pub struct CommandArgs<'a> {
+    iter: crate::slice::Iter<'a, OsString>,
+}
+
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+    fn next(&mut self) -> Option<&'a OsStr> {
+        self.iter.next().map(|s| s.as_ref())
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+impl<'a> fmt::Debug for CommandArgs<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter.clone()).finish()
+    }
+}
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs
index f3a2962098b4d..fe89b11043c0f 100644
--- a/library/std/src/sys_common/process.rs
+++ b/library/std/src/sys_common/process.rs
@@ -92,4 +92,41 @@ impl CommandEnv {
             self.saw_path = true;
         }
     }
+
+    pub fn iter(&self) -> CommandEnvs<'_> {
+        let iter = self.vars.iter();
+        CommandEnvs { iter }
+    }
+}
+
+/// An iterator over the command environment variables.
+///
+/// This struct is created by
+/// [`Command::get_envs`][crate::process::Command::get_envs]. See its
+/// documentation for more.
+#[unstable(feature = "command_access", issue = "44434")]
+#[derive(Debug)]
+pub struct CommandEnvs<'a> {
+    iter: crate::collections::btree_map::Iter<'a, EnvKey, Option<OsString>>,
+}
+
+#[unstable(feature = "command_access", issue = "44434")]
+impl<'a> Iterator for CommandEnvs<'a> {
+    type Item = (&'a OsStr, Option<&'a OsStr>);
+    fn next(&mut self) -> Option<Self::Item> {
+        self.iter.next().map(|(key, value)| (key.as_ref(), value.as_deref()))
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+#[unstable(feature = "command_access", issue = "44434")]
+impl<'a> ExactSizeIterator for CommandEnvs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
 }
diff --git a/src/test/codegen/issue-75659.rs b/src/test/codegen/issue-75659.rs
new file mode 100644
index 0000000000000..8f0ce8ef9a81b
--- /dev/null
+++ b/src/test/codegen/issue-75659.rs
@@ -0,0 +1,62 @@
+// This test checks that the call to memchr/slice_contains is optimized away
+// when searching in small slices.
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @foo1
+#[no_mangle]
+pub fn foo1(x: u8, data: &[u8; 1]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo2
+#[no_mangle]
+pub fn foo2(x: u8, data: &[u8; 2]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo3
+#[no_mangle]
+pub fn foo3(x: u8, data: &[u8; 3]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo4
+#[no_mangle]
+pub fn foo4(x: u8, data: &[u8; 4]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8
+#[no_mangle]
+pub fn foo8(x: u8, data: &[u8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// CHECK-LABEL: @foo8_i8
+#[no_mangle]
+pub fn foo8_i8(x: i8, data: &[i8; 8]) -> bool {
+    // CHECK-NOT: memchr
+    // CHECK-NOT: slice_contains
+    data.contains(&x)
+}
+
+// Check that the general case isn't inlined
+// CHECK-LABEL: @foo80
+#[no_mangle]
+pub fn foo80(x: u8, data: &[u8; 80]) -> bool {
+    // CHECK: call core::slice::memchr
+    data.contains(&x)
+}
diff --git a/src/tools/cargo b/src/tools/cargo
index 8777a6b1e8834..05c611ae3c425 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 8777a6b1e8834899f51b7e09cc9b8d85b2417110
+Subproject commit 05c611ae3c4255b7a2bcf4fcfa65b20286a07839
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 58112ac8da5f1..c3ff34e6e1eed 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(concat_idents)]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
+#![feature(in_band_lifetimes)]
 #![feature(or_patterns)]
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 1ad184dfc460b..e5f7cc5111120 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn;
+use crate::utils::qualify_min_const_fn::is_min_const_fn;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 use rustc_typeck::hir_ty_to_ty;
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index ea52741b7cc42..96d9905027b62 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -20,6 +20,7 @@ pub mod paths;
 pub mod ptr;
 pub mod sugg;
 pub mod usage;
+pub mod qualify_min_const_fn;
 
 pub use self::attrs::*;
 pub use self::diagnostics::*;
diff --git a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
similarity index 71%
rename from compiler/rustc_mir/src/transform/qualify_min_const_fn.rs
rename to src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
index f15a7f7c2c889..6809b1fa88d35 100644
--- a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{sym};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use std::borrow::Cow;
@@ -11,14 +11,6 @@ use std::borrow::Cow;
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
 
 pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult {
-    // Prevent const trait methods from being annotated as `stable`.
-    if tcx.features().staged_api {
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-        if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
-            return Err((body.span, "trait methods cannot be stable const fn".into()));
-        }
-    }
-
     let mut current = def_id;
     loop {
         let predicates = tcx.predicates_of(current);
@@ -32,27 +24,20 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
                 | ty::PredicateAtom::ConstEquate(..)
                 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
                 ty::PredicateAtom::ObjectSafe(_) => {
-                    bug!("object safe predicate on function: {:#?}", predicate)
+                    panic!("object safe predicate on function: {:#?}", predicate)
                 }
                 ty::PredicateAtom::ClosureKind(..) => {
-                    bug!("closure kind predicate on function: {:#?}", predicate)
+                    panic!("closure kind predicate on function: {:#?}", predicate)
                 }
                 ty::PredicateAtom::Subtype(_) => {
-                    bug!("subtype predicate on function: {:#?}", predicate)
+                    panic!("subtype predicate on function: {:#?}", predicate)
                 }
-                ty::PredicateAtom::Trait(pred, constness) => {
+                ty::PredicateAtom::Trait(pred, _) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
                     }
                     match pred.self_ty().kind() {
                         ty::Param(ref p) => {
-                            // Allow `T: ?const Trait`
-                            if constness == hir::Constness::NotConst
-                                && feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
-                            {
-                                continue;
-                            }
-
                             let generics = tcx.generics_of(current);
                             let def = generics.type_param(p, tcx);
                             let span = tcx.def_span(def.def_id);
@@ -77,18 +62,17 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
     }
 
     for local in &body.local_decls {
-        check_ty(tcx, local.ty, local.source_info.span, def_id)?;
+        check_ty(tcx, local.ty, local.source_info.span)?;
     }
     // impl trait is gone in MIR, so check the return type manually
     check_ty(
         tcx,
         tcx.fn_sig(def_id).output().skip_binder(),
         body.local_decls.iter().next().unwrap().source_info.span,
-        def_id,
     )?;
 
     for bb in body.basic_blocks() {
-        check_terminator(tcx, body, def_id, bb.terminator())?;
+        check_terminator(tcx, body, bb.terminator())?;
         for stmt in &bb.statements {
             check_statement(tcx, body, def_id, stmt)?;
         }
@@ -96,7 +80,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
     Ok(())
 }
 
-fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult {
+fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
     for arg in ty.walk() {
         let ty = match arg.unpack() {
             GenericArgKind::Type(ty) => ty,
@@ -108,15 +92,11 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
 
         match ty.kind() {
             ty::Ref(_, _, hir::Mutability::Mut) => {
-                if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
                     return Err((span, "mutable references in const fn are unstable".into()));
-                }
             }
             ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
-                if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
                     return Err((span, "function pointers in const fn are unstable".into()));
-                }
             }
             ty::Dynamic(preds, _) => {
                 for pred in preds.iter() {
@@ -161,12 +141,12 @@ fn check_rvalue(
             Err((span, "cannot access thread local storage in const fn".into()))
         }
         Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
-            check_operand(tcx, operand, span, def_id, body)
+            check_operand(tcx, operand, span, body)
         }
         Rvalue::Len(place)
         | Rvalue::Discriminant(place)
         | Rvalue::Ref(_, _, place)
-        | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, def_id, body),
+        | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span,  body),
         Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
             use rustc_middle::ty::cast::CastTy;
             let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
@@ -175,14 +155,14 @@ fn check_rvalue(
                 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
                     Err((span, "casting pointers to ints is unstable in const fn".into()))
                 }
-                _ => check_operand(tcx, operand, span, def_id, body),
+                _ => check_operand(tcx, operand, span, body),
             }
         }
         Rvalue::Cast(
             CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
             operand,
             _,
-        ) => check_operand(tcx, operand, span, def_id, body),
+        ) => check_operand(tcx, operand, span, body),
         Rvalue::Cast(
             CastKind::Pointer(
                 PointerCast::UnsafeFnPointer
@@ -204,7 +184,7 @@ fn check_rvalue(
             };
             let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
             if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
-                check_operand(tcx, op, span, def_id, body)?;
+                check_operand(tcx, op, span, body)?;
                 // Casting/coercing things to slices is fine.
                 Ok(())
             } else {
@@ -214,8 +194,8 @@ fn check_rvalue(
         }
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
-            check_operand(tcx, lhs, span, def_id, body)?;
-            check_operand(tcx, rhs, span, def_id, body)?;
+            check_operand(tcx, lhs, span, body)?;
+            check_operand(tcx, rhs, span, body)?;
             let ty = lhs.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() || ty.is_char() {
                 Ok(())
@@ -230,14 +210,14 @@ fn check_rvalue(
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() {
-                check_operand(tcx, operand, span, def_id, body)
+                check_operand(tcx, operand, span, body)
             } else {
                 Err((span, "only int and `bool` operations are stable in const fn".into()))
             }
         }
         Rvalue::Aggregate(_, operands) => {
             for operand in operands {
-                check_operand(tcx, operand, span, def_id, body)?;
+                check_operand(tcx, operand, span, body)?;
             }
             Ok(())
         }
@@ -253,15 +233,15 @@ fn check_statement(
     let span = statement.source_info.span;
     match &statement.kind {
         StatementKind::Assign(box (place, rval)) => {
-            check_place(tcx, *place, span, def_id, body)?;
+            check_place(tcx, *place, span,  body)?;
             check_rvalue(tcx, body, def_id, rval, span)
         }
 
-        StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, def_id, body),
+        StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, body),
 
         // just an assignment
         StatementKind::SetDiscriminant { place, .. } => {
-            check_place(tcx, **place, span, def_id, body)
+            check_place(tcx, **place, span,  body)
         }
 
         StatementKind::LlvmInlineAsm { .. } => {
@@ -282,11 +262,10 @@ fn check_operand(
     tcx: TyCtxt<'tcx>,
     operand: &Operand<'tcx>,
     span: Span,
-    def_id: DefId,
     body: &Body<'tcx>,
 ) -> McfResult {
     match operand {
-        Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, def_id, body),
+        Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
         Operand::Constant(c) => match c.check_static_ptr(tcx) {
             Some(_) => Err((span, "cannot access `static` items in const fn".into())),
             None => Ok(()),
@@ -298,7 +277,6 @@ fn check_place(
     tcx: TyCtxt<'tcx>,
     place: Place<'tcx>,
     span: Span,
-    def_id: DefId,
     body: &Body<'tcx>,
 ) -> McfResult {
     let mut cursor = place.projection.as_ref();
@@ -310,9 +288,7 @@ fn check_place(
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
-                        if !feature_allowed(tcx, def_id, sym::const_fn_union) {
                             return Err((span, "accessing union fields is unstable".into()));
-                        }
                     }
                 }
             }
@@ -327,48 +303,9 @@ fn check_place(
     Ok(())
 }
 
-/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
-fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
-    // All features require that the corresponding gate be enabled,
-    // even if the function has `#[allow_internal_unstable(the_gate)]`.
-    if !tcx.features().enabled(feature_gate) {
-        return false;
-    }
-
-    // If this crate is not using stability attributes, or this function is not claiming to be a
-    // stable `const fn`, that is all that is required.
-    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
-        return true;
-    }
-
-    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
-    // opt-in via `allow_internal_unstable`.
-    super::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
-}
-
-/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
-pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
-    // All features require that the corresponding gate be enabled,
-    // even if the function has `#[allow_internal_unstable(the_gate)]`.
-    if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
-        return false;
-    }
-
-    // If this crate is not using stability attributes, or this function is not claiming to be a
-    // stable `const fn`, that is all that is required.
-    if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
-        return true;
-    }
-
-    // However, we cannot allow stable `const fn`s to use unstable features without an explicit
-    // opt-in via `allow_internal_unstable`.
-    super::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
-}
-
 fn check_terminator(
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
-    def_id: DefId,
     terminator: &Terminator<'tcx>,
 ) -> McfResult {
     let span = terminator.source_info.span;
@@ -380,14 +317,14 @@ fn check_terminator(
         | TerminatorKind::Resume
         | TerminatorKind::Unreachable => Ok(()),
 
-        TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, def_id, body),
+        TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span,  body),
         TerminatorKind::DropAndReplace { place, value, .. } => {
-            check_place(tcx, *place, span, def_id, body)?;
-            check_operand(tcx, value, span, def_id, body)
+            check_place(tcx, *place, span,  body)?;
+            check_operand(tcx, value, span, body)
         }
 
         TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
-            check_operand(tcx, discr, span, def_id, body)
+            check_operand(tcx, discr, span, body)
         }
 
         TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
@@ -405,15 +342,7 @@ fn check_terminator(
         } => {
             let fn_ty = func.ty(body, tcx);
             if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
-                // Allow unstable const if we opt in by using #[allow_internal_unstable]
-                // on function or macro declaration.
-                if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
-                    && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
-                        .map(|feature| {
-                            span.allows_unstable(feature)
-                                || lib_feature_allowed(tcx, def_id, feature)
-                        })
-                        .unwrap_or(false)
+                if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id)
                 {
                     return Err((
                         span,
@@ -432,7 +361,6 @@ fn check_terminator(
                 // transmutes in const fn before we add more hacks to this.
                 if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
                     && tcx.item_name(fn_def_id) == sym::transmute
-                    && !feature_allowed(tcx, def_id, sym::const_fn_transmute)
                 {
                     return Err((
                         span,
@@ -440,10 +368,10 @@ fn check_terminator(
                     ));
                 }
 
-                check_operand(tcx, func, span, fn_def_id, body)?;
+                check_operand(tcx, func, span, body)?;
 
                 for arg in args {
-                    check_operand(tcx, arg, span, fn_def_id, body)?;
+                    check_operand(tcx, arg, span, body)?;
                 }
                 Ok(())
             } else {
@@ -452,7 +380,7 @@ fn check_terminator(
         }
 
         TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
-            check_operand(tcx, cond, span, def_id, body)
+            check_operand(tcx, cond, span, body)
         }
 
         TerminatorKind::InlineAsm { .. } => {