about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-04-02 02:35:03 +0000
committerbors <bors@rust-lang.org>2022-04-02 02:35:03 +0000
commit79f178b76ea9d5c6182f67413f62dd86b0e38508 (patch)
tree6b246b60668f826a00e2264255f7c2e4237ed837
parentc75909c2340c0f8bdf20079b34025fbf3b952985 (diff)
parent1c82fac3f7ca41937faf8b8ade8e120259255b88 (diff)
downloadrust-79f178b76ea9d5c6182f67413f62dd86b0e38508.tar.gz
rust-79f178b76ea9d5c6182f67413f62dd86b0e38508.zip
Auto merge of #95581 - Dylan-DPC:rollup-2suh5h1, r=Dylan-DPC
Rollup of 8 pull requests

Successful merges:

 - #95354 (Handle rustc_const_stable attribute in library feature collector)
 - #95373 (invalid_value lint: detect invalid initialization of arrays)
 - #95430 (Disable #[thread_local] support on i686-pc-windows-msvc)
 - #95544 (Add error message suggestion for missing noreturn in naked function)
 - #95556 (Implement provenance preserving methods on NonNull)
 - #95557 (Fix `thread_local!` macro to be compatible with `no_implicit_prelude`)
 - #95559 (small type system refactoring)
 - #95560 (convert more `DefId`s to `LocalDefId`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs4
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs10
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs18
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs23
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs29
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs9
-rw-r--r--compiler/rustc_passes/src/lib_features.rs11
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs15
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs8
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs9
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/inherited.rs6
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs4
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs29
-rw-r--r--library/core/src/alloc/layout.rs8
-rw-r--r--library/core/src/char/methods.rs2
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/mem/maybe_uninit.rs4
-rw-r--r--library/core/src/mem/mod.rs4
-rw-r--r--library/core/src/num/int_macros.rs6
-rw-r--r--library/core/src/num/mod.rs2
-rw-r--r--library/core/src/num/nonzero.rs2
-rw-r--r--library/core/src/num/uint_macros.rs6
-rw-r--r--library/core/src/option.rs6
-rw-r--r--library/core/src/ptr/mod.rs4
-rw-r--r--library/core/src/ptr/non_null.rs48
-rw-r--r--library/core/src/result.rs6
-rw-r--r--library/core/src/sync/atomic.rs4
-rw-r--r--library/core/src/time.rs8
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/core/tests/ptr.rs78
-rw-r--r--library/std/src/net/ip.rs46
-rw-r--r--library/std/src/thread/local.rs16
-rw-r--r--src/test/rustdoc/const-display.rs6
-rw-r--r--src/test/ui/asm/naked-functions.stderr25
-rw-r--r--src/test/ui/consts/assert-type-intrinsics.rs2
-rw-r--r--src/test/ui/consts/const-eval/simd/insert_extract.rs2
-rw-r--r--src/test/ui/lint/uninitialized-zeroed.rs8
-rw-r--r--src/test/ui/lint/uninitialized-zeroed.stderr55
-rw-r--r--src/test/ui/macros/issue-95533.rs8
49 files changed, 389 insertions, 192 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 79856867985..c7fa2527eb2 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -49,7 +49,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// At the end of processing, the substitution S (once
     /// canonicalized) then represents the values that you computed
     /// for each of the canonical inputs to your query.
-
     pub fn instantiate_canonical_with_fresh_inference_vars<T>(
         &self,
         span: Span,
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 41995ca509e..86229dbfad7 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -27,15 +27,12 @@ use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
 use super::type_variable::TypeVariableValue;
-use super::unify_key::replace_if_possible;
-use super::unify_key::{ConstVarValue, ConstVariableValue};
-use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use super::{InferCtxt, MiscVariable, TypeTrace};
-
 use crate::traits::{Obligation, PredicateObligations};
-
 use rustc_data_structures::sso::SsoHashMap;
 use rustc_hir::def_id::DefId;
+use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -140,8 +137,8 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
             return Ok(a);
         }
 
-        let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), a);
-        let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), b);
+        let a = self.shallow_resolve(a);
+        let b = self.shallow_resolve(b);
 
         let a_is_expected = relation.a_is_expected();
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 4fcdcb63666..c33c0c996bd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -237,7 +237,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
                 _ => cause.code(),
             }
-            && let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
+            && let (&ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
         {
             // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
             // lifetime as above, but called using a fully-qualified path to the method:
@@ -245,7 +245,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             let mut v = TraitObjectVisitor(FxHashSet::default());
             v.visit_ty(param.param_ty);
             if let Some((ident, self_ty)) =
-                self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0)
+                self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0)
                 && self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
             {
                 override_error_code = Some(ident.name);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index b1a42ee66c9..6d23dc4f471 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -7,7 +7,7 @@ use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::print::RegionHighlightMode;
@@ -51,7 +51,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         {
             let guar = self.emit_associated_type_err(
                 span,
-                self.infcx.tcx.item_name(impl_item_def_id),
+                self.infcx.tcx.item_name(impl_item_def_id.to_def_id()),
                 impl_item_def_id,
                 trait_item_def_id,
             );
@@ -155,7 +155,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         &self,
         span: Span,
         item_name: Symbol,
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     ) -> ErrorGuaranteed {
         let impl_sp = self.tcx().def_span(impl_item_def_id);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index e6c8dc302b6..5dcac7f56cc 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -348,7 +348,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 let mut err = self.report_concrete_failure(*parent, sub, sup);
 
                 let trait_item_span = self.tcx.def_span(trait_item_def_id);
-                let item_name = self.tcx.item_name(impl_item_def_id);
+                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
                 err.span_label(
                     trait_item_span,
                     format!("definition of `{}` from trait", item_name),
@@ -370,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     let where_clause_span = self
                         .tcx
                         .hir()
-                        .get_generics(impl_item_def_id.expect_local())
+                        .get_generics(impl_item_def_id)
                         .unwrap()
                         .where_clause
                         .tail_span_for_suggestion();
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index e9d3b6a8aa1..0a11a81c294 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -30,17 +30,13 @@
 //! solving a set of constraints. In contrast, the type inferencer assigns a value to each type
 //! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
 //! inferencer knows "so far".
-
+use super::InferCtxt;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::infer::unify_key::ToType;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
-
-use rustc_data_structures::fx::FxHashMap;
-
 use std::collections::hash_map::Entry;
 
-use super::unify_key::ToType;
-use super::InferCtxt;
-
 pub struct TypeFreshener<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     ty_freshen_count: u32,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index bd59bf4dea8..2524bd78355 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -70,8 +70,6 @@ mod sub;
 pub mod type_variable;
 mod undo_log;
 
-pub use rustc_middle::infer::unify_key;
-
 #[must_use]
 #[derive(Debug)]
 pub struct InferOk<'tcx, T> {
@@ -425,16 +423,20 @@ pub enum SubregionOrigin<'tcx> {
 
     /// Comparing the signature and requirements of an impl method against
     /// the containing trait.
-    CompareImplMethodObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
+    CompareImplMethodObligation {
+        span: Span,
+        impl_item_def_id: LocalDefId,
+        trait_item_def_id: DefId,
+    },
 
     /// Comparing the signature and requirements of an impl associated type
     /// against the containing trait
-    CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
+    CompareImplTypeObligation { span: Span, impl_item_def_id: LocalDefId, trait_item_def_id: DefId },
 
     /// Checking that the bounds of a trait's associated type hold for a given impl
     CheckAssociatedTypeBounds {
         parent: Box<SubregionOrigin<'tcx>>,
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     },
 }
@@ -558,9 +560,9 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
     }
 }
 
-/// Helper type of a temporary returned by `tcx.infer_ctxt()`.
-/// Necessary because we can't write the following bound:
-/// `F: for<'b, 'tcx> where 'tcx FnOnce(InferCtxt<'b, 'tcx>)`.
+/// A temporary returned by `tcx.infer_ctxt()`. This is necessary
+/// for multiple `InferCtxt` to share the same `in_progress_typeck_results`
+/// without using `Rc` or something similar.
 pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index c8ef08f48b6..25b11e31d57 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -4,7 +4,7 @@ use crate::infer::InferCtxt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{MultiSpan, Span};
 use std::fmt;
@@ -14,7 +14,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_extra_impl_obligation(
         &self,
         error_span: Span,
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
         requirement: &dyn fmt::Display,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
@@ -25,7 +25,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
             let span = self.tcx.sess.source_map().guess_head_span(trait_item_span);
-            let item_name = self.tcx.item_name(impl_item_def_id);
+            let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
             err.span_label(span, format!("definition of `{}` from trait", item_name));
         }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 50a3df21a3b..d43c661dda6 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2548,7 +2548,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
         /// Return `Some` only if we are sure this type does *not*
         /// allow zero initialization.
         fn ty_find_init_error<'tcx>(
-            tcx: TyCtxt<'tcx>,
+            cx: &LateContext<'tcx>,
             ty: Ty<'tcx>,
             init: InitKind,
         ) -> Option<InitError> {
@@ -2575,7 +2575,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                 Adt(adt_def, substs) if !adt_def.is_union() => {
                     // First check if this ADT has a layout attribute (like `NonNull` and friends).
                     use std::ops::Bound;
-                    match tcx.layout_scalar_valid_range(adt_def.did()) {
+                    match cx.tcx.layout_scalar_valid_range(adt_def.did()) {
                         // We exploit here that `layout_scalar_valid_range` will never
                         // return `Bound::Excluded`.  (And we have tests checking that we
                         // handle the attribute correctly.)
@@ -2603,12 +2603,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                             // Proceed recursively, check all fields.
                             let variant = &adt_def.variant(VariantIdx::from_u32(0));
                             variant.fields.iter().find_map(|field| {
-                                ty_find_init_error(tcx, field.ty(tcx, substs), init).map(
+                                ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(
                                     |(mut msg, span)| {
                                         if span.is_none() {
                                             // Point to this field, should be helpful for figuring
                                             // out where the source of the error is.
-                                            let span = tcx.def_span(field.did);
+                                            let span = cx.tcx.def_span(field.did);
                                             write!(
                                                 &mut msg,
                                                 " (in this {} field)",
@@ -2627,7 +2627,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                         // Multi-variant enum.
                         _ => {
                             if init == InitKind::Uninit && is_multi_variant(*adt_def) {
-                                let span = tcx.def_span(adt_def.did());
+                                let span = cx.tcx.def_span(adt_def.did());
                                 Some((
                                     "enums have to be initialized to a variant".to_string(),
                                     Some(span),
@@ -2642,7 +2642,16 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
                 }
                 Tuple(..) => {
                     // Proceed recursively, check all fields.
-                    ty.tuple_fields().iter().find_map(|field| ty_find_init_error(tcx, field, init))
+                    ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
+                }
+                Array(ty, len) => {
+                    if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
+                        // Array length known at array non-empty -- recurse.
+                        ty_find_init_error(cx, *ty, init)
+                    } else {
+                        // Empty array or size unknown.
+                        None
+                    }
                 }
                 // Conservative fallback.
                 _ => None,
@@ -2655,7 +2664,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
             // We are extremely conservative with what we warn about.
             let conjured_ty = cx.typeck_results().expr_ty(expr);
             if let Some((msg, span)) =
-                with_no_trimmed_paths!(ty_find_init_error(cx.tcx, conjured_ty, init))
+                with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
             {
                 cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
                     let mut err = lint.build(&format!(
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index dd303aaada9..f2627885d03 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -1,13 +1,8 @@
-use crate::ty::{self, InferConst, Ty, TyCtxt};
-use rustc_data_structures::snapshot_vec;
-use rustc_data_structures::undo_log::UndoLogs;
-use rustc_data_structures::unify::{
-    self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue,
-};
+use crate::ty::{self, Ty, TyCtxt};
+use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
-
 use std::cmp;
 use std::marker::PhantomData;
 
@@ -165,23 +160,3 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
         })
     }
 }
-
-impl<'tcx> EqUnifyValue for ty::Const<'tcx> {}
-
-pub fn replace_if_possible<'tcx, V, L>(
-    table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>, V, L>>,
-    c: ty::Const<'tcx>,
-) -> ty::Const<'tcx>
-where
-    V: snapshot_vec::VecLike<unify::Delegate<ty::ConstVid<'tcx>>>,
-    L: UndoLogs<snapshot_vec::UndoLog<unify::Delegate<ty::ConstVid<'tcx>>>>,
-{
-    if let ty::ConstKind::Infer(InferConst::Var(vid)) = c.val() {
-        match table.probe_value(vid).val.known() {
-            Some(c) => c,
-            None => c,
-        }
-    } else {
-        c
-    }
-}
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 1f18260d915..7c3d08b26bf 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -276,24 +276,23 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplMethodObligation {
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     },
 
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplTypeObligation {
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     },
 
     /// Checking that the bounds of a trait's associated type hold for a given impl
     CheckAssociatedTypeBounds {
-        impl_item_def_id: DefId,
+        impl_item_def_id: LocalDefId,
         trait_item_def_id: DefId,
     },
 
-    /// Checking that this expression can be assigned where it needs to be
-    // FIXME(eddyb) #11161 is the original Expr required?
+    /// Checking that this expression can be assigned to its target.
     ExprAssignable,
 
     /// Computing common supertype in the arms of a match expression
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 00445690f8f..c414d7c031c 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -29,10 +29,11 @@ impl<'tcx> LibFeatureCollector<'tcx> {
     }
 
     fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
-        let stab_attrs = [sym::stable, sym::unstable, sym::rustc_const_unstable];
+        let stab_attrs =
+            [sym::stable, sym::unstable, sym::rustc_const_stable, sym::rustc_const_unstable];
 
-        // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`,
-        // `#[rustc_const_unstable (..)]`).
+        // Find a stability attribute: one of #[stable(…)], #[unstable(…)],
+        // #[rustc_const_stable(…)], or #[rustc_const_unstable(…)].
         if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
             let meta_kind = attr.meta_kind();
             if let Some(MetaItemKind::List(ref metas)) = meta_kind {
@@ -52,7 +53,9 @@ impl<'tcx> LibFeatureCollector<'tcx> {
                     // This additional check for stability is to make sure we
                     // don't emit additional, irrelevant errors for malformed
                     // attributes.
-                    if *stab_attr != sym::stable || since.is_some() {
+                    let is_unstable =
+                        matches!(*stab_attr, sym::unstable | sym::rustc_const_unstable);
+                    if since.is_some() || is_unstable {
                         return Some((feature, since, attr.span));
                     }
                 }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 00a93ccc9aa..02f6b406059 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,7 +1,7 @@
 //! Checks validity of naked functions.
 
 use rustc_ast::{Attribute, InlineAsmOptions};
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{FnKind, Visitor};
@@ -274,12 +274,25 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
         }
 
         if !asm.options.contains(InlineAsmOptions::NORETURN) {
+            let last_span = asm
+                .operands
+                .last()
+                .map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1)
+                .shrink_to_hi();
+
             struct_span_err!(
                 self.tcx.sess,
                 span,
                 E0787,
                 "asm in naked functions must use `noreturn` option"
             )
+            .span_suggestion(
+                last_span,
+                "consider specifying that the asm block is responsible \
+                for returning from the function",
+                String::from(", options(noreturn)"),
+                Applicability::MachineApplicable,
+            )
             .emit();
         }
     }
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
index 174294895bf..5b30dc1d3da 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
@@ -19,6 +19,8 @@ pub fn target() -> Target {
         .entry(LinkerFlavor::Lld(LldFlavor::Link))
         .or_default()
         .extend(pre_link_args_msvc);
+    // Workaround for #95429
+    base.has_thread_local = false;
 
     Target {
         llvm_target: "i686-pc-windows-msvc".to_string(),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 727847968e5..216aa89dd1f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1913,15 +1913,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 } else if let (
                     Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                    &ObligationCauseCode::BindingObligation(def_id, _),
                 ) =
                     (self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code())
                 {
-                    let generics = self.tcx.generics_of(*def_id);
+                    let generics = self.tcx.generics_of(def_id);
                     if generics.params.iter().any(|p| p.name != kw::SelfUpper)
                         && !snippet.ends_with('>')
                         && !generics.has_impl_trait()
-                        && !self.tcx.fn_trait_kind_from_lang_item(*def_id).is_some()
+                        && !self.tcx.fn_trait_kind_from_lang_item(def_id).is_some()
                     {
                         // FIXME: To avoid spurious suggestions in functions where type arguments
                         // where already supplied, we check the snippet to make sure it doesn't
@@ -2223,6 +2223,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
             "suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}",
             pred, item_def_id, span
         );
+
         let (Some(node), true) = (
             self.tcx.hir().get_if_local(item_def_id),
             Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 58e002b3360..b49a5f6578f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -128,7 +128,7 @@ pub trait InferCtxtExt<'tcx> {
     fn suggest_fully_qualified_path(
         &self,
         err: &mut Diagnostic,
-        def_id: DefId,
+        item_def_id: DefId,
         span: Span,
         trait_ref: DefId,
     );
@@ -1317,16 +1317,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     fn suggest_fully_qualified_path(
         &self,
         err: &mut Diagnostic,
-        def_id: DefId,
+        item_def_id: DefId,
         span: Span,
         trait_ref: DefId,
     ) {
-        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) {
             if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
                 err.note(&format!(
                     "{}s cannot be accessed directly on a `trait`, they can only be \
                         accessed through a specific `impl`",
-                    assoc_item.kind.as_def_kind().descr(def_id)
+                    assoc_item.kind.as_def_kind().descr(item_def_id)
                 ));
                 err.span_suggestion(
                     span,
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index a22c9210a9c..0bd5e018f4a 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -28,7 +28,6 @@ use super::{potentially_plural_count, FnCtxt, Inherited};
 /// - `impl_m_span`: span to use for reporting errors
 /// - `trait_m`: the method in the trait
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
-
 crate fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
@@ -88,7 +87,7 @@ fn compare_predicate_entailment<'tcx>(
         impl_m_span,
         impl_m_hir_id,
         ObligationCauseCode::CompareImplMethodObligation {
-            impl_item_def_id: impl_m.def_id,
+            impl_item_def_id: impl_m.def_id.expect_local(),
             trait_item_def_id: trait_m.def_id,
         },
     );
@@ -231,7 +230,7 @@ fn compare_predicate_entailment<'tcx>(
                 span,
                 impl_m_hir_id,
                 ObligationCauseCode::CompareImplMethodObligation {
-                    impl_item_def_id: impl_m.def_id,
+                    impl_item_def_id: impl_m.def_id.expect_local(),
                     trait_item_def_id: trait_m.def_id,
                 },
             );
@@ -1154,7 +1153,7 @@ fn compare_type_predicate_entailment<'tcx>(
         impl_ty_span,
         impl_ty_hir_id,
         ObligationCauseCode::CompareImplTypeObligation {
-            impl_item_def_id: impl_ty.def_id,
+            impl_item_def_id: impl_ty.def_id.expect_local(),
             trait_item_def_id: trait_ty.def_id,
         },
     );
@@ -1383,7 +1382,7 @@ pub fn check_type_bounds<'tcx>(
             impl_ty_span,
             impl_ty_hir_id,
             ObligationCauseCode::CheckAssociatedTypeBounds {
-                impl_item_def_id: impl_ty.def_id,
+                impl_item_def_id: impl_ty.def_id.expect_local(),
                 trait_item_def_id: trait_ty.def_id,
             },
         );
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
index 6c55f821294..55a5eb966c2 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
@@ -14,7 +14,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt};
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index e7cfa3a7c14..62ca728868b 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -68,9 +68,9 @@ impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
     }
 }
 
-/// Helper type of a temporary returned by `Inherited::build(...)`.
-/// Necessary because we can't write the following bound:
-/// `F: for<'b, 'tcx> where 'tcx FnOnce(Inherited<'b, 'tcx>)`.
+/// A temporary returned by `Inherited::build(...)`. This is necessary
+/// for multiple `InferCtxt` to share the same `in_progress_typeck_results`
+/// without using `Rc` or something similar.
 pub struct InheritedBuilder<'tcx> {
     infcx: infer::InferCtxtBuilder<'tcx>,
     def_id: LocalDefId,
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 3fa873e46ab..bc0fa916556 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -2,9 +2,9 @@ use super::{probe, MethodCallee};
 
 use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
 use crate::check::{callee, FnCtxt};
-use crate::hir::def_id::DefId;
-use crate::hir::GenericArg;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::GenericArg;
 use rustc_infer::infer::{self, InferOk};
 use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index e3782fe5911..6edcc12bcf5 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -15,8 +15,8 @@ use rustc_hir::def::Namespace;
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::middle::stability;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index bd08da9529a..9b1767c7835 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -940,7 +940,7 @@ fn check_associated_item(
                     item.ident(fcx.tcx).span,
                     sig,
                     hir_sig.decl,
-                    item.def_id,
+                    item.def_id.expect_local(),
                     &mut implied_bounds,
                 );
                 check_method_receiver(fcx, hir_sig, item, self_ty);
@@ -1068,7 +1068,7 @@ fn check_type_defn<'tcx, F>(
             }
         }
 
-        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
+        check_where_clauses(fcx, item.span, item.def_id, None);
 
         // No implied bounds in a struct definition.
         FxHashSet::default()
@@ -1096,7 +1096,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
 
     // FIXME: this shouldn't use an `FnCtxt` at all.
     for_item(tcx, item).with_fcx(|fcx| {
-        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
+        check_where_clauses(fcx, item.span, item.def_id, None);
 
         FxHashSet::default()
     });
@@ -1144,7 +1144,7 @@ fn check_item_fn(
     for_id(tcx, def_id, span).with_fcx(|fcx| {
         let sig = tcx.fn_sig(def_id);
         let mut implied_bounds = FxHashSet::default();
-        check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
+        check_fn_or_method(fcx, ident.span, sig, decl, def_id, &mut implied_bounds);
         implied_bounds
     })
 }
@@ -1238,7 +1238,7 @@ fn check_impl<'tcx>(
             }
         }
 
-        check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
+        check_where_clauses(fcx, item.span, item.def_id, None);
 
         fcx.impl_implied_bounds(item.def_id.to_def_id(), item.span)
     });
@@ -1249,7 +1249,7 @@ fn check_impl<'tcx>(
 fn check_where_clauses<'tcx, 'fcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
-    def_id: DefId,
+    def_id: LocalDefId,
     return_ty: Option<(Ty<'tcx>, Span)>,
 ) {
     let tcx = fcx.tcx;
@@ -1317,7 +1317,7 @@ fn check_where_clauses<'tcx, 'fcx>(
     // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
     //
     // First we build the defaulted substitution.
-    let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
+    let substs = InternalSubsts::for_item(tcx, def_id.to_def_id(), |param, _| {
         match param.kind {
             GenericParamDefKind::Lifetime => {
                 // All regions are identity.
@@ -1411,8 +1411,11 @@ fn check_where_clauses<'tcx, 'fcx>(
             // below: there, we are not trying to prove those predicates
             // to be *true* but merely *well-formed*.
             let pred = fcx.normalize_associated_types_in(sp, pred);
-            let cause =
-                traits::ObligationCause::new(sp, fcx.body_id, traits::ItemObligation(def_id));
+            let cause = traits::ObligationCause::new(
+                sp,
+                fcx.body_id,
+                traits::ItemObligation(def_id.to_def_id()),
+            );
             traits::Obligation::new(cause, fcx.param_env, pred)
         });
 
@@ -1445,10 +1448,10 @@ fn check_fn_or_method<'fcx, 'tcx>(
     span: Span,
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
-    def_id: DefId,
+    def_id: LocalDefId,
     implied_bounds: &mut FxHashSet<Ty<'tcx>>,
 ) {
-    let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
 
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
@@ -1462,7 +1465,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
                 span,
                 ty,
                 WellFormedLoc::Param {
-                    function: def_id.expect_local(),
+                    function: def_id,
                     // Note that the `param_idx` of the output type is
                     // one greater than the index of the last input type.
                     param_idx: i.try_into().unwrap(),
@@ -1485,7 +1488,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
             input_ty.into(),
             ty.span,
             ObligationCauseCode::WellFormed(Some(WellFormedLoc::Param {
-                function: def_id.expect_local(),
+                function: def_id,
                 param_idx: i.try_into().unwrap(),
             })),
         );
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 0639d6eed62..db6898c1308 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -56,7 +56,7 @@ impl Layout {
     ///    must not overflow (i.e., the rounded value must be less than
     ///    or equal to `usize::MAX`).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
     #[inline]
     pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
         if !align.is_power_of_two() {
@@ -93,7 +93,7 @@ impl Layout {
     /// This function is unsafe as it does not verify the preconditions from
     /// [`Layout::from_size_align`].
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")]
+    #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
     #[must_use]
     #[inline]
     pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
@@ -103,7 +103,7 @@ impl Layout {
 
     /// The minimum size in bytes for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
     #[must_use]
     #[inline]
     pub const fn size(&self) -> usize {
@@ -112,7 +112,7 @@ impl Layout {
 
     /// The minimum byte alignment for a memory block of this layout.
     #[stable(feature = "alloc_layout", since = "1.28.0")]
-    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
     #[must_use = "this returns the minimum alignment, \
                   without modifying the layout"]
     #[inline]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 7deb3358c95..3195205b1b6 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1092,7 +1092,7 @@ impl char {
     /// ```
     #[must_use]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")]
     #[inline]
     pub const fn is_ascii(&self) -> bool {
         *self as u32 <= 0x7F
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 8ad4317c145..474a632773f 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1638,7 +1638,7 @@ extern "rust-intrinsic" {
     /// let num_trailing = unsafe { cttz_nonzero(x) };
     /// assert_eq!(num_trailing, 3);
     /// ```
-    #[rustc_const_stable(feature = "const_cttz", since = "1.53.0")]
+    #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
     pub fn cttz_nonzero<T: Copy>(x: T) -> T;
 
     /// Reverses the bytes in an integer type `T`.
@@ -1718,7 +1718,7 @@ extern "rust-intrinsic" {
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_div` method. For example,
     /// [`u32::checked_div`]
-    #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")]
+    #[rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")]
     pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
     /// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
@@ -1726,7 +1726,7 @@ extern "rust-intrinsic" {
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_rem` method. For example,
     /// [`u32::checked_rem`]
-    #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")]
+    #[rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")]
     pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 445a7ba6e2d..7dfcc36ce93 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -97,7 +97,6 @@
 // Library features:
 #![feature(const_align_offset)]
 #![feature(const_align_of_val)]
-#![feature(const_alloc_layout)]
 #![feature(const_arguments_as_str)]
 #![feature(const_array_into_iter_constructors)]
 #![feature(const_bigint_helper_methods)]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 9db5a9a2889..58d682fc4c8 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -622,7 +622,7 @@ impl<T> MaybeUninit<T> {
     /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
     /// ```
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")]
     #[inline(always)]
     #[rustc_diagnostic_item = "assume_init"]
     #[track_caller]
@@ -788,7 +788,7 @@ impl<T> MaybeUninit<T> {
     /// }
     /// ```
     #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
-    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")]
+    #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_ref", since = "1.59.0")]
     #[inline(always)]
     pub const unsafe fn assume_init_ref(&self) -> &T {
         // SAFETY: the caller must guarantee that `self` is initialized.
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 8a99bed6a96..005f8749e01 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -299,7 +299,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
-#[rustc_const_stable(feature = "const_size_of", since = "1.24.0")]
+#[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")]
 pub const fn size_of<T>() -> usize {
     intrinsics::size_of::<T>()
@@ -581,7 +581,7 @@ pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
 #[inline]
 #[must_use]
 #[stable(feature = "needs_drop", since = "1.21.0")]
-#[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")]
+#[rustc_const_stable(feature = "const_mem_needs_drop", since = "1.36.0")]
 #[rustc_diagnostic_item = "needs_drop"]
 pub const fn needs_drop<T>() -> bool {
     intrinsics::needs_drop::<T>()
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 3665573ab0f..ec460286d03 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -270,7 +270,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
         /// ```
         #[stable(feature = "reverse_bits", since = "1.37.0")]
-        #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")]
+        #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -603,7 +603,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);")]
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")]
+        #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -656,7 +656,7 @@ macro_rules! int_impl {
         #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")]
         /// ```
         #[stable(feature = "wrapping", since = "1.7.0")]
-        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")]
+        #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f4f1d274d10..8cbece0417b 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -281,7 +281,7 @@ impl u8 {
     /// ```
     #[must_use]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")]
+    #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")]
     #[inline]
     pub const fn is_ascii(&self) -> bool {
         *self & 128 == 0
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index c3652931478..0ffbde33a0d 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -74,7 +74,7 @@ macro_rules! nonzero_integers {
                 /// Returns the value as a primitive type.
                 #[$stability]
                 #[inline]
-                #[rustc_const_stable(feature = "nonzero", since = "1.34.0")]
+                #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
                 pub const fn get(self) -> $Int {
                     self.0
                 }
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 4751faeb936..514ac69f7e0 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -273,7 +273,7 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
         /// ```
         #[stable(feature = "reverse_bits", since = "1.37.0")]
-        #[rustc_const_stable(feature = "const_math", since = "1.37.0")]
+        #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline(always)]
@@ -591,7 +591,7 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);")]
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")]
+        #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
@@ -642,7 +642,7 @@ macro_rules! uint_impl {
         #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")]
         /// ```
         #[stable(feature = "wrapping", since = "1.7.0")]
-        #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")]
+        #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         #[inline]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index acab8de8c70..b5ca9e35dce 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -549,7 +549,7 @@ impl<T> Option<T> {
     #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")]
     pub const fn is_some(&self) -> bool {
         matches!(*self, Some(_))
     }
@@ -592,7 +592,7 @@ impl<T> Option<T> {
                   `.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")]
     pub const fn is_none(&self) -> bool {
         !self.is_some()
     }
@@ -621,7 +621,7 @@ impl<T> Option<T> {
     /// println!("still can print text: {text:?}");
     /// ```
     #[inline]
-    #[rustc_const_stable(feature = "const_option", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn as_ref(&self) -> Option<&T> {
         match *self {
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 68d80022b4c..e2a19c1b581 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -510,7 +510,7 @@ pub const fn null_mut<T>() -> *mut T {
 /// see the [module documentation][crate::ptr] for details.
 #[inline(always)]
 #[must_use]
-#[rustc_const_stable(feature = "strict_provenance", since = "1.61.0")]
+#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 pub const fn invalid<T>(addr: usize) -> *const T {
     // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
@@ -537,7 +537,7 @@ pub const fn invalid<T>(addr: usize) -> *const T {
 /// see the [module documentation][crate::ptr] for details.
 #[inline(always)]
 #[must_use]
-#[rustc_const_stable(feature = "strict_provenance", since = "1.61.0")]
+#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 pub const fn invalid_mut<T>(addr: usize) -> *mut T {
     // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index c1b19895f00..7516d4bba4c 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -4,6 +4,7 @@ use crate::fmt;
 use crate::hash;
 use crate::marker::Unsize;
 use crate::mem::{self, MaybeUninit};
+use crate::num::NonZeroUsize;
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
 use crate::ptr::Unique;
 use crate::slice::{self, SliceIndex};
@@ -253,6 +254,53 @@ impl<T: ?Sized> NonNull<T> {
         (self.cast(), super::metadata(self.as_ptr()))
     }
 
+    /// Gets the "address" portion of the pointer.
+    ///
+    /// This API and its claimed semantics are part of the Strict Provenance experiment,
+    /// see the [module documentation][crate::ptr] for details.
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "strict_provenance", issue = "95228")]
+    pub fn addr(self) -> NonZeroUsize
+    where
+        T: Sized,
+    {
+        // SAFETY: The pointer is guaranteed by the type to be non-null,
+        // meaning that the address will be non-zero.
+        unsafe { NonZeroUsize::new_unchecked(self.pointer.addr()) }
+    }
+
+    /// Creates a new pointer with the given address.
+    ///
+    /// This API and its claimed semantics are part of the Strict Provenance experiment,
+    /// see the [module documentation][crate::ptr] for details.
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "strict_provenance", issue = "95228")]
+    pub fn with_addr(self, addr: NonZeroUsize) -> Self
+    where
+        T: Sized,
+    {
+        // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero.
+        unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) }
+    }
+
+    /// Creates a new pointer by mapping `self`'s address to a new one.
+    ///
+    /// This is a convenience for [`with_addr`][Self::with_addr], see that method for details.
+    ///
+    /// This API and its claimed semantics are part of the Strict Provenance experiment,
+    /// see the [module documentation][crate::ptr] for details.
+    #[must_use]
+    #[inline]
+    #[unstable(feature = "strict_provenance", issue = "95228")]
+    pub fn map_addr(self, f: impl FnOnce(NonZeroUsize) -> NonZeroUsize) -> Self
+    where
+        T: Sized,
+    {
+        self.with_addr(f(self.addr()))
+    }
+
     /// Acquires the underlying `*mut` pointer.
     ///
     /// # Examples
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index afd0c857229..641749be366 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -536,7 +536,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.is_ok(), false);
     /// ```
     #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
-    #[rustc_const_stable(feature = "const_result", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_ok(&self) -> bool {
@@ -580,7 +580,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.is_err(), true);
     /// ```
     #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
-    #[rustc_const_stable(feature = "const_result", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn is_err(&self) -> bool {
@@ -698,7 +698,7 @@ impl<T, E> Result<T, E> {
     /// assert_eq!(x.as_ref(), Err(&"Error"));
     /// ```
     #[inline]
-    #[rustc_const_stable(feature = "const_result", since = "1.48.0")]
+    #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const fn as_ref(&self) -> Result<&T, &E> {
         match *self {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index c11a35ab947..6285d1c1cbb 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2498,7 +2498,7 @@ macro_rules! atomic_int_ptr_sized {
             stable(feature = "atomic_access", since = "1.15.0"),
             stable(feature = "atomic_from", since = "1.23.0"),
             stable(feature = "atomic_nand", since = "1.27.0"),
-            rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"),
+            rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
             stable(feature = "rust1", since = "1.0.0"),
             "isize",
             "",
@@ -2518,7 +2518,7 @@ macro_rules! atomic_int_ptr_sized {
             stable(feature = "atomic_access", since = "1.15.0"),
             stable(feature = "atomic_from", since = "1.23.0"),
             stable(feature = "atomic_nand", since = "1.27.0"),
-            rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"),
+            rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
             stable(feature = "rust1", since = "1.0.0"),
             "usize",
             "",
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index bd72d82b71c..6c97305b1a8 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -333,7 +333,7 @@ impl Duration {
     ///
     /// [`subsec_nanos`]: Duration::subsec_nanos
     #[stable(feature = "duration", since = "1.3.0")]
-    #[rustc_const_stable(feature = "duration", since = "1.32.0")]
+    #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
     #[must_use]
     #[inline]
     pub const fn as_secs(&self) -> u64 {
@@ -356,7 +356,7 @@ impl Duration {
     /// assert_eq!(duration.subsec_millis(), 432);
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
-    #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")]
+    #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
     #[must_use]
     #[inline]
     pub const fn subsec_millis(&self) -> u32 {
@@ -379,7 +379,7 @@ impl Duration {
     /// assert_eq!(duration.subsec_micros(), 234_567);
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
-    #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")]
+    #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
     #[must_use]
     #[inline]
     pub const fn subsec_micros(&self) -> u32 {
@@ -402,7 +402,7 @@ impl Duration {
     /// assert_eq!(duration.subsec_nanos(), 10_000_000);
     /// ```
     #[stable(feature = "duration", since = "1.3.0")]
-    #[rustc_const_stable(feature = "duration", since = "1.32.0")]
+    #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
     #[must_use]
     #[inline]
     pub const fn subsec_nanos(&self) -> u32 {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 5f90a76ab74..3af277a556b 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -13,7 +13,6 @@
 #![feature(const_convert)]
 #![feature(const_heap)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
-#![feature(const_maybe_uninit_assume_init)]
 #![feature(const_maybe_uninit_assume_init_read)]
 #![feature(const_nonnull_new)]
 #![feature(const_num_from_num)]
@@ -87,6 +86,7 @@
 #![feature(int_roundings)]
 #![feature(slice_group_by)]
 #![feature(split_array)]
+#![feature(strict_provenance)]
 #![feature(trusted_random_access)]
 #![feature(unsize)]
 #![feature(unzip_option)]
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 6a39ab79f49..03fe56022b0 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -1,4 +1,5 @@
 use core::cell::RefCell;
+use core::num::NonZeroUsize;
 use core::ptr;
 use core::ptr::*;
 use std::fmt::{Debug, Display};
@@ -691,3 +692,80 @@ fn thin_box() {
         }
     }
 }
+
+#[test]
+fn nonnull_tagged_pointer_with_provenance() {
+    let raw_pointer = Box::into_raw(Box::new(10));
+
+    let mut p = TaggedPointer::new(raw_pointer).unwrap();
+    assert_eq!(p.tag(), 0);
+
+    p.set_tag(1);
+    assert_eq!(p.tag(), 1);
+    assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
+
+    p.set_tag(3);
+    assert_eq!(p.tag(), 3);
+    assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
+
+    unsafe { Box::from_raw(p.pointer().as_ptr()) };
+
+    /// A non-null pointer type which carries several bits of metadata and maintains provenance.
+    #[repr(transparent)]
+    pub struct TaggedPointer<T>(NonNull<T>);
+
+    impl<T> Clone for TaggedPointer<T> {
+        fn clone(&self) -> Self {
+            Self(self.0)
+        }
+    }
+
+    impl<T> Copy for TaggedPointer<T> {}
+
+    impl<T> TaggedPointer<T> {
+        /// The ABI-required minimum alignment of the `P` type.
+        pub const ALIGNMENT: usize = core::mem::align_of::<T>();
+        /// A mask for data-carrying bits of the address.
+        pub const DATA_MASK: usize = !Self::ADDRESS_MASK;
+        /// Number of available bits of storage in the address.
+        pub const NUM_BITS: u32 = Self::ALIGNMENT.trailing_zeros();
+        /// A mask for the non-data-carrying bits of the address.
+        pub const ADDRESS_MASK: usize = usize::MAX << Self::NUM_BITS;
+
+        /// Create a new tagged pointer from a possibly null pointer.
+        pub fn new(pointer: *mut T) -> Option<TaggedPointer<T>> {
+            Some(TaggedPointer(NonNull::new(pointer)?))
+        }
+
+        /// Consume this tagged pointer and produce a raw mutable pointer to the
+        /// memory location.
+        pub fn pointer(self) -> NonNull<T> {
+            // SAFETY: The `addr` guaranteed to have bits set in the Self::ADDRESS_MASK, so the result will be non-null.
+            self.0.map_addr(|addr| unsafe {
+                NonZeroUsize::new_unchecked(addr.get() & Self::ADDRESS_MASK)
+            })
+        }
+
+        /// Consume this tagged pointer and produce the data it carries.
+        pub fn tag(&self) -> usize {
+            self.0.addr().get() & Self::DATA_MASK
+        }
+
+        /// Update the data this tagged pointer carries to a new value.
+        pub fn set_tag(&mut self, data: usize) {
+            assert_eq!(
+                data & Self::ADDRESS_MASK,
+                0,
+                "cannot set more data beyond the lowest NUM_BITS"
+            );
+            let data = data & Self::DATA_MASK;
+
+            // SAFETY: This value will always be non-zero because the upper bits (from
+            // ADDRESS_MASK) will always be non-zero. This a property of the type and its
+            // construction.
+            self.0 = self.0.map_addr(|addr| unsafe {
+                NonZeroUsize::new_unchecked((addr.get() & Self::ADDRESS_MASK) | data)
+            })
+        }
+    }
+}
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 70a7d7a8cab..036f2919976 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -235,7 +235,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     #[must_use]
     #[inline]
@@ -259,7 +259,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     #[must_use]
     #[inline]
@@ -309,7 +309,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     #[must_use]
     #[inline]
@@ -387,7 +387,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     #[must_use]
     #[inline]
@@ -408,7 +408,7 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
     #[must_use]
     #[inline]
@@ -454,7 +454,7 @@ impl Ipv4Addr {
     ///
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -516,7 +516,7 @@ impl Ipv4Addr {
     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
     /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -540,7 +540,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
     #[stable(feature = "ip_shared", since = "1.12.0")]
     #[must_use]
     #[inline]
@@ -562,7 +562,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -593,7 +593,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
     /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -621,7 +621,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
     /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -823,7 +823,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -845,7 +845,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -873,7 +873,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
     /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -901,7 +901,7 @@ impl Ipv4Addr {
     ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
     /// );
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
@@ -928,7 +928,7 @@ impl Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
     /// ```
-    #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
@@ -1216,7 +1216,7 @@ impl Ipv6Addr {
     ///
     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -1278,7 +1278,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
     ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -1315,7 +1315,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -1339,7 +1339,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -1624,7 +1624,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     #[must_use]
     #[inline]
@@ -1693,7 +1693,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
     ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
@@ -1740,7 +1740,7 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
     ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
     /// ```
-    #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
     #[must_use]
     #[inline]
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index ca29261b1c9..587e453ceef 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -193,7 +193,7 @@ macro_rules! __thread_local_inner {
             #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
             {
                 static mut VAL: $t = INIT_EXPR;
-                Some(&VAL)
+                $crate::option::Option::Some(&VAL)
             }
 
             // If the platform has support for `#[thread_local]`, use it.
@@ -209,7 +209,7 @@ macro_rules! __thread_local_inner {
                 // just get going.
                 if !$crate::mem::needs_drop::<$t>() {
                     unsafe {
-                        return Some(&VAL)
+                        return $crate::option::Option::Some(&VAL)
                     }
                 }
 
@@ -223,7 +223,7 @@ macro_rules! __thread_local_inner {
                     let ptr = ptr as *mut $t;
 
                     unsafe {
-                        debug_assert_eq!(STATE, 1);
+                        $crate::debug_assert_eq!(STATE, 1);
                         STATE = 2;
                         $crate::ptr::drop_in_place(ptr);
                     }
@@ -239,14 +239,14 @@ macro_rules! __thread_local_inner {
                                 destroy,
                             );
                             STATE = 1;
-                            Some(&VAL)
+                            $crate::option::Option::Some(&VAL)
                         }
                         // 1 == the destructor is registered and the value
                         //   is valid, so return the pointer.
-                        1 => Some(&VAL),
+                        1 => $crate::option::Option::Some(&VAL),
                         // otherwise the destructor has already run, so we
                         // can't give access.
-                        _ => None,
+                        _ => $crate::option::Option::None,
                     }
                 }
             }
@@ -269,7 +269,7 @@ macro_rules! __thread_local_inner {
                             if let $crate::option::Option::Some(value) = init.take() {
                                 return value;
                             } else if $crate::cfg!(debug_assertions) {
-                                unreachable!("missing initial value");
+                                $crate::unreachable!("missing initial value");
                             }
                         }
                         __init()
@@ -344,7 +344,7 @@ macro_rules! __thread_local_inner {
                             if let $crate::option::Option::Some(value) = init.take() {
                                 return value;
                             } else if $crate::cfg!(debug_assertions) {
-                                unreachable!("missing default value");
+                                $crate::unreachable!("missing default value");
                             }
                         }
                         __init()
diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs
index e3f5d074783..8455dd9ef95 100644
--- a/src/test/rustdoc/const-display.rs
+++ b/src/test/rustdoc/const-display.rs
@@ -64,7 +64,7 @@ impl Foo {
     // @has 'foo/struct.Foo.html' '//*[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "rust1", since = "1.2.0")]
+    #[rustc_const_stable(feature = "const2", since = "1.2.0")]
     pub const fn stable_impl() -> u32 { 42 }
 }
 
@@ -75,12 +75,12 @@ impl Bar {
     // Do not show non-const stabilities that are the same as the enclosing item.
     // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$'
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "rust1", since = "1.2.0")]
+    #[rustc_const_stable(feature = "const2", since = "1.2.0")]
     pub const fn stable_impl() -> u32 { 42 }
 
     // Show const-stability even for unstable functions.
     // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$'
     #[unstable(feature = "foo2", issue = "none")]
-    #[rustc_const_stable(feature = "rust1", since = "1.3.0")]
+    #[rustc_const_stable(feature = "const3", since = "1.3.0")]
     pub const fn const_stable_unstable() -> u32 { 42 }
 }
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
index 5520f815f3e..35dc9cca33b 100644
--- a/src/test/ui/asm/naked-functions.stderr
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -97,6 +97,11 @@ LL | |
 LL | |          sym G,
 LL | |     );
    | |_____^
+   |
+help: consider specifying that the asm block is responsible for returning from the function
+   |
+LL |          sym G, options(noreturn),
+   |               +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
   --> $DIR/naked-functions.rs:53:1
@@ -131,18 +136,33 @@ error[E0787]: asm in naked functions must use `noreturn` option
    |
 LL |     asm!("");
    |     ^^^^^^^^
+   |
+help: consider specifying that the asm block is responsible for returning from the function
+   |
+LL |     asm!("", options(noreturn));
+   |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
   --> $DIR/naked-functions.rs:85:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
+   |
+help: consider specifying that the asm block is responsible for returning from the function
+   |
+LL |     asm!("", options(noreturn));
+   |            +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
   --> $DIR/naked-functions.rs:87:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
+   |
+help: consider specifying that the asm block is responsible for returning from the function
+   |
+LL |     asm!("", options(noreturn));
+   |            +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
   --> $DIR/naked-functions.rs:81:1
@@ -198,6 +218,11 @@ error[E0787]: asm in naked functions must use `noreturn` option
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider specifying that the asm block is responsible for returning from the function
+   |
+LL |     asm!("", options(noreturn), options(readonly, nostack), options(pure));
+   |            +++++++++++++++++++
 
 error[E0787]: asm options unsupported in naked functions: `may_unwind`
   --> $DIR/naked-functions.rs:118:5
diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs
index 31ff6aed03b..38e5c454edf 100644
--- a/src/test/ui/consts/assert-type-intrinsics.rs
+++ b/src/test/ui/consts/assert-type-intrinsics.rs
@@ -1,7 +1,7 @@
 // error-pattern: any use of this value will cause an error
 
 #![feature(never_type)]
-#![feature(const_maybe_uninit_assume_init, const_assert_type2)]
+#![feature(const_assert_type2)]
 #![feature(core_intrinsics)]
 
 use std::intrinsics;
diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs
index a1d6c5e51b4..3472c05d12f 100644
--- a/src/test/ui/consts/const-eval/simd/insert_extract.rs
+++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs
@@ -2,7 +2,7 @@
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 #![feature(staged_api)]
-#![stable(feature = "foo", since = "1.33.7")]
+#![stable(feature = "foo", since = "1.3.37")]
 #![allow(non_camel_case_types)]
 
 #[repr(simd)] struct i8x1(i8);
diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs
index 122933c3c4e..5cd323c01db 100644
--- a/src/test/ui/lint/uninitialized-zeroed.rs
+++ b/src/test/ui/lint/uninitialized-zeroed.rs
@@ -81,6 +81,9 @@ fn main() {
         let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization
         let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
 
+        let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+        let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
         // Things that can be zero, but not uninit.
         let _val: bool = mem::zeroed();
         let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
@@ -94,6 +97,9 @@ fn main() {
         let _val: Fruit = mem::zeroed();
         let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
 
+        let _val: [bool; 2] = mem::zeroed();
+        let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
         // Transmute-from-0
         let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization
         let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization
@@ -110,6 +116,8 @@ fn main() {
         let _val: MaybeUninit<&'static i32> = mem::zeroed();
         let _val: i32 = mem::zeroed();
         let _val: bool = MaybeUninit::zeroed().assume_init();
+        let _val: [bool; 0] = MaybeUninit::uninit().assume_init();
+        let _val: [!; 0] = MaybeUninit::zeroed().assume_init();
         // Some things that happen to work due to rustc implementation details,
         // but are not guaranteed to keep working.
         let _val: i32 = mem::uninitialized();
diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr
index 0af185ef61b..b6a66f0a95a 100644
--- a/src/test/ui/lint/uninitialized-zeroed.stderr
+++ b/src/test/ui/lint/uninitialized-zeroed.stderr
@@ -329,8 +329,30 @@ LL |         let _val: *const dyn Send = mem::uninitialized();
    |
    = note: the vtable of a wide raw pointer must be non-null
 
+error: the type `[fn(); 2]` does not permit zero-initialization
+  --> $DIR/uninitialized-zeroed.rs:84:31
+   |
+LL |         let _val: [fn(); 2] = mem::zeroed();
+   |                               ^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: function pointers must be non-null
+
+error: the type `[fn(); 2]` does not permit being left uninitialized
+  --> $DIR/uninitialized-zeroed.rs:85:31
+   |
+LL |         let _val: [fn(); 2] = mem::uninitialized();
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: function pointers must be non-null
+
 error: the type `bool` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:86:26
+  --> $DIR/uninitialized-zeroed.rs:89:26
    |
 LL |         let _val: bool = mem::uninitialized();
    |                          ^^^^^^^^^^^^^^^^^^^^
@@ -341,7 +363,7 @@ LL |         let _val: bool = mem::uninitialized();
    = note: booleans must be either `true` or `false`
 
 error: the type `Wrap<char>` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:89:32
+  --> $DIR/uninitialized-zeroed.rs:92:32
    |
 LL |         let _val: Wrap<char> = mem::uninitialized();
    |                                ^^^^^^^^^^^^^^^^^^^^
@@ -356,7 +378,7 @@ LL | struct Wrap<T> { wrapped: T }
    |                  ^^^^^^^^^^
 
 error: the type `NonBig` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:92:28
+  --> $DIR/uninitialized-zeroed.rs:95:28
    |
 LL |         let _val: NonBig = mem::uninitialized();
    |                            ^^^^^^^^^^^^^^^^^^^^
@@ -367,7 +389,7 @@ LL |         let _val: NonBig = mem::uninitialized();
    = note: `NonBig` must be initialized inside its custom valid range
 
 error: the type `Fruit` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:95:27
+  --> $DIR/uninitialized-zeroed.rs:98:27
    |
 LL |         let _val: Fruit = mem::uninitialized();
    |                           ^^^^^^^^^^^^^^^^^^^^
@@ -384,8 +406,19 @@ LL | |     Banana,
 LL | | }
    | |_^
 
+error: the type `[bool; 2]` does not permit being left uninitialized
+  --> $DIR/uninitialized-zeroed.rs:101:31
+   |
+LL |         let _val: [bool; 2] = mem::uninitialized();
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: booleans must be either `true` or `false`
+
 error: the type `&i32` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:98:34
+  --> $DIR/uninitialized-zeroed.rs:104:34
    |
 LL |         let _val: &'static i32 = mem::transmute(0usize);
    |                                  ^^^^^^^^^^^^^^^^^^^^^^
@@ -396,7 +429,7 @@ LL |         let _val: &'static i32 = mem::transmute(0usize);
    = note: references must be non-null
 
 error: the type `&[i32]` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:99:36
+  --> $DIR/uninitialized-zeroed.rs:105:36
    |
 LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -407,7 +440,7 @@ LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
    = note: references must be non-null
 
 error: the type `NonZeroU32` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:100:32
+  --> $DIR/uninitialized-zeroed.rs:106:32
    |
 LL |         let _val: NonZeroU32 = mem::transmute(0);
    |                                ^^^^^^^^^^^^^^^^^
@@ -418,7 +451,7 @@ LL |         let _val: NonZeroU32 = mem::transmute(0);
    = note: `std::num::NonZeroU32` must be non-null
 
 error: the type `NonNull<i32>` does not permit zero-initialization
-  --> $DIR/uninitialized-zeroed.rs:103:34
+  --> $DIR/uninitialized-zeroed.rs:109:34
    |
 LL |         let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -429,7 +462,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `NonNull<i32>` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:104:34
+  --> $DIR/uninitialized-zeroed.rs:110:34
    |
 LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -440,7 +473,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    = note: `std::ptr::NonNull<i32>` must be non-null
 
 error: the type `bool` does not permit being left uninitialized
-  --> $DIR/uninitialized-zeroed.rs:105:26
+  --> $DIR/uninitialized-zeroed.rs:111:26
    |
 LL |         let _val: bool = MaybeUninit::uninit().assume_init();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -450,5 +483,5 @@ LL |         let _val: bool = MaybeUninit::uninit().assume_init();
    |
    = note: booleans must be either `true` or `false`
 
-error: aborting due to 36 previous errors
+error: aborting due to 39 previous errors
 
diff --git a/src/test/ui/macros/issue-95533.rs b/src/test/ui/macros/issue-95533.rs
new file mode 100644
index 00000000000..905c14dc5fd
--- /dev/null
+++ b/src/test/ui/macros/issue-95533.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![no_implicit_prelude]
+// the macro should not rely on the prelude being imported
+::std::thread_local! { static P: () = (); }
+::std::thread_local! { static Q: () = const { () }; }
+
+fn main () {}