about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-19 12:15:10 +0000
committerbors <bors@rust-lang.org>2022-02-19 12:15:10 +0000
commite08d5693609a659e45025b8ea4dbd9efa342fa68 (patch)
tree582c4ebf10591a5a758a3552b3e4cd7996e73974
parentcb4ee81ef555126e49b3e9f16ca6f12a3264a451 (diff)
parent5a083dbbe6cbb5e7bcab3b21942d162b4628e76f (diff)
downloadrust-e08d5693609a659e45025b8ea4dbd9efa342fa68.tar.gz
rust-e08d5693609a659e45025b8ea4dbd9efa342fa68.zip
Auto merge of #94148 - matthiaskrgr:rollup-jgea68f, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #92902 (Improve the documentation of drain members)
 - #93658 (Stabilize `#[cfg(panic = "...")]`)
 - #93954 (rustdoc-json: buffer output)
 - #93979 (Add debug assertions to validate NUL terminator in c strings)
 - #93990 (pre #89862 cleanup)
 - #94006 (Use a `Field` in `ConstraintCategory::ClosureUpvar`)
 - #94086 (Fix ScalarInt to char conversion)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs22
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs30
-rw-r--r--compiler/rustc_middle/src/mir/query.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs18
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs31
-rw-r--r--compiler/rustc_middle/src/ty/util.rs33
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs40
-rw-r--r--library/alloc/src/collections/binary_heap.rs16
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs20
-rw-r--r--library/alloc/src/string.rs17
-rw-r--r--library/alloc/src/vec/mod.rs19
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/std/src/collections/hash/map.rs4
-rw-r--r--library/std/src/collections/hash/set.rs7
-rw-r--r--library/std/src/ffi/c_str.rs41
-rw-r--r--library/std/src/ffi/c_str/tests.rs8
-rw-r--r--src/doc/unstable-book/src/language-features/cfg-panic.md38
-rw-r--r--src/librustdoc/json/mod.rs9
-rw-r--r--src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff48
-rw-r--r--src/test/mir-opt/const_prop/invalid_constant.rs8
-rw-r--r--src/test/ui/cfg/cfg-panic-abort.rs2
-rw-r--r--src/test/ui/cfg/cfg-panic.rs2
-rw-r--r--src/test/ui/const-generics/defaults/doesnt_infer.rs2
-rw-r--r--src/test/ui/const-generics/defaults/doesnt_infer.stderr2
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/issue-91614.rs2
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-panic.rs11
-rw-r--r--src/test/ui/feature-gates/feature-gate-cfg-panic.stderr21
-rw-r--r--src/test/ui/fmt/format-args-capture.rs1
-rw-r--r--src/test/ui/issues/issue-68696-catch-during-unwind.rs1
34 files changed, 256 insertions, 214 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index ca1e77ff8fd..e6a323d676e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -5,6 +5,7 @@ use rustc_infer::infer::{
     error_reporting::nice_region_error::NiceRegionError,
     error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
 };
+use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{self, RegionVid, Ty};
@@ -421,17 +422,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         diag.span_label(*span, message);
 
-        // FIXME(project-rfc-2229#48): This should store a captured_place not a hir id
-        if let ReturnConstraint::ClosureUpvar(upvar) = kind {
+        if let ReturnConstraint::ClosureUpvar(upvar_field) = kind {
             let def_id = match self.regioncx.universal_regions().defining_ty {
                 DefiningTy::Closure(def_id, _) => def_id,
                 ty => bug!("unexpected DefiningTy {:?}", ty),
             };
 
-            let upvar_def_span = self.infcx.tcx.hir().span(upvar);
-            let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span;
-            diag.span_label(upvar_def_span, "variable defined here");
-            diag.span_label(upvar_span, "variable captured here");
+            let captured_place = &self.upvars[upvar_field.index()].place;
+            let defined_hir = match captured_place.place.base {
+                PlaceBase::Local(hirid) => Some(hirid),
+                PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id),
+                _ => None,
+            };
+
+            if defined_hir.is_some() {
+                let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
+                let upvar_def_span = self.infcx.tcx.hir().span(defined_hir.unwrap());
+                let upvar_span = upvars_map.get(&defined_hir.unwrap()).unwrap().span;
+                diag.span_label(upvar_def_span, "variable defined here");
+                diag.span_label(upvar_span, "variable captured here");
+            }
         }
 
         if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 46924f50d2e..a5824090096 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2530,9 +2530,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             body,
         );
         let category = if let Some(field) = field {
-            let var_hir_id = self.borrowck_context.upvars[field.index()].place.get_root_variable();
-            // FIXME(project-rfc-2229#8): Use Place for better diagnostics
-            ConstraintCategory::ClosureUpvar(var_hir_id)
+            ConstraintCategory::ClosureUpvar(field)
         } else {
             ConstraintCategory::Boring
         };
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 32a9d081ed8..d43f926d0a5 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -70,6 +70,8 @@ declare_features! (
     (accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
     /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
     (accepted, cfg_doctest, "1.40.0", Some(62210), None),
+    /// Enables `#[cfg(panic = "...")]` config key.
+    (accepted, cfg_panic, "1.60.0", Some(77443), None),
     /// Allows `cfg(target_feature = "...")`.
     (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
     /// Allows `cfg(target_vendor = "...")`.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 9cb12778a56..5545abc6024 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -306,8 +306,6 @@ declare_features! (
     (active, c_variadic, "1.34.0", Some(44930), None),
     /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
     (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
-    /// Enables `#[cfg(panic = "...")]` config key.
-    (active, cfg_panic, "1.49.0", Some(77443), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d9a986aba7d..1fb1a38a927 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -34,7 +34,6 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
     (sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
-    (sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index a61100d907b..205ad044554 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -497,16 +497,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let ty_to_string = |ty: Ty<'tcx>| -> String {
             let mut s = String::new();
             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
-            let mut inner = self.inner.borrow_mut();
-            let ty_vars = inner.type_variables();
-            let getter = move |ty_vid| {
-                let var_origin = ty_vars.var_origin(ty_vid);
-                if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
+            let ty_getter = move |ty_vid| {
+                if let TypeVariableOriginKind::TypeParameterDefinition(name, _) =
+                    self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind
+                {
+                    Some(name.to_string())
+                } else {
+                    None
+                }
+            };
+            printer.ty_infer_name_resolver = Some(Box::new(ty_getter));
+            let const_getter = move |ct_vid| {
+                if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = self
+                    .inner
+                    .borrow_mut()
+                    .const_unification_table()
+                    .probe_value(ct_vid)
+                    .origin
+                    .kind
+                {
                     return Some(name.to_string());
+                } else {
+                    None
                 }
-                None
             };
-            printer.name_resolver = Some(Box::new(&getter));
+            printer.const_infer_name_resolver = Some(Box::new(const_getter));
+
             let _ = if let ty::FnDef(..) = ty.kind() {
                 // We don't want the regular output for `fn`s because it includes its path in
                 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 5c616425957..fbd5a2d08a5 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -341,7 +341,7 @@ pub enum ConstraintCategory {
     /// like `Foo { field: my_val }`)
     Usage,
     OpaqueType,
-    ClosureUpvar(hir::HirId),
+    ClosureUpvar(Field),
 
     /// A constraint from a user-written predicate
     /// with the provided span, written on the item
@@ -363,7 +363,7 @@ pub enum ConstraintCategory {
 #[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ReturnConstraint {
     Normal,
-    ClosureUpvar(hir::HirId),
+    ClosureUpvar(Field),
 }
 
 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index de45e1bb851..ca1db2fd551 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -294,12 +294,22 @@ impl From<char> for ScalarInt {
     }
 }
 
+/// Error returned when a conversion from ScalarInt to char fails.
+#[derive(Debug)]
+pub struct CharTryFromScalarInt;
+
 impl TryFrom<ScalarInt> for char {
-    type Error = Size;
+    type Error = CharTryFromScalarInt;
+
     #[inline]
-    fn try_from(int: ScalarInt) -> Result<Self, Size> {
-        int.to_bits(Size::from_bytes(std::mem::size_of::<char>()))
-            .map(|u| char::from_u32(u.try_into().unwrap()).unwrap())
+    fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
+        let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else  {
+            return Err(CharTryFromScalarInt);
+        };
+        match char::from_u32(bits.try_into().unwrap()) {
+            Some(c) => Ok(c),
+            None => Err(CharTryFromScalarInt),
+        }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index ae838a46157..bf7370c9e0e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -606,7 +606,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Infer(infer_ty) => {
                 let verbose = self.tcx().sess.verbose();
                 if let ty::TyVar(ty_vid) = infer_ty {
-                    if let Some(name) = self.infer_ty_name(ty_vid) {
+                    if let Some(name) = self.ty_infer_name(ty_vid) {
                         p!(write("{}", name))
                     } else {
                         if verbose {
@@ -1015,7 +1015,11 @@ pub trait PrettyPrinter<'tcx>:
         }
     }
 
-    fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
+    fn ty_infer_name(&self, _: ty::TyVid) -> Option<String> {
+        None
+    }
+
+    fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option<String> {
         None
     }
 
@@ -1203,7 +1207,14 @@ pub trait PrettyPrinter<'tcx>:
                     }
                 }
             }
-            ty::ConstKind::Infer(..) => print_underscore!(),
+            ty::ConstKind::Infer(infer_ct) => {
+                match infer_ct {
+                    ty::InferConst::Var(ct_vid)
+                        if let Some(name) = self.const_infer_name(ct_vid) =>
+                            p!(write("{}", name)),
+                    _ => print_underscore!(),
+                }
+            }
             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
             ty::ConstKind::Value(value) => {
                 return self.pretty_print_const_value(value, ct.ty(), print_ty);
@@ -1559,7 +1570,8 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
 
     pub region_highlight_mode: RegionHighlightMode<'tcx>,
 
-    pub name_resolver: Option<Box<&'a dyn Fn(ty::TyVid) -> Option<String>>>,
+    pub ty_infer_name_resolver: Option<Box<dyn Fn(ty::TyVid) -> Option<String> + 'a>>,
+    pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid<'tcx>) -> Option<String> + 'a>>,
 }
 
 impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> {
@@ -1588,7 +1600,8 @@ impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> {
             binder_depth: 0,
             printed_type_count: 0,
             region_highlight_mode: RegionHighlightMode::new(tcx),
-            name_resolver: None,
+            ty_infer_name_resolver: None,
+            const_infer_name_resolver: None,
         }))
     }
 }
@@ -1843,8 +1856,12 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
 }
 
 impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
-    fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
-        self.0.name_resolver.as_ref().and_then(|func| func(id))
+    fn ty_infer_name(&self, id: ty::TyVid) -> Option<String> {
+        self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
+    }
+
+    fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<String> {
+        self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
     }
 
     fn print_value_path(
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c2a4cea2b1a..92d9cb2fc1b 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -17,7 +17,7 @@ use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::NodeIdHashingMode;
@@ -146,6 +146,37 @@ impl<'tcx> TyCtxt<'tcx> {
         hasher.finish()
     }
 
+    pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
+        match res {
+            Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => {
+                Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap())
+            }
+            Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
+                Some(self.parent(def_id).unwrap())
+            }
+            // Other `DefKind`s don't have generics and would ICE when calling
+            // `generics_of`.
+            Res::Def(
+                DefKind::Struct
+                | DefKind::Union
+                | DefKind::Enum
+                | DefKind::Trait
+                | DefKind::OpaqueTy
+                | DefKind::TyAlias
+                | DefKind::ForeignTy
+                | DefKind::TraitAlias
+                | DefKind::AssocTy
+                | DefKind::Fn
+                | DefKind::AssocFn
+                | DefKind::AssocConst
+                | DefKind::Impl,
+                def_id,
+            ) => Some(def_id),
+            Res::Err => None,
+            _ => None,
+        }
+    }
+
     pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
         if let ty::Adt(def, substs) = *ty.kind() {
             for field in def.all_fields() {
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index cd7343a3211..39da7c82c4e 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -1,7 +1,6 @@
 use rustc_errors::{Applicability, ErrorReported, StashKey};
 use rustc_hir as hir;
-use rustc_hir::def::CtorOf;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
@@ -9,7 +8,7 @@ use rustc_hir::{HirId, Node};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -198,38 +197,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
             // Try to use the segment resolution if it is valid, otherwise we
             // default to the path resolution.
             let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res);
-            let generics = match res {
-                Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx
-                    .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()),
-                Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => {
-                    tcx.generics_of(tcx.parent(def_id).unwrap())
-                }
-                // Other `DefKind`s don't have generics and would ICE when calling
-                // `generics_of`.
-                Res::Def(
-                    DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Enum
-                    | DefKind::Trait
-                    | DefKind::OpaqueTy
-                    | DefKind::TyAlias
-                    | DefKind::ForeignTy
-                    | DefKind::TraitAlias
-                    | DefKind::AssocTy
-                    | DefKind::Fn
-                    | DefKind::AssocFn
-                    | DefKind::AssocConst
-                    | DefKind::Impl,
-                    def_id,
-                ) => tcx.generics_of(def_id),
-                Res::Err => {
-                    tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err");
-                    return None;
-                }
-                _ => {
-                    // If the user tries to specify generics on a type that does not take them,
-                    // e.g. `usize<T>`, we may hit this branch, in which case we treat it as if
-                    // no arguments have been passed. An error should already have been emitted.
+            let generics = match tcx.res_generics_def_id(res) {
+                Some(def_id) => tcx.generics_of(def_id),
+                None => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(def_id),
                         &format!("unexpected anon const res {:?} in path: {:?}", res, path),
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 56a47001811..e18cd8cd464 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -746,9 +746,12 @@ impl<T: Ord> BinaryHeap<T> {
         self.rebuild_tail(start);
     }
 
-    /// Returns an iterator which retrieves elements in heap order.
-    /// The retrieved elements are removed from the original heap.
-    /// The remaining elements will be removed on drop in heap order.
+    /// Clears the binary heap, returning an iterator over the removed elements
+    /// in heap order. If the iterator is dropped before being fully consumed,
+    /// it drops the remaining elements in heap order.
+    ///
+    /// The returned iterator keeps a mutable borrow on the heap to optimize
+    /// its implementation.
     ///
     /// Note:
     /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
@@ -1158,9 +1161,12 @@ impl<T> BinaryHeap<T> {
         self.len() == 0
     }
 
-    /// Clears the binary heap, returning an iterator over the removed elements.
+    /// Clears the binary heap, returning an iterator over the removed elements
+    /// in arbitrary order. If the iterator is dropped before being fully
+    /// consumed, it drops the remaining elements in arbitrary order.
     ///
-    /// The elements are removed in arbitrary order.
+    /// The returned iterator keeps a mutable borrow on the heap to optimize
+    /// its implementation.
     ///
     /// # Examples
     ///
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 763175fc045..7139a0fb94d 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1215,21 +1215,25 @@ impl<T, A: Allocator> VecDeque<T, A> {
         unsafe { IterMut::new(ring, tail, head, PhantomData) }
     }
 
-    /// Creates a draining iterator that removes the specified range in the
-    /// deque and yields the removed items.
+    /// Removes the specified range from the deque in bulk, returning all
+    /// removed elements as an iterator. If the iterator is dropped before
+    /// being fully consumed, it drops the remaining removed elements.
     ///
-    /// Note 1: The element range is removed even if the iterator is not
-    /// consumed until the end.
+    /// The returned iterator keeps a mutable borrow on the queue to optimize
+    /// its implementation.
     ///
-    /// Note 2: It is unspecified how many elements are removed from the deque,
-    /// if the `Drain` value is not dropped, but the borrow it holds expires
-    /// (e.g., due to `mem::forget`).
     ///
     /// # Panics
     ///
     /// Panics if the starting point is greater than the end point or if
     /// the end point is greater than the length of the deque.
     ///
+    /// # Leaking
+    ///
+    /// If the returned iterator goes out of scope without being dropped (due to
+    /// [`mem::forget`], for example), the deque may have lost and leaked
+    /// elements arbitrarily, including elements outside the range.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1240,7 +1244,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(drained, [3]);
     /// assert_eq!(deque, [1, 2]);
     ///
-    /// // A full range clears all contents
+    /// // A full range clears all contents, like `clear()` does
     /// deque.drain(..);
     /// assert!(deque.is_empty());
     /// ```
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 7c0faf0659a..716bb4983a6 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1628,17 +1628,24 @@ impl String {
         self.vec.clear()
     }
 
-    /// Creates a draining iterator that removes the specified range in the `String`
-    /// and yields the removed `chars`.
+    /// Removes the specified range from the string in bulk, returning all
+    /// removed characters as an iterator.
     ///
-    /// Note: The element range is removed even if the iterator is not
-    /// consumed until the end.
+    /// The returned iterator keeps a mutable borrow on the string to optimize
+    /// its implementation.
     ///
     /// # Panics
     ///
     /// Panics if the starting point or end point do not lie on a [`char`]
     /// boundary, or if they're out of bounds.
     ///
+    /// # Leaking
+    ///
+    /// If the returned iterator goes out of scope without being dropped (due to
+    /// [`core::mem::forget`], for example), the string may still contain a copy
+    /// of any drained characters, or may have lost characters arbitrarily,
+    /// including characters outside the range.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1652,7 +1659,7 @@ impl String {
     /// assert_eq!(t, "α is alpha, ");
     /// assert_eq!(s, "β is beta");
     ///
-    /// // A full range clears the string
+    /// // A full range clears the string, like `clear()` does
     /// s.drain(..);
     /// assert_eq!(s, "");
     /// ```
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 3dc3eee4133..c29aa0fec5b 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1799,19 +1799,24 @@ impl<T, A: Allocator> Vec<T, A> {
         self.len += count;
     }
 
-    /// Creates a draining iterator that removes the specified range in the vector
-    /// and yields the removed items.
+    /// Removes the specified range from the vector in bulk, returning all
+    /// removed elements as an iterator. If the iterator is dropped before
+    /// being fully consumed, it drops the remaining removed elements.
     ///
-    /// When the iterator **is** dropped, all elements in the range are removed
-    /// from the vector, even if the iterator was not fully consumed. If the
-    /// iterator **is not** dropped (with [`mem::forget`] for example), it is
-    /// unspecified how many elements are removed.
+    /// The returned iterator keeps a mutable borrow on the vector to optimize
+    /// its implementation.
     ///
     /// # Panics
     ///
     /// Panics if the starting point is greater than the end point or if
     /// the end point is greater than the length of the vector.
     ///
+    /// # Leaking
+    ///
+    /// If the returned iterator goes out of scope without being dropped (due to
+    /// [`mem::forget`], for example), the vector may have lost and leaked
+    /// elements arbitrarily, including elements outside the range.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1820,7 +1825,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// assert_eq!(v, &[1]);
     /// assert_eq!(u, &[2, 3]);
     ///
-    /// // A full range clears the vector
+    /// // A full range clears the vector, like `clear()` does
     /// v.drain(..);
     /// assert_eq!(v, &[]);
     /// ```
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 32f3405243c..06c7be054a0 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -6,7 +6,7 @@
 #![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(cell_update)]
-#![feature(cfg_panic)]
+#![cfg_attr(bootstrap, feature(cfg_panic))]
 #![cfg_attr(bootstrap, feature(cfg_target_has_atomic))]
 #![feature(const_assume)]
 #![feature(const_black_box)]
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index c7e34962abb..53b43455b5a 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -547,6 +547,10 @@ impl<K, V, S> HashMap<K, V, S> {
     /// Clears the map, returning all key-value pairs as an iterator. Keeps the
     /// allocated memory for reuse.
     ///
+    /// If the returned iterator is dropped before being fully consumed, it
+    /// drops the remaining key-value pairs. The returned iterator keeps a
+    /// mutable borrow on the vector to optimize its implementation.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index d1450987e73..200667ae390 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -227,7 +227,12 @@ impl<T, S> HashSet<T, S> {
         self.base.is_empty()
     }
 
-    /// Clears the set, returning all elements in an iterator.
+    /// Clears the set, returning all elements as an iterator. Keeps the
+    /// allocated memory for reuse.
+    ///
+    /// If the returned iterator is dropped before being fully consumed, it
+    /// drops the remaining elements. The returned iterator keeps a mutable
+    /// borrow on the vector to optimize its implementation.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 6e70d5ca02d..1678367290e 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -382,7 +382,7 @@ impl CString {
                 let bytes: Vec<u8> = self.into();
                 match memchr::memchr(0, &bytes) {
                     Some(i) => Err(NulError(i, bytes)),
-                    None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+                    None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }),
                 }
             }
         }
@@ -405,7 +405,7 @@ impl CString {
             // This allows better optimizations if lto enabled.
             match memchr::memchr(0, bytes) {
                 Some(i) => Err(NulError(i, buffer)),
-                None => Ok(unsafe { CString::from_vec_unchecked(buffer) }),
+                None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }),
             }
         }
 
@@ -451,10 +451,15 @@ impl CString {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+    pub unsafe fn from_vec_unchecked(v: Vec<u8>) -> Self {
+        debug_assert!(memchr::memchr(0, &v).is_none());
+        unsafe { Self::_from_vec_unchecked(v) }
+    }
+
+    unsafe fn _from_vec_unchecked(mut v: Vec<u8>) -> Self {
         v.reserve_exact(1);
         v.push(0);
-        CString { inner: v.into_boxed_slice() }
+        Self { inner: v.into_boxed_slice() }
     }
 
     /// Retakes ownership of a `CString` that was transferred to C via
@@ -578,7 +583,7 @@ impl CString {
     pub fn into_string(self) -> Result<String, IntoStringError> {
         String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
             error: e.utf8_error(),
-            inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
+            inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) },
         })
     }
 
@@ -735,6 +740,11 @@ impl CString {
     #[must_use]
     #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
     pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
+        debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len());
+        unsafe { Self::_from_vec_with_nul_unchecked(v) }
+    }
+
+    unsafe fn _from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
         Self { inner: v.into_boxed_slice() }
     }
 
@@ -778,7 +788,7 @@ impl CString {
             Some(nul_pos) if nul_pos + 1 == v.len() => {
                 // SAFETY: We know there is only one nul byte, at the end
                 // of the vec.
-                Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
+                Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) })
             }
             Some(nul_pos) => Err(FromVecWithNulError {
                 error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
@@ -811,7 +821,7 @@ impl ops::Deref for CString {
 
     #[inline]
     fn deref(&self) -> &CStr {
-        unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
+        unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
     }
 }
 
@@ -928,7 +938,7 @@ impl From<Vec<NonZeroU8>> for CString {
             };
             // SAFETY: `v` cannot contain null bytes, given the type-level
             // invariant of `NonZeroU8`.
-            CString::from_vec_unchecked(v)
+            Self::_from_vec_unchecked(v)
         }
     }
 }
@@ -1225,7 +1235,7 @@ impl CStr {
         unsafe {
             let len = sys::strlen(ptr);
             let ptr = ptr as *const u8;
-            CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+            Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
         }
     }
 
@@ -1268,7 +1278,7 @@ impl CStr {
             Some(nul_pos) if nul_pos + 1 == bytes.len() => {
                 // SAFETY: We know there is only one nul byte, at the end
                 // of the byte slice.
-                Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
+                Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) })
             }
             Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
             None => Err(FromBytesWithNulError::not_nul_terminated()),
@@ -1297,12 +1307,19 @@ impl CStr {
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
     #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
+        // We're in a const fn, so this is the best we can do
+        debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
+        unsafe { Self::_from_bytes_with_nul_unchecked(bytes) }
+    }
+
+    #[inline]
+    const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self {
         // SAFETY: Casting to CStr is safe because its internal representation
         // is a [u8] too (safe only inside std).
         // Dereferencing the obtained pointer is safe because it comes from a
         // reference. Making a reference is then safe because its lifetime
         // is bound by the lifetime of the given `bytes`.
-        unsafe { &*(bytes as *const [u8] as *const CStr) }
+        unsafe { &*(bytes as *const [u8] as *const Self) }
     }
 
     /// Returns the inner pointer to this C string.
@@ -1566,7 +1583,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
         // byte, since otherwise we could get an empty string that doesn't end
         // in a null.
         if index.start < bytes.len() {
-            unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
+            unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) }
         } else {
             panic!(
                 "index out of bounds: the len is {} but the index is {}",
diff --git a/library/std/src/ffi/c_str/tests.rs b/library/std/src/ffi/c_str/tests.rs
index 4f7ba9ad437..00ba5460821 100644
--- a/library/std/src/ffi/c_str/tests.rs
+++ b/library/std/src/ffi/c_str/tests.rs
@@ -33,14 +33,6 @@ fn build_with_zero2() {
 }
 
 #[test]
-fn build_with_zero3() {
-    unsafe {
-        let s = CString::from_vec_unchecked(vec![0]);
-        assert_eq!(s.as_bytes(), b"\0");
-    }
-}
-
-#[test]
 fn formatted() {
     let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap();
     assert_eq!(format!("{:?}", s), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#);
diff --git a/src/doc/unstable-book/src/language-features/cfg-panic.md b/src/doc/unstable-book/src/language-features/cfg-panic.md
deleted file mode 100644
index f5b73128ad6..00000000000
--- a/src/doc/unstable-book/src/language-features/cfg-panic.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# `cfg_panic`
-
-The tracking issue for this feature is: [#77443]
-
-[#77443]: https://github.com/rust-lang/rust/issues/77443
-
-------------------------
-
-The `cfg_panic` feature makes it possible to execute different code
-depending on the panic strategy.
-
-Possible values at the moment are `"unwind"` or `"abort"`, although
-it is possible that new panic strategies may be added to Rust in the
-future.
-
-## Examples
-
-```rust
-#![feature(cfg_panic)]
-
-#[cfg(panic = "unwind")]
-fn a() {
-    // ...
-}
-
-#[cfg(not(panic = "unwind"))]
-fn a() {
-    // ...
-}
-
-fn b() {
-    if cfg!(panic = "abort") {
-        // ...
-    } else {
-        // ...
-    }
-}
-```
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index f9e9fe0d3cf..52980e07b8c 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -8,6 +8,7 @@ mod conversions;
 
 use std::cell::RefCell;
 use std::fs::{create_dir_all, File};
+use std::io::{BufWriter, Write};
 use std::path::PathBuf;
 use std::rc::Rc;
 
@@ -213,7 +214,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         let mut index = (*self.index).clone().into_inner();
         index.extend(self.get_trait_items());
         // This needs to be the default HashMap for compatibility with the public interface for
-        // rustdoc-json
+        // rustdoc-json-types
         #[allow(rustc::default_hash_types)]
         let output = types::Crate {
             root: types::Id(String::from("0:0")),
@@ -263,8 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         let mut p = out_dir;
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
         p.set_extension("json");
-        let file = try_err!(File::create(&p), p);
-        serde_json::ser::to_writer(&file, &output).unwrap();
+        let mut file = BufWriter::new(try_err!(File::create(&p), p));
+        serde_json::ser::to_writer(&mut file, &output).unwrap();
+        try_err!(file.flush(), p);
+
         Ok(())
     }
 
diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
index ee6c3b5f36f..1b53318806f 100644
--- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
@@ -5,39 +5,53 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11
       let _1: std::option::Option<()>;     // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12
       let mut _2: std::option::Option<std::option::Option<()>>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
-      scope 1 (inlined f) {                // at $DIR/invalid_constant.rs:16:5: 16:12
-          debug x => _2;                   // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
-          let mut _3: isize;               // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
-          let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
-          scope 2 {
-              debug y => _4;               // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+      let _3: main::Union;                 // in scope 0 at $DIR/invalid_constant.rs:22:9: 22:22
+      scope 1 {
+          debug _invalid_char => _3;       // in scope 1 at $DIR/invalid_constant.rs:22:9: 22:22
+      }
+      scope 2 (inlined f) {                // at $DIR/invalid_constant.rs:16:5: 16:12
+          debug x => _2;                   // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+          let mut _4: isize;               // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+          let _5: std::option::Option<()>; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+          scope 3 {
+              debug y => _5;               // in scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
           }
       }
   
       bb0: {
           discriminant(_2) = 0;            // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
--         _3 = discriminant(_2);           // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
--         switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
-+         _3 = const 0_isize;              // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
-+         switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+-         _4 = discriminant(_2);           // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+-         switchInt(move _4) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
++         _4 = const 0_isize;              // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
++         switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
       }
   
       bb1: {
-          nop;                             // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2
-          return;                          // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2
+-         _3 = const { Union { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
++         _3 = const main::Union { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
+                                           // ty::Const
+                                           // + ty: main::Union
+-                                          // + val: Unevaluated(main::{constant#0}, [main::Union], None)
++                                          // + val: Value(Scalar(0x00110001))
+                                           // mir::Constant
+                                           // + span: $DIR/invalid_constant.rs:22:25: 22:58
+-                                          // + literal: Const { ty: main::Union, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ invalid_constant[726d]::main::{constant#0}), const_param_did: None }, substs: [main::Union], promoted: None }) }
++                                          // + literal: Const { ty: main::Union, val: Value(Scalar(0x00110001)) }
+          nop;                             // scope 0 at $DIR/invalid_constant.rs:15:11: 23:2
+          return;                          // scope 0 at $DIR/invalid_constant.rs:23:2: 23:2
       }
   
       bb2: {
--         _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
--         _1 = _4;                         // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
-+         _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+-         _5 = ((_2 as Some).0: std::option::Option<()>); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+-         _1 = _5;                         // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
++         _5 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
 +                                          // ty::Const
 +                                          // + ty: std::option::Option<()>
 +                                          // + val: Value(Scalar(0x02))
 +                                          // mir::Constant
 +                                          // + span: $DIR/invalid_constant.rs:16:5: 16:12
 +                                          // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
-+         _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
++         _1 = const Scalar(0x02): Option::<()>; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
 +                                          // ty::Const
 +                                          // + ty: std::option::Option<()>
 +                                          // + val: Value(Scalar(0x02))
@@ -48,7 +62,7 @@
       }
   
       bb3: {
-          discriminant(_1) = 0;            // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+          discriminant(_1) = 0;            // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
           goto -> bb1;                     // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21
       }
   }
diff --git a/src/test/mir-opt/const_prop/invalid_constant.rs b/src/test/mir-opt/const_prop/invalid_constant.rs
index 1eb6f37df59..4aca9090019 100644
--- a/src/test/mir-opt/const_prop/invalid_constant.rs
+++ b/src/test/mir-opt/const_prop/invalid_constant.rs
@@ -2,7 +2,7 @@
 // by constant propagation. Regression test for issue #93688.
 //
 // compile-flags: -Copt-level=0 -Zinline-mir
-
+#![feature(inline_const)]
 #[inline(always)]
 pub fn f(x: Option<Option<()>>) -> Option<()> {
     match x {
@@ -14,4 +14,10 @@ pub fn f(x: Option<Option<()>>) -> Option<()> {
 // EMIT_MIR invalid_constant.main.ConstProp.diff
 fn main() {
     f(None);
+
+    union Union {
+        int: u32,
+        chr: char,
+    }
+    let _invalid_char = const { Union { int: 0x110001 } };
 }
diff --git a/src/test/ui/cfg/cfg-panic-abort.rs b/src/test/ui/cfg/cfg-panic-abort.rs
index 9b88eff12ed..3853b598a7a 100644
--- a/src/test/ui/cfg/cfg-panic-abort.rs
+++ b/src/test/ui/cfg/cfg-panic-abort.rs
@@ -1,7 +1,7 @@
 // build-pass
 // compile-flags: -C panic=abort
 // no-prefer-dynamic
-#![feature(cfg_panic)]
+
 
 #[cfg(panic = "unwind")]
 pub fn bad() -> i32 { }
diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs
index d2113e4f5ec..fb3e5059c81 100644
--- a/src/test/ui/cfg/cfg-panic.rs
+++ b/src/test/ui/cfg/cfg-panic.rs
@@ -4,7 +4,7 @@
 // ignore-emscripten no panic_unwind implementation
 // ignore-wasm32     no panic_unwind implementation
 // ignore-wasm64     no panic_unwind implementation
-#![feature(cfg_panic)]
+
 
 #[cfg(panic = "abort")]
 pub fn bad() -> i32 { }
diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.rs b/src/test/ui/const-generics/defaults/doesnt_infer.rs
index cd533b57bc3..9c59e672d8e 100644
--- a/src/test/ui/const-generics/defaults/doesnt_infer.rs
+++ b/src/test/ui/const-generics/defaults/doesnt_infer.rs
@@ -9,5 +9,5 @@ impl<const N: u32> Foo<N> {
 fn main() {
     let foo = Foo::<1>::foo();
     let foo = Foo::foo();
-    //~^ error: type annotations needed for `Foo<{_: u32}>`
+    //~^ error: type annotations needed for `Foo<N>`
 }
diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr
index 1551e81ea75..cccf433e328 100644
--- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr
+++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Foo<{_: u32}>`
+error[E0282]: type annotations needed for `Foo<N>`
   --> $DIR/doesnt_infer.rs:11:15
    |
 LL |     let foo = Foo::foo();
diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
index 413cc153924..b45e2cbc737 100644
--- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
+++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
@@ -4,5 +4,5 @@ use std::simd::Mask;
 
 fn main() {
     let y = Mask::<_, _>::splat(false);
-    //~^ error: type annotations needed for `Mask<_, {_: usize}>`
+    //~^ ERROR: type annotations needed for
 }
diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
index 71a5ff79280..347cd2364b2 100644
--- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
+++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed for `Mask<_, {_: usize}>`
+error[E0283]: type annotations needed for `Mask<_, LANES>`
   --> $DIR/issue-91614.rs:6:13
    |
 LL |     let y = Mask::<_, _>::splat(false);
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs b/src/test/ui/feature-gates/feature-gate-cfg-panic.rs
deleted file mode 100644
index 1508374d942..00000000000
--- a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#[cfg(panic = "unwind")]
-//~^ ERROR `cfg(panic)` is experimental and subject to change
-fn foo() -> bool { true }
-#[cfg(not(panic = "unwind"))]
-//~^ ERROR `cfg(panic)` is experimental and subject to change
-fn foo() -> bool { false }
-
-
-fn main() {
-    assert!(foo());
-}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr
deleted file mode 100644
index ea5cd54fa90..00000000000
--- a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: `cfg(panic)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-panic.rs:1:7
-   |
-LL | #[cfg(panic = "unwind")]
-   |       ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information
-   = help: add `#![feature(cfg_panic)]` to the crate attributes to enable
-
-error[E0658]: `cfg(panic)` is experimental and subject to change
-  --> $DIR/feature-gate-cfg-panic.rs:4:11
-   |
-LL | #[cfg(not(panic = "unwind"))]
-   |           ^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #77443 <https://github.com/rust-lang/rust/issues/77443> for more information
-   = help: add `#![feature(cfg_panic)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs
index d31d2a6c336..560352b5cb9 100644
--- a/src/test/ui/fmt/format-args-capture.rs
+++ b/src/test/ui/fmt/format-args-capture.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(cfg_panic)]
 
 fn main() {
     named_argument_takes_precedence_to_captured();
diff --git a/src/test/ui/issues/issue-68696-catch-during-unwind.rs b/src/test/ui/issues/issue-68696-catch-during-unwind.rs
index f25a78f59cd..2b12a62d0eb 100644
--- a/src/test/ui/issues/issue-68696-catch-during-unwind.rs
+++ b/src/test/ui/issues/issue-68696-catch-during-unwind.rs
@@ -4,7 +4,6 @@
 // entering the catch_unwind.
 //
 // run-pass
-#![feature(cfg_panic)]
 
 use std::panic::catch_unwind;