about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--README.md2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs114
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs20
-rw-r--r--compiler/rustc_driver/Cargo.toml2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs9
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs20
-rw-r--r--compiler/rustc_middle/src/mir/query.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs9
-rw-r--r--compiler/rustc_mir/src/borrow_check/invalidation.rs9
-rw-r--r--compiler/rustc_mir/src/borrow_check/mod.rs9
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs6
-rw-r--r--compiler/rustc_mir/src/dataflow/impls/borrows.rs1
-rw-r--r--compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs1
-rw-r--r--compiler/rustc_mir/src/dataflow/move_paths/builder.rs1
-rw-r--r--compiler/rustc_mir/src/interpret/intrinsics.rs24
-rw-r--r--compiler/rustc_mir/src/interpret/step.rs36
-rw-r--r--compiler/rustc_mir/src/lib.rs1
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs1
-rw-r--r--compiler/rustc_mir/src/transform/check_unsafety.rs6
-rw-r--r--compiler/rustc_mir/src/transform/coverage/graph.rs5
-rw-r--r--compiler/rustc_mir/src/transform/coverage/spans.rs1
-rw-r--r--compiler/rustc_mir/src/transform/dest_prop.rs1
-rw-r--r--compiler/rustc_mir/src/transform/generator.rs1
-rw-r--r--compiler/rustc_mir/src/transform/lower_intrinsics.rs21
-rw-r--r--compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs1
-rw-r--r--compiler/rustc_mir/src/transform/simplify.rs1
-rw-r--r--compiler/rustc_mir/src/transform/validate.rs44
-rw-r--r--compiler/rustc_mir/src/util/spanview.rs1
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs16
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs7
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/option.rs28
-rw-r--r--library/core/tests/lib.rs4
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/process.rs25
-rw-r--r--library/std/src/sys/unix/ext/process.rs14
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs17
-rw-r--r--library/std/src/sys/unix/process/process_unix/tests.rs30
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr30
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs1
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr32
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs9
m---------src/tools/rust-analyzer32
56 files changed, 454 insertions, 204 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 120403b3bf6..25039b5cbd9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5460,9 +5460,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-tree"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a60657cfbf397c603257a8230b3f427e6a2a4e5911a59331b9bb4dffff5b608"
+checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967"
 dependencies = [
  "ansi_term 0.12.1",
  "atty",
diff --git a/README.md b/README.md
index 6ab11e7e2be..cc073875cde 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
    * `g++` 5.1 or later or `clang++` 3.5 or later
    * `python` 3 or 2.7
    * GNU `make` 3.81 or later
-   * `cmake` 3.4.3 or later
+   * `cmake` 3.13.4 or later
    * `ninja`
    * `curl`
    * `git`
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index f2c61c95f4f..8b5ae9e0541 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -832,6 +832,27 @@ fn codegen_stmt<'tcx>(
             }
         }
         StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
+        StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
+          src,
+          dst,
+          count,
+        }) => {
+            let dst = codegen_operand(fx, dst);
+            let pointee = dst
+              .layout()
+              .pointee_info_at(fx, rustc_target::abi::Size::ZERO)
+              .expect("Expected pointer");
+            let dst = dst.load_scalar(fx);
+            let src = codegen_operand(fx, src).load_scalar(fx);
+            let count = codegen_operand(fx, count).load_scalar(fx);
+            let elem_size: u64 = pointee.size.bytes();
+            let bytes = if elem_size != 1 {
+               fx.bcx.ins().imul_imm(count, elem_size as i64)
+            } else {
+               count
+            };
+            fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes);
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 0307117e1c8..2c2330409fd 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(or_patterns)]
 #![feature(associated_type_bounds)]
 #![recursion_limit = "256"]
+#![feature(box_syntax)]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
 //! The backend-agnostic functions of this crate use functions defined in various traits that
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 9ce90669800..e148ed7ad3b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -641,67 +641,73 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             return;
         }
 
-        if intrinsic.is_some() && intrinsic != Some(sym::drop_in_place) {
-            let intrinsic = intrinsic.unwrap();
-            let dest = match ret_dest {
-                _ if fn_abi.ret.is_indirect() => llargs[0],
-                ReturnDest::Nothing => {
-                    bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret)))
-                }
-                ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.llval,
-                ReturnDest::DirectOperand(_) => {
-                    bug!("Cannot use direct operand with an intrinsic call")
-                }
-            };
+        match intrinsic {
+            None | Some(sym::drop_in_place) => {}
+            Some(sym::copy_nonoverlapping) => unreachable!(),
+            Some(intrinsic) => {
+                let dest = match ret_dest {
+                    _ if fn_abi.ret.is_indirect() => llargs[0],
+                    ReturnDest::Nothing => {
+                        bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret)))
+                    }
+                    ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.llval,
+                    ReturnDest::DirectOperand(_) => {
+                        bug!("Cannot use direct operand with an intrinsic call")
+                    }
+                };
 
-            let args: Vec<_> = args
-                .iter()
-                .enumerate()
-                .map(|(i, arg)| {
-                    // The indices passed to simd_shuffle* in the
-                    // third argument must be constant. This is
-                    // checked by const-qualification, which also
-                    // promotes any complex rvalues to constants.
-                    if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
-                        if let mir::Operand::Constant(constant) = arg {
-                            let c = self.eval_mir_constant(constant);
-                            let (llval, ty) = self.simd_shuffle_indices(
-                                &bx,
-                                constant.span,
-                                constant.literal.ty,
-                                c,
-                            );
-                            return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty) };
-                        } else {
-                            span_bug!(span, "shuffle indices must be constant");
+                let args: Vec<_> = args
+                    .iter()
+                    .enumerate()
+                    .map(|(i, arg)| {
+                        // The indices passed to simd_shuffle* in the
+                        // third argument must be constant. This is
+                        // checked by const-qualification, which also
+                        // promotes any complex rvalues to constants.
+                        if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
+                            if let mir::Operand::Constant(constant) = arg {
+                                let c = self.eval_mir_constant(constant);
+                                let (llval, ty) = self.simd_shuffle_indices(
+                                    &bx,
+                                    constant.span,
+                                    constant.literal.ty,
+                                    c,
+                                );
+                                return OperandRef {
+                                    val: Immediate(llval),
+                                    layout: bx.layout_of(ty),
+                                };
+                            } else {
+                                span_bug!(span, "shuffle indices must be constant");
+                            }
                         }
-                    }
 
-                    self.codegen_operand(&mut bx, arg)
-                })
-                .collect();
+                        self.codegen_operand(&mut bx, arg)
+                    })
+                    .collect();
+
+                Self::codegen_intrinsic_call(
+                    &mut bx,
+                    *instance.as_ref().unwrap(),
+                    &fn_abi,
+                    &args,
+                    dest,
+                    span,
+                );
 
-            Self::codegen_intrinsic_call(
-                &mut bx,
-                *instance.as_ref().unwrap(),
-                &fn_abi,
-                &args,
-                dest,
-                span,
-            );
+                if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
+                    self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval);
+                }
 
-            if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
-                self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval);
-            }
+                if let Some((_, target)) = *destination {
+                    helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
+                    helper.funclet_br(self, &mut bx, target);
+                } else {
+                    bx.unreachable();
+                }
 
-            if let Some((_, target)) = *destination {
-                helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
-                helper.funclet_br(self, &mut bx, target);
-            } else {
-                bx.unreachable();
+                return;
             }
-
-            return;
         }
 
         // Split the rust-call tupled arguments off.
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 80e3ed75b85..8502309b90e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -125,19 +125,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let offset = args[1].immediate();
                 bx.gep(ptr, &[offset])
             }
-
-            sym::copy_nonoverlapping => {
-                copy_intrinsic(
-                    bx,
-                    false,
-                    false,
-                    substs.type_at(0),
-                    args[1].immediate(),
-                    args[0].immediate(),
-                    args[2].immediate(),
-                );
-                return;
-            }
             sym::copy => {
                 copy_intrinsic(
                     bx,
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 6f74ba77d4c..5523e5f2e86 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -115,6 +115,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_coverage(&mut bx, coverage.clone());
                 bx
             }
+            mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping {
+                ref src,
+                ref dst,
+                ref count,
+            }) => {
+                let dst_val = self.codegen_operand(&mut bx, dst);
+                let src_val = self.codegen_operand(&mut bx, src);
+                let count = self.codegen_operand(&mut bx, count).immediate();
+                let pointee_layout = dst_val
+                    .layout
+                    .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
+                    .expect("Expected pointer");
+                let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
+
+                let align = pointee_layout.align;
+                let dst = dst_val.immediate();
+                let src = src_val.immediate();
+                bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty());
+                bx
+            }
             mir::StatementKind::FakeRead(..)
             | mir::StatementKind::Retag { .. }
             | mir::StatementKind::AscribeUserType(..)
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 47cff34cd3e..93c6ec04e4f 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -12,7 +12,7 @@ libc = "0.2"
 atty = "0.2"
 tracing = { version = "0.1.25" }
 tracing-subscriber = { version = "0.2.16", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
-tracing-tree = "0.1.8"
+tracing-tree = "0.1.9"
 rustc_middle = { path = "../rustc_middle" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 5012d500cee..9902b6cc9e8 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -275,6 +275,8 @@ declare_features! (
     (accepted, move_ref_pattern, "1.49.0", Some(68354), None),
     /// The smallest useful subset of `const_generics`.
     (accepted, min_const_generics, "1.51.0", Some(74878), None),
+    /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
+    (accepted, unsafe_block_in_unsafe_fn, "1.51.0", Some(71668), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 8ee995a59d8..9cb06684c0f 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -557,9 +557,6 @@ declare_features! (
     /// Allows the use of `#[ffi_const]` on foreign functions.
     (active, ffi_const, "1.45.0", Some(58328), None),
 
-    /// No longer treat an unsafe function as an unsafe block.
-    (active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),
-
     /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
     (active, abi_avr_interrupt, "1.45.0", Some(69664), None),
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e6f81ce828f..af48f6c2a5d 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -8,7 +8,6 @@
 
 use crate::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::symbol::sym;
 
 declare_lint! {
     /// The `forbidden_lint_groups` lint detects violations of
@@ -2489,16 +2488,11 @@ declare_lint! {
 
 declare_lint! {
     /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
-    /// functions without an explicit unsafe block. This lint only works on
-    /// the [**nightly channel**] with the
-    /// `#![feature(unsafe_block_in_unsafe_fn)]` feature.
-    ///
-    /// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
+    /// functions without an explicit unsafe block.
     ///
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![feature(unsafe_block_in_unsafe_fn)]
     /// #![deny(unsafe_op_in_unsafe_fn)]
     ///
     /// unsafe fn foo() {}
@@ -2536,7 +2530,6 @@ declare_lint! {
     pub UNSAFE_OP_IN_UNSAFE_FN,
     Allow,
     "unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
-    @feature_gate = sym::unsafe_block_in_unsafe_fn;
 }
 
 declare_lint! {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 42bbc9a0d95..f6952667494 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1541,6 +1541,11 @@ pub enum StatementKind<'tcx> {
     /// counter varible at runtime, each time the code region is executed.
     Coverage(Box<Coverage>),
 
+    /// Denotes a call to the intrinsic function copy_overlapping, where `src_dst` denotes the
+    /// memory being read from and written to(one field to save memory), and size
+    /// indicates how many bytes are being copied over.
+    CopyNonOverlapping(Box<CopyNonOverlapping<'tcx>>),
+
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
 }
@@ -1659,6 +1664,13 @@ impl Debug for Statement<'_> {
                     write!(fmt, "Coverage::{:?}", coverage.kind)
                 }
             }
+            CopyNonOverlapping(box crate::mir::CopyNonOverlapping {
+                ref src,
+                ref dst,
+                ref count,
+            }) => {
+                write!(fmt, "copy_nonoverlapping(src={:?}, dst={:?}, count={:?})", src, dst, count)
+            }
             Nop => write!(fmt, "nop"),
         }
     }
@@ -1670,6 +1682,14 @@ pub struct Coverage {
     pub code_region: Option<CodeRegion>,
 }
 
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
+pub struct CopyNonOverlapping<'tcx> {
+    pub src: Operand<'tcx>,
+    pub dst: Operand<'tcx>,
+    /// Number of elements to copy from src to dest, not bytes.
+    pub count: Operand<'tcx>,
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Places
 
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index f2f7242a8fd..bde48018013 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -28,11 +28,9 @@ pub enum UnsafetyViolationKind {
     BorrowPacked,
     /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
     /// Has to be handled as a lint for backwards compatibility.
-    /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
     UnsafeFn,
     /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block.
     /// Has to be handled as a lint for backwards compatibility.
-    /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
     UnsafeFnBorrowPacked,
 }
 
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 464220cf77e..4e81612c0b9 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -436,6 +436,15 @@ macro_rules! make_mir_visitor {
                             location
                         )
                     }
+                    StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{
+                      ref $($mutability)? src,
+                      ref $($mutability)? dst,
+                      ref $($mutability)? count,
+                    }) => {
+                      self.visit_operand(src, location);
+                      self.visit_operand(dst, location);
+                      self.visit_operand(count, location)
+                    }
                     StatementKind::Nop => {}
                 }
             }
diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs
index 1a3ba16585d..17c4f3c6494 100644
--- a/compiler/rustc_mir/src/borrow_check/invalidation.rs
+++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs
@@ -92,6 +92,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                     self.consume_operand(location, input);
                 }
             }
+            StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
+                ref src,
+                ref dst,
+                ref count,
+            }) => {
+                self.consume_operand(location, src);
+                self.consume_operand(location, dst);
+                self.consume_operand(location, count);
+            }
             StatementKind::Nop
             | StatementKind::Coverage(..)
             | StatementKind::AscribeUserType(..)
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index dcf3093baaf..5b8bb7257e2 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -626,6 +626,15 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
                     self.consume_operand(location, (input, span), flow_state);
                 }
             }
+
+            StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
+                ..
+            }) => {
+                span_bug!(
+                    span,
+                    "Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
+                )
+            }
             StatementKind::Nop
             | StatementKind::Coverage(..)
             | StatementKind::AscribeUserType(..)
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index f6bbd3b6283..ab7e75bf4f1 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1520,6 +1520,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
+            StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
+                ..
+            }) => span_bug!(
+                stmt.source_info.span,
+                "Unexpected StatementKind::CopyNonOverlapping, should only appear after lowering_intrinsics",
+            ),
             StatementKind::FakeRead(..)
             | StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_mir/src/dataflow/impls/borrows.rs
index b149ffa9667..f24d0f0266d 100644
--- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/borrows.rs
@@ -305,6 +305,7 @@ impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
             | mir::StatementKind::Retag { .. }
             | mir::StatementKind::AscribeUserType(..)
             | mir::StatementKind::Coverage(..)
+            | mir::StatementKind::CopyNonOverlapping(..)
             | mir::StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs b/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs
index 9250cd40847..792664597fd 100644
--- a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs
@@ -149,6 +149,7 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir,
             | StatementKind::FakeRead(..)
             | StatementKind::Nop
             | StatementKind::Retag(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::StorageLive(..) => {}
         }
     }
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index 67c3b043262..1ddd81e779b 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -318,6 +318,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             StatementKind::Retag { .. }
             | StatementKind::AscribeUserType(..)
             | StatementKind::Coverage(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index d36b3a7d9b5..25c3c2c632d 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -323,28 +323,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let result = Scalar::from_uint(truncated_bits, layout.size);
                 self.write_scalar(result, dest)?;
             }
-            sym::copy | sym::copy_nonoverlapping => {
-                let elem_ty = instance.substs.type_at(0);
-                let elem_layout = self.layout_of(elem_ty)?;
-                let count = self.read_scalar(&args[2])?.to_machine_usize(self)?;
-                let elem_align = elem_layout.align.abi;
-
-                let size = elem_layout.size.checked_mul(count, self).ok_or_else(|| {
-                    err_ub_format!("overflow computing total size of `{}`", intrinsic_name)
-                })?;
-                let src = self.read_scalar(&args[0])?.check_init()?;
-                let src = self.memory.check_ptr_access(src, size, elem_align)?;
-                let dest = self.read_scalar(&args[1])?.check_init()?;
-                let dest = self.memory.check_ptr_access(dest, size, elem_align)?;
-
-                if let (Some(src), Some(dest)) = (src, dest) {
-                    self.memory.copy(
-                        src,
-                        dest,
-                        size,
-                        intrinsic_name == sym::copy_nonoverlapping,
-                    )?;
-                }
+            sym::copy => {
+                self.copy(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
             }
             sym::offset => {
                 let ptr = self.read_scalar(&args[0])?.check_init()?;
diff --git a/compiler/rustc_mir/src/interpret/step.rs b/compiler/rustc_mir/src/interpret/step.rs
index c22d91fd82a..0f365eaa41d 100644
--- a/compiler/rustc_mir/src/interpret/step.rs
+++ b/compiler/rustc_mir/src/interpret/step.rs
@@ -2,6 +2,7 @@
 //!
 //! The main entry point is the `step` method.
 
+use crate::interpret::OpTy;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_target::abi::LayoutOf;
@@ -113,6 +114,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 M::retag(self, *kind, &dest)?;
             }
 
+            // Call CopyNonOverlapping
+            CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { dst, src, count }) => {
+                let count = self.eval_operand(count, None)?;
+
+                let src = self.eval_operand(src, None)?;
+                let dst = self.eval_operand(dst, None)?;
+                self.copy(&src, &dst, &count, /* nonoverlapping */ true)?;
+            }
+
             // Statements we do not track.
             AscribeUserType(..) => {}
 
@@ -140,6 +150,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
+    pub(crate) fn copy(
+        &mut self,
+        src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+        dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+        count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+        nonoverlapping: bool,
+    ) -> InterpResult<'tcx> {
+        let count = self.read_scalar(&count)?.to_machine_usize(self)?;
+        let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
+        let (size, align) = (layout.size, layout.align.abi);
+        let src =
+            self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
+
+        let dst =
+            self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
+
+        let size = size.checked_mul(count, self).ok_or_else(|| {
+            err_ub_format!("overflow computing total size of `copy_nonoverlapping`")
+        })?;
+
+        if let (Some(src), Some(dst)) = (src, dst) {
+            self.memory.copy(src, dst, size, nonoverlapping)?;
+        }
+        Ok(())
+    }
+
     /// Evaluate an assignment statement.
     ///
     /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 508510a81e1..bbfcec5a76a 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -25,6 +25,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
 #![feature(option_expect_none)]
+#![feature(option_get_or_default)]
 #![feature(or_patterns)]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index dd3e28acf96..1ad7b8fbbd5 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -808,6 +808,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
             | StatementKind::Retag { .. }
             | StatementKind::AscribeUserType(..)
             | StatementKind::Coverage(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index f0472758dfb..532d201e056 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -123,6 +123,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 UnsafetyViolationKind::General,
                 UnsafetyViolationDetails::UseOfInlineAssembly,
             ),
+            StatementKind::CopyNonOverlapping(..) => unreachable!(),
         }
         self.super_statement(statement, location);
     }
@@ -340,7 +341,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 false
             }
             // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
-            Safety::FnUnsafe if self.tcx.features().unsafe_block_in_unsafe_fn => {
+            Safety::FnUnsafe => {
                 for violation in violations {
                     let mut violation = *violation;
 
@@ -355,8 +356,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 }
                 false
             }
-            // `unsafe` function bodies allow unsafe without additional unsafe blocks (before RFC 2585)
-            Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
+            Safety::BuiltinUnsafe => true,
             Safety::ExplicitUnsafe(hir_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir/src/transform/coverage/graph.rs
index e58b915f126..8ad0d133b17 100644
--- a/compiler/rustc_mir/src/transform/coverage/graph.rs
+++ b/compiler/rustc_mir/src/transform/coverage/graph.rs
@@ -392,10 +392,7 @@ impl BasicCoverageBlockData {
             }
         }
         let operand = counter_kind.as_operand_id();
-        if let Some(replaced) = self
-            .edge_from_bcbs
-            .get_or_insert_with(FxHashMap::default)
-            .insert(from_bcb, counter_kind)
+        if let Some(replaced) = self.edge_from_bcbs.get_or_default().insert(from_bcb, counter_kind)
         {
             Error::from_string(format!(
                 "attempt to set an edge counter more than once; from_bcb: \
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs
index fd3e782f6df..e7097ce8619 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir/src/transform/coverage/spans.rs
@@ -687,6 +687,7 @@ pub(super) fn filtered_statement_span(
 
         // Retain spans from all other statements
         StatementKind::FakeRead(_, _) // Not including `ForGuardBinding`
+        | StatementKind::CopyNonOverlapping(..)
         | StatementKind::Assign(_)
         | StatementKind::SetDiscriminant { .. }
         | StatementKind::LlvmInlineAsm(_)
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index f7568e1d929..6656deac967 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -587,6 +587,7 @@ impl Conflicts<'a> {
             | StatementKind::FakeRead(..)
             | StatementKind::AscribeUserType(..)
             | StatementKind::Coverage(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs
index 7a1f3d44a5e..f299b6ecc28 100644
--- a/compiler/rustc_mir/src/transform/generator.rs
+++ b/compiler/rustc_mir/src/transform/generator.rs
@@ -1454,6 +1454,7 @@ impl Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             | StatementKind::Retag(..)
             | StatementKind::AscribeUserType(..)
             | StatementKind::Coverage(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::Nop => {}
         }
     }
diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir/src/transform/lower_intrinsics.rs
index 177b00b00da..d6a73360616 100644
--- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs
+++ b/compiler/rustc_mir/src/transform/lower_intrinsics.rs
@@ -40,6 +40,27 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             terminator.kind = TerminatorKind::Goto { target };
                         }
                     }
+                    sym::copy_nonoverlapping => {
+                        let target = destination.unwrap().1;
+                        let mut args = args.drain(..);
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::CopyNonOverlapping(
+                                box rustc_middle::mir::CopyNonOverlapping {
+                                    src: args.next().unwrap(),
+                                    dst: args.next().unwrap(),
+                                    count: args.next().unwrap(),
+                                },
+                            ),
+                        });
+                        assert_eq!(
+                            args.next(),
+                            None,
+                            "Extra argument for copy_non_overlapping intrinsic"
+                        );
+                        drop(args);
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
                         if let Some((destination, target)) = *destination {
                             let lhs;
diff --git a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs
index 31e201c3a5b..5347846a4b3 100644
--- a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs
@@ -55,6 +55,7 @@ impl RemoveNoopLandingPads {
                 StatementKind::Assign { .. }
                 | StatementKind::SetDiscriminant { .. }
                 | StatementKind::LlvmInlineAsm { .. }
+                | StatementKind::CopyNonOverlapping(..)
                 | StatementKind::Retag { .. } => {
                     return false;
                 }
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs
index 85f27428bbb..a5764d9bf4e 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir/src/transform/simplify.rs
@@ -428,6 +428,7 @@ impl Visitor<'_> for UsedLocals {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match statement.kind {
             StatementKind::LlvmInlineAsm(..)
+            | StatementKind::CopyNonOverlapping(..)
             | StatementKind::Retag(..)
             | StatementKind::Coverage(..)
             | StatementKind::FakeRead(..)
diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs
index 29b90bff210..d009b0b1b23 100644
--- a/compiler/rustc_mir/src/transform/validate.rs
+++ b/compiler/rustc_mir/src/transform/validate.rs
@@ -294,7 +294,49 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            _ => {}
+            StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
+                ref src,
+                ref dst,
+                ref count,
+            }) => {
+                let src_ty = src.ty(&self.body.local_decls, self.tcx);
+                let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) {
+                    src_deref.ty
+                } else {
+                    self.fail(
+                        location,
+                        format!("Expected src to be ptr in copy_nonoverlapping, got: {}", src_ty),
+                    );
+                    return;
+                };
+                let dst_ty = dst.ty(&self.body.local_decls, self.tcx);
+                let op_dst_ty = if let Some(dst_deref) = dst_ty.builtin_deref(true) {
+                    dst_deref.ty
+                } else {
+                    self.fail(
+                        location,
+                        format!("Expected dst to be ptr in copy_nonoverlapping, got: {}", dst_ty),
+                    );
+                    return;
+                };
+                // since CopyNonOverlapping is parametrized by 1 type,
+                // we only need to check that they are equal and not keep an extra parameter.
+                if op_src_ty != op_dst_ty {
+                    self.fail(location, format!("bad arg ({:?} != {:?})", op_src_ty, op_dst_ty));
+                }
+
+                let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
+                if op_cnt_ty != self.tcx.types.usize {
+                    self.fail(location, format!("bad arg ({:?} != usize)", op_cnt_ty))
+                }
+            }
+            StatementKind::SetDiscriminant { .. }
+            | StatementKind::StorageLive(..)
+            | StatementKind::StorageDead(..)
+            | StatementKind::LlvmInlineAsm(..)
+            | StatementKind::Retag(_, _)
+            | StatementKind::Coverage(_)
+            | StatementKind::Nop => {}
         }
 
         self.super_statement(statement, location);
diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_mir/src/util/spanview.rs
index d3ef8c64565..a9a30e407b4 100644
--- a/compiler/rustc_mir/src/util/spanview.rs
+++ b/compiler/rustc_mir/src/util/spanview.rs
@@ -245,6 +245,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
         Retag(..) => "Retag",
         AscribeUserType(..) => "AscribeUserType",
         Coverage(..) => "Coverage",
+        CopyNonOverlapping(..) => "CopyNonOverlapping",
         Nop => "Nop",
     }
 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 2ee7f53ffa8..e7b3d459766 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -334,7 +334,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 .lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant)
                 .into_iter()
                 .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
-                .filter(|(_, enum_ty_path)| enum_ty_path != "std::prelude::v1")
+                .filter(|(_, enum_ty_path)| !enum_ty_path.starts_with("std::prelude::"))
                 .collect();
             if !enum_candidates.is_empty() {
                 if let (PathSource::Type, Some(span)) =
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index eb191663752..09400a1d130 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -694,6 +694,7 @@ supported_targets! {
     ("i686-unknown-openbsd", i686_unknown_openbsd),
     ("sparc64-unknown-openbsd", sparc64_unknown_openbsd),
     ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
+    ("powerpc-unknown-openbsd", powerpc_unknown_openbsd),
 
     ("aarch64-unknown-netbsd", aarch64_unknown_netbsd),
     ("armv6-unknown-netbsd-eabihf", armv6_unknown_netbsd_eabihf),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
new file mode 100644
index 00000000000..c17183faa7a
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
@@ -0,0 +1,16 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::openbsd_base::opts();
+    base.endian = Endian::Big;
+    base.max_atomic_width = Some(32);
+
+    Target {
+        llvm_target: "powerpc-unknown-openbsd".to_string(),
+        pointer_width: 32,
+        data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
+        arch: "powerpc".to_string(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 39b973ed371..f9f67769e96 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -200,7 +200,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path = self.tcx.def_path_str(variant.def_id);
                         // FIXME #56861: DRYer prelude filtering
-                        Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
+                        if let Some(path) = variant_path.strip_prefix("std::prelude::") {
+                            if let Some((_, path)) = path.split_once("::") {
+                                return Some(path.to_string());
+                            }
+                        }
+                        Some(variant_path)
                     } else {
                         None
                     }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index e702e02d2e4..a70812bd13c 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -133,7 +133,7 @@
 #![feature(trusted_len)]
 #![feature(unboxed_closures)]
 #![feature(unicode_internals)]
-#![feature(unsafe_block_in_unsafe_fn)]
+#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
 #![feature(unsize)]
 #![feature(unsized_fn_params)]
 #![feature(allocator_internals)]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 04926123729..e10e1738de5 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -164,8 +164,8 @@
 #![feature(const_caller_location)]
 #![feature(slice_ptr_get)]
 #![feature(no_niche)] // rust-lang/rust#68303
-#![feature(unsafe_block_in_unsafe_fn)]
 #![feature(int_error_matching)]
+#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 #[prelude_import]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index e3c812a047c..9478e7f06bd 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -854,6 +854,34 @@ impl<T> Option<T> {
     // Entry-like operations to insert if None and return a reference
     /////////////////////////////////////////////////////////////////////////
 
+    /// Inserts the default value into the option if it is [`None`], then
+    /// returns a mutable reference to the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_get_or_default)]
+    ///
+    /// let mut x = None;
+    ///
+    /// {
+    ///     let y: &mut u32 = x.get_or_default();
+    ///     assert_eq!(y, &0);
+    ///
+    ///     *y = 7;
+    /// }
+    ///
+    /// assert_eq!(x, Some(7));
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_get_or_default", issue = "82901")]
+    pub fn get_or_default(&mut self) -> &mut T
+    where
+        T: Default,
+    {
+        self.get_or_insert_with(Default::default)
+    }
+
     /// Inserts `value` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index d6d3111e2ff..b7fcc740363 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -72,7 +72,6 @@
 #![feature(peekable_peek_mut)]
 #![cfg_attr(not(bootstrap), feature(ptr_metadata))]
 #![feature(once_cell)]
-#![feature(unsafe_block_in_unsafe_fn)]
 #![feature(unsized_tuple_coercion)]
 #![feature(int_bits_const)]
 #![feature(nonzero_leading_trailing_zeros)]
@@ -80,8 +79,9 @@
 #![feature(integer_atomics)]
 #![feature(slice_group_by)]
 #![feature(trusted_random_access)]
-#![deny(unsafe_op_in_unsafe_fn)]
+#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
 #![cfg_attr(not(bootstrap), feature(unsize))]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index cebe05c39cb..247d39743be 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -327,7 +327,7 @@
 #![feature(try_blocks)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(unsafe_block_in_unsafe_fn)]
+#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
 #![feature(unsafe_cell_raw_get)]
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 6480e654c55..15ac9e402c5 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -885,7 +885,7 @@ impl Command {
     }
 
     /// Executes a command as a child process, waiting for it to finish and
-    /// collecting its exit status.
+    /// collecting its status.
     ///
     /// By default, stdin, stdout and stderr are inherited from the parent.
     ///
@@ -899,7 +899,7 @@ impl Command {
     ///                      .status()
     ///                      .expect("failed to execute process");
     ///
-    /// println!("process exited with: {}", status);
+    /// println!("process finished with: {}", status);
     ///
     /// assert!(status.success());
     /// ```
@@ -1368,11 +1368,17 @@ impl From<fs::File> for Stdio {
 
 /// Describes the result of a process after it has terminated.
 ///
-/// This `struct` is used to represent the exit status of a child process.
+/// This `struct` is used to represent the exit status or other termination of a child process.
 /// Child processes are created via the [`Command`] struct and their exit
 /// status is exposed through the [`status`] method, or the [`wait`] method
 /// of a [`Child`] process.
 ///
+/// An `ExitStatus` represents every possible disposition of a process.  On Unix this
+/// is the **wait status**.  It is *not* simply an *exit status* (a value passed to `exit`).
+///
+/// For proper error reporting of failed processes, print the value of `ExitStatus` using its
+/// implementation of [`Display`](crate::fmt::Display).
+///
 /// [`status`]: Command::status
 /// [`wait`]: Child::wait
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
@@ -1400,7 +1406,7 @@ impl ExitStatus {
     /// if status.success() {
     ///     println!("'projects/' directory created");
     /// } else {
-    ///     println!("failed to create 'projects/' directory");
+    ///     println!("failed to create 'projects/' directory: {}", status);
     /// }
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
@@ -1410,9 +1416,14 @@ impl ExitStatus {
 
     /// Returns the exit code of the process, if any.
     ///
-    /// On Unix, this will return `None` if the process was terminated
-    /// by a signal; `std::os::unix` provides an extension trait for
-    /// extracting the signal and other details from the `ExitStatus`.
+    /// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the
+    /// process finished by calling `exit`.  Note that on Unix the exit status is truncated to 8
+    /// bits, and that values that didn't come from a program's call to `exit` may be invented the
+    /// runtime system (often, for example, 255, 254, 127 or 126).
+    ///
+    /// On Unix, this will return `None` if the process was terminated by a signal.
+    /// [`ExitStatusExt`](crate::os::unix::process::ExitStatusExt) is an
+    /// extension trait for extracting any such signal, and other details, from the `ExitStatus`.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs
index 88a27f27f66..4e170a8bb1c 100644
--- a/library/std/src/sys/unix/ext/process.rs
+++ b/library/std/src/sys/unix/ext/process.rs
@@ -188,12 +188,20 @@ impl CommandExt for process::Command {
 
 /// Unix-specific extensions to [`process::ExitStatus`].
 ///
+/// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as passed to the
+/// `exit` system call or returned by [`ExitStatus::code()`](crate::process::ExitStatus::code).
+/// It represents **any wait status**, as returned by one of the `wait` family of system calls.
+///
+/// This is because a Unix wait status (a Rust `ExitStatus`) can represent a Unix exit status, but
+/// can also represent other kinds of process event.
+///
 /// This trait is sealed: it cannot be implemented outside the standard library.
 /// This is so that future additional methods are not breaking changes.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt: Sealed {
-    /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
-    /// a process.
+    /// Creates a new `ExitStatus` from the raw underlying integer status value from `wait`
+    ///
+    /// The value should be a **wait status, not an exit status**.
     #[stable(feature = "exit_status_from", since = "1.12.0")]
     fn from_raw(raw: i32) -> Self;
 
@@ -222,6 +230,8 @@ pub trait ExitStatusExt: Sealed {
     fn continued(&self) -> bool;
 
     /// Returns the underlying raw `wait` status.
+    ///
+    /// The returned integer is a **wait status, not an exit status**.
     #[unstable(feature = "unix_process_wait_more", issue = "80695")]
     fn into_raw(self) -> i32;
 }
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 2746f87468d..2fdbabae277 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -527,9 +527,22 @@ impl fmt::Display for ExitStatus {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if let Some(code) = self.code() {
             write!(f, "exit code: {}", code)
+        } else if let Some(signal) = self.signal() {
+            if self.core_dumped() {
+                write!(f, "signal: {} (core dumped)", signal)
+            } else {
+                write!(f, "signal: {}", signal)
+            }
+        } else if let Some(signal) = self.stopped_signal() {
+            write!(f, "stopped (not terminated) by signal: {}", signal)
+        } else if self.continued() {
+            write!(f, "continued (WIFCONTINUED)")
         } else {
-            let signal = self.signal().unwrap();
-            write!(f, "signal: {}", signal)
+            write!(f, "unrecognised wait status: {} {:#x}", self.0, self.0)
         }
     }
 }
+
+#[cfg(test)]
+#[path = "process_unix/tests.rs"]
+mod tests;
diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs
new file mode 100644
index 00000000000..5819d2c2a5a
--- /dev/null
+++ b/library/std/src/sys/unix/process/process_unix/tests.rs
@@ -0,0 +1,30 @@
+#[test]
+fn exitstatus_display_tests() {
+    // In practice this is the same on every Unix.
+    // If some weird platform turns out to be different, and this test fails, use #[cfg].
+    use crate::os::unix::process::ExitStatusExt;
+    use crate::process::ExitStatus;
+
+    let t = |v, s| assert_eq!(s, format!("{}", <ExitStatus as ExitStatusExt>::from_raw(v)));
+
+    t(0x0000f, "signal: 15");
+    t(0x0008b, "signal: 11 (core dumped)");
+    t(0x00000, "exit code: 0");
+    t(0x0ff00, "exit code: 255");
+
+    // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED.  Probably *BSD is similar.
+    //   https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956
+    // The purpose of this test is to test our string formatting, not our understanding of the wait
+    // status magic numbers.  So restrict these to Linux.
+    if cfg!(target_os = "linux") {
+        t(0x0137f, "stopped (not terminated) by signal: 19");
+        t(0x0ffff, "continued (WIFCONTINUED)");
+    }
+
+    // Testing "unrecognised wait status" is hard because the wait.h macros typically
+    // assume that the value came from wait and isn't mad.  With the glibc I have here
+    // this works:
+    if cfg!(all(target_os = "linux", target_env = "gnu")) {
+        t(0x000ff, "unrecognised wait status: 255 0xff");
+    }
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 03ae684e23f..5d836c6bb62 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1076,7 +1076,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
 
         // Avoid depending on rustdoc when we don't need it.
         if mode == "rustdoc"
-            || (mode == "run-make" && suite.ends_with("fulldeps"))
+            || mode == "run-make"
             || (mode == "ui" && is_rustdoc)
             || mode == "js-doc-test"
             || mode == "rustdoc-json"
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 611117788da..ee17fcac45c 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -198,6 +198,7 @@ target | std | host | notes
 `powerpc-unknown-linux-gnuspe` | ✓ |  | PowerPC SPE Linux
 `powerpc-unknown-linux-musl` | ? |  |
 `powerpc-unknown-netbsd` | ✓ | ✓ |
+`powerpc-unknown-openbsd` | ? |  |
 `powerpc-wrs-vxworks` | ? |  |
 `powerpc-wrs-vxworks-spe` | ? |  |
 `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 9084a1713cb..2d0722396fc 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -20,7 +20,7 @@ itertools = "0.9"
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 tracing = "0.1"
-tracing-tree = "0.1.6"
+tracing-tree = "0.1.9"
 
 [dependencies.tracing-subscriber]
 version = "0.2.13"
diff --git a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs
deleted file mode 100644
index 61e512a12a1..00000000000
--- a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-//~^ ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
-//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
-//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr
deleted file mode 100644
index c5cad4a98d9..00000000000
--- a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
-  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
-   |
-LL | #![deny(unsafe_op_in_unsafe_fn)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
-   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
-
-error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
-  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
-   |
-LL | #![deny(unsafe_op_in_unsafe_fn)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
-   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
-
-error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
-  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
-   |
-LL | #![deny(unsafe_op_in_unsafe_fn)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
-   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
index 9eec7e0e8fe..c8400a6fc4d 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
@@ -1,4 +1,3 @@
-#![feature(unsafe_block_in_unsafe_fn)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![deny(unused_unsafe)]
 
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
index 278a036c9f1..3157783acb6 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
@@ -1,18 +1,18 @@
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:10:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:9:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
 note: the lint level is defined here
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:2:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:1:9
    |
 LL | #![deny(unsafe_op_in_unsafe_fn)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:5
    |
 LL |     *PTR;
    |     ^^^^ dereference of raw pointer
@@ -20,7 +20,7 @@ LL |     *PTR;
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:14:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:13:5
    |
 LL |     VOID = ();
    |     ^^^^^^^^^ use of mutable static
@@ -28,25 +28,25 @@ LL |     VOID = ();
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:16:5
    |
 LL |     unsafe {}
    |     ^^^^^^ unnecessary `unsafe` block
    |
 note: the lint level is defined here
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:3:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:2:9
    |
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
 
 error: call to unsafe function is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:25:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
    |
 note: the lint level is defined here
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:23:8
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:22:8
    |
 LL | #[deny(warnings)]
    |        ^^^^^^^^
@@ -54,7 +54,7 @@ LL | #[deny(warnings)]
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5
    |
 LL |     *PTR;
    |     ^^^^ dereference of raw pointer
@@ -62,7 +62,7 @@ LL |     *PTR;
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: use of mutable static is unsafe and requires unsafe block (error E0133)
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:29:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5
    |
 LL |     VOID = ();
    |     ^^^^^^^^^ use of mutable static
@@ -70,13 +70,13 @@ LL |     VOID = ();
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:30:5
    |
 LL |     unsafe {}
    |     ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:45:14
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:44:14
    |
 LL |     unsafe { unsafe { unsf() } }
    |     ------   ^^^^^^ unnecessary `unsafe` block
@@ -84,7 +84,7 @@ LL |     unsafe { unsafe { unsf() } }
    |     because it's nested under this `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:56:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:55:5
    |
 LL | unsafe fn allow_level() {
    | ----------------------- because it's nested under this `unsafe` fn
@@ -93,7 +93,7 @@ LL |     unsafe { unsf() }
    |     ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:68:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:67:9
    |
 LL | unsafe fn nested_allow_level() {
    | ------------------------------ because it's nested under this `unsafe` fn
@@ -102,7 +102,7 @@ LL |         unsafe { unsf() }
    |         ^^^^^^ unnecessary `unsafe` block
 
 error[E0133]: call to unsafe function is unsafe and requires unsafe block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:74:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:73:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
@@ -110,7 +110,7 @@ LL |     unsf();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:77:9
    |
 LL |         unsf();
    |         ^^^^^^ call to unsafe function
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 2cb9588e13f..1391f7505e2 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -210,7 +210,7 @@ fn check_statement(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, statemen
         StatementKind::Assign(box (place, rval)) => {
             check_place(tcx, *place, span, body)?;
             check_rvalue(tcx, body, def_id, rval, span)
-        },
+        }
 
         StatementKind::FakeRead(_, place) |
         // just an assignment
@@ -218,6 +218,13 @@ fn check_statement(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, statemen
 
         StatementKind::LlvmInlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
 
+        StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping{
+          dst, src, count,
+        }) => {
+          check_operand(tcx, dst, span, body)?;
+          check_operand(tcx, src, span, body)?;
+          check_operand(tcx, count, span, body)
+        }
         // These are all NOPs
         StatementKind::StorageLive(_)
         | StatementKind::StorageDead(_)
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 5df3ee8274fdb7cdeb2b0871b4efea8cbf4724a
+Subproject d54e1157b66017e4aae38328cd213286e39ca13