diff --git a/.gitignore b/.gitignore
index 3f77e6884b90f..0cd6b9f648d0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,53 +5,71 @@
 # created during manual debugging and many people like to clean up instead of
 # having git ignore such leftovers. You can use `.git/info/exclude` to
 # configure your local ignore list.
-# FIXME: This needs cleanup.
-*~
+
+## File system
+.DS_Store
+desktop.ini
+
+## Editor
 *.swp
 *.swo
-.#*
-.DS_Store
+Session.vim
 .cproject
-.hg/
-.hgignore
 .idea
 *.iml
-__pycache__/
-*.py[cod]
-*$py.class
+.vscode
 .project
+.favorites.json
 .settings/
+
+## Tool
 .valgrindrc
-.vscode
-.favorites.json
-/Makefile
-/build/
+.cargo
+# Included because it is part of the test case
+!/src/test/run-make/thumb-none-qemu/example/.cargo
+
+## Configuration
 /config.toml
-/dist/
+/Makefile
+config.mk
+config.stamp
+no_llvm_build
+
+## Build
 /dl/
 /doc/
 /inst/
 /llvm/
 /mingw-build/
-/src/tools/x/target
-# Created by default with `src/ci/docker/run.sh`:
-/obj/
+/build/
+/dist/
 /unicode-downloads
 /target
-# Generated by compiletest for incremental:
+/src/tools/x/target
+# Generated by compiletest for incremental
 /tmp/
+# Created by default with `src/ci/docker/run.sh`
+/obj/
+
+## Temporary files
+*~
+\#*
+\#*\#
+.#*
+
+## Tags
 tags
 tags.*
 TAGS
 TAGS.*
-\#*
-\#*\#
-config.mk
-config.stamp
-Session.vim
-.cargo
-!/src/test/run-make/thumb-none-qemu/example/.cargo
-no_llvm_build
+
+## Python
+__pycache__/
+*.py[cod]
+*$py.class
+
+## Node
 **node_modules
 **package-lock.json
+
 # Before adding new lines, see the comment at the top.
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8a3f76415968e..6d6438920c09b 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -754,7 +754,7 @@ fn validate_generic_param_order(
             GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
             GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
                 let ty = pprust::ty_to_string(ty);
-                let unordered = sess.features_untracked().const_generics;
+                let unordered = sess.features_untracked().unordered_const_ty_params();
                 (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
             }
         };
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index c803c8a83b15c..0679ccabe726c 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -727,16 +727,46 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 }
 
 fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
+    use rustc_errors::Applicability;
+
     if !sess.opts.unstable_features.is_nightly_build() {
+        let lang_features = &sess.features_untracked().declared_lang_features;
         for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) {
-            struct_span_err!(
+            let mut err = struct_span_err!(
                 sess.parse_sess.span_diagnostic,
                 attr.span,
                 E0554,
                 "`#![feature]` may not be used on the {} release channel",
                 option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
-            )
-            .emit();
+            );
+            let mut all_stable = true;
+            for ident in
+                attr.meta_item_list().into_iter().flatten().map(|nested| nested.ident()).flatten()
+            {
+                let name = ident.name;
+                let stable_since = lang_features
+                    .iter()
+                    .flat_map(|&(feature, _, since)| if feature == name { since } else { None })
+                    .next();
+                if let Some(since) = stable_since {
+                    err.help(&format!(
+                        "the feature `{}` has been stable since {} and no longer requires \
+                                  an attribute to enable",
+                        name, since
+                    ));
+                } else {
+                    all_stable = false;
+                }
+            }
+            if all_stable {
+                err.span_suggestion(
+                    attr.span,
+                    "remove the attribute",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
         }
     }
 }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a410826d3fda6..cb0615746012f 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -63,6 +63,10 @@ macro_rules! declare_features {
                     _ => panic!("`{}` was not listed in `declare_features`", feature),
                 }
             }
+
+            pub fn unordered_const_ty_params(&self) -> bool {
+                self.const_generics || self.const_generics_defaults
+            }
         }
     };
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 1051fb8cea279..a70be14546b41 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -296,7 +296,9 @@ impl GenericArg<'_> {
         match self {
             GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
             GenericArg::Type(_) => ast::ParamKindOrd::Type,
-            GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics },
+            GenericArg::Const(_) => {
+                ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
+            }
         }
     }
 }
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 3ced3920cfdfe..4036f4da1a76b 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,4 +1,5 @@
 #![feature(allow_internal_unstable)]
+#![feature(bench_black_box)]
 #![feature(const_fn)]
 #![feature(const_panic)]
 #![feature(extend_one)]
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index d30a8693959f3..c8fdbc30d1591 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -36,7 +36,7 @@ impl GenericParamDefKind {
             GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
             GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
             GenericParamDefKind::Const { .. } => {
-                ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
+                ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() }
             }
         }
     }
diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs
index 93133e9b7f063..60757178bec0b 100644
--- a/compiler/rustc_mir/src/transform/coverage/mod.rs
+++ b/compiler/rustc_mir/src/transform/coverage/mod.rs
@@ -111,7 +111,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         let body_span = hir_body.value.span;
         let source_file = source_map.lookup_source_file(body_span.lo());
         let fn_sig_span = match some_fn_sig.filter(|fn_sig| {
-            Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi()))
+            fn_sig.span.ctxt() == body_span.ctxt()
+                && Lrc::ptr_eq(&source_file, &source_map.lookup_source_file(fn_sig.span.hi()))
         }) {
             Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()),
             None => body_span.shrink_to_lo(),
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs
index 067e1001def88..249f5e835cd78 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir/src/transform/coverage/spans.rs
@@ -240,13 +240,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// to be).
     pub(super) fn generate_coverage_spans(
         mir_body: &'a mir::Body<'tcx>,
-        fn_sig_span: Span,
+        fn_sig_span: Span, // Ensured to be same SourceFile and SyntaxContext as `body_span`
         body_span: Span,
         basic_coverage_blocks: &'a CoverageGraph,
     ) -> Vec<CoverageSpan> {
         let mut coverage_spans = CoverageSpans {
             mir_body,
-            fn_sig_span: fn_sig_source_span(fn_sig_span, body_span),
+            fn_sig_span,
             body_span,
             basic_coverage_blocks,
             sorted_spans_iter: None,
@@ -731,11 +731,6 @@ pub(super) fn filtered_terminator_span(
     }
 }
 
-#[inline]
-fn fn_sig_source_span(fn_sig_span: Span, body_span: Span) -> Span {
-    original_sp(fn_sig_span, body_span).with_ctxt(body_span.ctxt())
-}
-
 #[inline]
 fn function_source_span(span: Span, body_span: Span) -> Span {
     let span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index c63edf365a1aa..70b019e8468e7 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -3,6 +3,7 @@
 // from live codes are live, and everything else is dead.
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -15,7 +16,7 @@ use rustc_middle::middle::privacy;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::lint;
 
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
 
 // Any local node that may call something in its body block should be
 // explored. For example, if it's a live Node::Item that is a
@@ -505,6 +506,13 @@ fn find_live<'tcx>(
     symbol_visitor.live_symbols
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+enum ExtraNote {
+    /// Use this to provide some examples in the diagnostic of potential other purposes for a value
+    /// or field that is dead code
+    OtherPurposeExamples,
+}
+
 struct DeadVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     live_symbols: FxHashSet<hir::HirId>,
@@ -570,14 +578,42 @@ impl DeadVisitor<'tcx> {
         &mut self,
         id: hir::HirId,
         span: rustc_span::Span,
-        name: Symbol,
+        name: Ident,
         participle: &str,
+        extra_note: Option<ExtraNote>,
     ) {
         if !name.as_str().starts_with('_') {
             self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| {
                 let def_id = self.tcx.hir().local_def_id(id);
                 let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
-                lint.build(&format!("{} is never {}: `{}`", descr, participle, name)).emit()
+
+                let prefixed = vec![(name.span, format!("_{}", name))];
+
+                let mut diag =
+                    lint.build(&format!("{} is never {}: `{}`", descr, participle, name));
+
+                diag.multipart_suggestion(
+                    "if this is intentional, prefix it with an underscore",
+                    prefixed,
+                    Applicability::MachineApplicable,
+                );
+
+                let mut note = format!(
+                    "the leading underscore signals that this {} serves some other \
+                    purpose even if it isn't used in a way that we can detect.",
+                    descr,
+                );
+                if matches!(extra_note, Some(ExtraNote::OtherPurposeExamples)) {
+                    note += " (e.g. for its effect when dropped or in foreign code)";
+                }
+
+                diag.note(&note);
+
+                // Force the note we added to the front, before any other subdiagnostics
+                // added in lint.build(...)
+                diag.children.rotate_right(1);
+
+                diag.emit()
             });
         }
     }
@@ -623,7 +659,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 hir::ItemKind::Struct(..) => "constructed", // Issue #52325
                 _ => "used",
             };
-            self.warn_dead_code(item.hir_id(), span, item.ident.name, participle);
+            self.warn_dead_code(item.hir_id(), span, item.ident, participle, None);
         } else {
             // Only continue if we didn't warn
             intravisit::walk_item(self, item);
@@ -637,7 +673,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
         id: hir::HirId,
     ) {
         if self.should_warn_about_variant(&variant) {
-            self.warn_dead_code(variant.id, variant.span, variant.ident.name, "constructed");
+            self.warn_dead_code(variant.id, variant.span, variant.ident, "constructed", None);
         } else {
             intravisit::walk_variant(self, variant, g, id);
         }
@@ -645,14 +681,20 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
 
     fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
         if self.should_warn_about_foreign_item(fi) {
-            self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used");
+            self.warn_dead_code(fi.hir_id(), fi.span, fi.ident, "used", None);
         }
         intravisit::walk_foreign_item(self, fi);
     }
 
     fn visit_field_def(&mut self, field: &'tcx hir::FieldDef<'tcx>) {
         if self.should_warn_about_field(&field) {
-            self.warn_dead_code(field.hir_id, field.span, field.ident.name, "read");
+            self.warn_dead_code(
+                field.hir_id,
+                field.span,
+                field.ident,
+                "read",
+                Some(ExtraNote::OtherPurposeExamples),
+            );
         }
         intravisit::walk_field_def(self, field);
     }
@@ -664,8 +706,9 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                     self.warn_dead_code(
                         impl_item.hir_id(),
                         impl_item.span,
-                        impl_item.ident.name,
+                        impl_item.ident,
                         "used",
+                        None,
                     );
                 }
                 self.visit_nested_body(body_id)
@@ -683,7 +726,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                     } else {
                         impl_item.ident.span
                     };
-                    self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used");
+                    self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident, "used", None);
                 }
                 self.visit_nested_body(body_id)
             }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 87e28f7fcc592..c5f12c0c691b3 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -472,17 +472,6 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
-            ResolutionError::ParamInAnonConstInTyDefault(name) => {
-                let mut err = self.session.struct_span_err(
-                    span,
-                    "constant values inside of type parameter defaults must not depend on generic parameters",
-                );
-                err.span_label(
-                    span,
-                    format!("the anonymous constant must not depend on the parameter `{}`", name),
-                );
-                err
-            }
             ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
                 let mut err = self.session.struct_span_err(
                     span,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9321f11f65933..92f21191de430 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
         // provide previous type parameters as they're built. We
         // put all the parameters on the ban list and then remove
         // them one by one as they are processed and become available.
-        let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
-        let mut found_default = false;
-        default_ban_rib.bindings.extend(generics.params.iter().filter_map(
-            |param| match param.kind {
-                GenericParamKind::Type { default: Some(_), .. }
-                | GenericParamKind::Const { default: Some(_), .. } => {
-                    found_default = true;
-                    Some((Ident::with_dummy_span(param.ident.name), Res::Err))
+        let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        for param in generics.params.iter() {
+            match param.kind {
+                GenericParamKind::Type { .. } => {
+                    forward_ty_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
                 }
-                _ => None,
-            },
-        ));
+                GenericParamKind::Const { .. } => {
+                    forward_const_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+                }
+                GenericParamKind::Lifetime => {}
+            }
+        }
 
         // rust-lang/rust#61631: The type `Self` is essentially
         // another type parameter. For ADTs, we consider it
@@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
         // such as in the case of `trait Add<Rhs = Self>`.)
         if self.diagnostic_metadata.current_self_item.is_some() {
             // (`Some` if + only if we are in ADT's generics.)
-            default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
+            forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
         for param in &generics.params {
@@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                     }
 
                     if let Some(ref ty) = default {
-                        self.ribs[TypeNS].push(default_ban_rib);
-                        self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| {
-                            // HACK: We use an empty `ForwardGenericParamBanRibKind` here which
-                            // is only used to forbid the use of const parameters inside of
-                            // type defaults.
-                            //
-                            // While the rib name doesn't really fit here, it does allow us to use the same
-                            // code for both const and type parameters.
-                            this.visit_ty(ty);
-                        });
-                        default_ban_rib = self.ribs[TypeNS].pop().unwrap();
+                        self.ribs[TypeNS].push(forward_ty_ban_rib);
+                        self.ribs[ValueNS].push(forward_const_ban_rib);
+                        self.visit_ty(ty);
+                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
+                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
                     }
 
                     // Allow all following defaults to refer to this type parameter.
-                    default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
+                    forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
-                GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
-                    // FIXME(const_generics_defaults): handle `default` value here
-                    for bound in &param.bounds {
-                        self.visit_param_bound(bound);
-                    }
+                GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
+                    // Const parameters can't have param bounds.
+                    assert!(param.bounds.is_empty());
+
                     self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
                     self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
                     self.visit_ty(ty);
                     self.ribs[TypeNS].pop().unwrap();
                     self.ribs[ValueNS].pop().unwrap();
+
+                    if let Some(ref expr) = default {
+                        self.ribs[TypeNS].push(forward_ty_ban_rib);
+                        self.ribs[ValueNS].push(forward_const_ban_rib);
+                        self.visit_anon_const(expr);
+                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
+                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
+                    }
+
+                    // Allow all following defaults to refer to this const parameter.
+                    forward_const_ban_rib
+                        .bindings
+                        .remove(&Ident::with_dummy_span(param.ident.name));
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 129954381c9ba..1d1969f7e78ab 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -239,8 +239,6 @@ enum ResolutionError<'a> {
     ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
     ParamInTyOfConstParam(Symbol),
-    /// constant values inside of type parameter defaults must not depend on generic parameters.
-    ParamInAnonConstInTyDefault(Symbol),
     /// generic parameters must not be used inside const evaluations.
     ///
     /// This error is only emitted when using `min_const_generics`.
@@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> {
                 }
             }
             Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
-                let mut in_ty_param_default = false;
                 for rib in ribs {
-                    let has_generic_params = match rib.kind {
+                    let has_generic_params: HasGenericParams = match rib.kind {
                         NormalRibKind
                         | ClosureOrAsyncRibKind
                         | AssocItemRibKind
                         | ModuleRibKind(..)
-                        | MacroDefinition(..) => {
+                        | MacroDefinition(..)
+                        | ForwardGenericParamBanRibKind => {
                             // Nothing to do. Continue.
                             continue;
                         }
 
-                        // We only forbid constant items if we are inside of type defaults,
-                        // for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
-                        ForwardGenericParamBanRibKind => {
-                            // FIXME(const_generic_defaults): we may need to distinguish between
-                            // being in type parameter defaults and const parameter defaults
-                            in_ty_param_default = true;
-                            continue;
-                        }
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> {
                                 }
                             }
 
-                            if in_ty_param_default {
-                                if record_used {
-                                    self.report_error(
-                                        span,
-                                        ResolutionError::ParamInAnonConstInTyDefault(
-                                            rib_ident.name,
-                                        ),
-                                    );
-                                }
-                                return Res::Err;
-                            } else {
-                                continue;
-                            }
+                            continue;
                         }
 
                         // This was an attempt to use a type parameter outside its scope.
@@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> {
                     ribs.next();
                 }
 
-                let mut in_ty_param_default = false;
                 for rib in ribs {
                     let has_generic_params = match rib.kind {
                         NormalRibKind
                         | ClosureOrAsyncRibKind
                         | AssocItemRibKind
                         | ModuleRibKind(..)
-                        | MacroDefinition(..) => continue,
-
-                        // We only forbid constant items if we are inside of type defaults,
-                        // for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
-                        ForwardGenericParamBanRibKind => {
-                            // FIXME(const_generic_defaults): we may need to distinguish between
-                            // being in type parameter defaults and const parameter defaults
-                            in_ty_param_default = true;
-                            continue;
-                        }
+                        | MacroDefinition(..)
+                        | ForwardGenericParamBanRibKind => continue,
+
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> {
                                 return Res::Err;
                             }
 
-                            if in_ty_param_default {
-                                if record_used {
-                                    self.report_error(
-                                        span,
-                                        ResolutionError::ParamInAnonConstInTyDefault(
-                                            rib_ident.name,
-                                        ),
-                                    );
-                                }
-                                return Res::Err;
-                            } else {
-                                continue;
-                            }
+                            continue;
                         }
 
                         ItemRibKind(has_generic_params) => has_generic_params,
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 7a297f2c65f13..2bbb38c294d57 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -286,7 +286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                                         ParamKindOrd::Const {
                                                             unordered: tcx
                                                                 .features()
-                                                                .const_generics,
+                                                                .unordered_const_ty_params(),
                                                         }
                                                     }
                                                 },
@@ -309,7 +309,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                             GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
                                             GenericArg::Type(_) => ParamKindOrd::Type,
                                             GenericArg::Const(_) => ParamKindOrd::Const {
-                                                unordered: tcx.features().const_generics,
+                                                unordered: tcx
+                                                    .features()
+                                                    .unordered_const_ty_params(),
                                             },
                                         }),
                                         Some(&format!(
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index b6de491911ab7..62a1584d16be0 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     GenericParamDefKind::Const { has_default } => {
                         let ty = tcx.at(self.span).type_of(param.def_id);
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .into()
                         } else {
                             if infer_args {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 9ace455042103..a50f8e1c65599 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     GenericParamDefKind::Const { has_default, .. } => {
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .into()
                         } else {
                             self.fcx.var_for_def(self.span, param)
                         }
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 887cc42a1dd27..26871d6f0285c 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -728,20 +728,36 @@ fn check_where_clauses<'tcx, 'fcx>(
     //
     // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
     for param in &generics.params {
-        if let GenericParamDefKind::Type { .. } = param.kind {
-            if is_our_default(&param) {
-                let ty = fcx.tcx.type_of(param.def_id);
-                // Ignore dependent defaults -- that is, where the default of one type
-                // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
-                // be sure if it will error or not as user might always specify the other.
-                if !ty.needs_subst() {
+        match param.kind {
+            GenericParamDefKind::Type { .. } => {
+                if is_our_default(&param) {
+                    let ty = fcx.tcx.type_of(param.def_id);
+                    // Ignore dependent defaults -- that is, where the default of one type
+                    // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
+                    // be sure if it will error or not as user might always specify the other.
+                    if !ty.needs_subst() {
+                        fcx.register_wf_obligation(
+                            ty.into(),
+                            fcx.tcx.def_span(param.def_id),
+                            ObligationCauseCode::MiscObligation,
+                        );
+                    }
+                }
+            }
+            GenericParamDefKind::Const { .. } => {
+                // FIXME(const_generics_defaults): Figure out if this
+                // is the behavior we want, see the comment further below.
+                if is_our_default(&param) {
+                    let default_ct = tcx.const_param_default(param.def_id);
                     fcx.register_wf_obligation(
-                        ty.into(),
+                        default_ct.into(),
                         fcx.tcx.def_span(param.def_id),
                         ObligationCauseCode::MiscObligation,
                     );
                 }
             }
+            // Doesn't have defaults.
+            GenericParamDefKind::Lifetime => {}
         }
     }
 
@@ -774,14 +790,25 @@ fn check_where_clauses<'tcx, 'fcx>(
                 fcx.tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
+                // FIXME(const_generics_defaults): I(@lcnr) feel like always
+                // using the const parameter is the right choice here, even
+                // if it needs substs.
+                //
+                // Before stabilizing this we probably want to get some tests
+                // where this makes a difference and figure out what's the exact
+                // behavior we want here.
+
+                // If the param has a default, ...
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
-                    // Const params currently have to be concrete.
-                    assert!(!default_ct.needs_subst());
-                    default_ct.into()
-                } else {
-                    fcx.tcx.mk_param_from_def(param)
+                    // ... and it's not a dependent default, ...
+                    if !default_ct.needs_subst() {
+                        // ... then substitute it with the default.
+                        return default_ct.into();
+                    }
                 }
+
+                fcx.tcx.mk_param_from_def(param)
             }
         }
     });
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 1477418d5d8cf..927d8c57191a7 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1316,13 +1316,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 }
 
-struct AnonConstInParamListDetector {
-    in_param_list: bool,
-    found_anon_const_in_list: bool,
+struct AnonConstInParamTyDetector {
+    in_param_ty: bool,
+    found_anon_const_in_param_ty: bool,
     ct: HirId,
 }
 
-impl<'v> Visitor<'v> for AnonConstInParamListDetector {
+impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
     type Map = intravisit::ErasedMap<'v>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -1330,15 +1330,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector {
     }
 
     fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
-        let prev = self.in_param_list;
-        self.in_param_list = true;
-        intravisit::walk_generic_param(self, p);
-        self.in_param_list = prev;
+        if let GenericParamKind::Const { ref ty, default: _ } = p.kind {
+            let prev = self.in_param_ty;
+            self.in_param_ty = true;
+            self.visit_ty(ty);
+            self.in_param_ty = prev;
+        }
     }
 
     fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
-        if self.in_param_list && self.ct == c.hir_id {
-            self.found_anon_const_in_list = true;
+        if self.in_param_ty && self.ct == c.hir_id {
+            self.found_anon_const_in_param_ty = true;
         } else {
             intravisit::walk_anon_const(self, c)
         }
@@ -1366,27 +1368,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             let parent_id = tcx.hir().get_parent_item(hir_id);
             let parent_def_id = tcx.hir().local_def_id(parent_id);
 
-            let mut in_param_list = false;
+            let mut in_param_ty = false;
             for (_parent, node) in tcx.hir().parent_iter(hir_id) {
                 if let Some(generics) = node.generics() {
-                    let mut visitor = AnonConstInParamListDetector {
-                        in_param_list: false,
-                        found_anon_const_in_list: false,
+                    let mut visitor = AnonConstInParamTyDetector {
+                        in_param_ty: false,
+                        found_anon_const_in_param_ty: false,
                         ct: hir_id,
                     };
 
                     visitor.visit_generics(generics);
-                    in_param_list = visitor.found_anon_const_in_list;
+                    in_param_ty = visitor.found_anon_const_in_param_ty;
                     break;
                 }
             }
 
-            if in_param_list {
+            if in_param_ty {
                 // We do not allow generic parameters in anon consts if we are inside
-                // of a param list.
-                //
-                // This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
-                // and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
+                // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
                 None
             } else if tcx.lazy_normalization() {
                 // HACK(eddyb) this provides the correct generics when
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index 2792181acc352..9df66263459b1 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -112,7 +112,7 @@ fn write_str_macro_debug(bh: &mut Bencher) {
 #[bench]
 fn write_u128_max(bh: &mut Bencher) {
     bh.iter(|| {
-        std::hint::black_box(format!("{}", u128::MAX));
+        test::black_box(format!("{}", u128::MAX));
     });
 }
 
@@ -120,20 +120,20 @@ fn write_u128_max(bh: &mut Bencher) {
 fn write_u128_min(bh: &mut Bencher) {
     bh.iter(|| {
         let s = format!("{}", 0u128);
-        std::hint::black_box(s);
+        test::black_box(s);
     });
 }
 
 #[bench]
 fn write_u64_max(bh: &mut Bencher) {
     bh.iter(|| {
-        std::hint::black_box(format!("{}", u64::MAX));
+        test::black_box(format!("{}", u64::MAX));
     });
 }
 
 #[bench]
 fn write_u64_min(bh: &mut Bencher) {
     bh.iter(|| {
-        std::hint::black_box(format!("{}", 0u64));
+        test::black_box(format!("{}", 0u64));
     });
 }
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 5b113610a5d3f..a522b7da3bd1c 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -45,8 +45,10 @@ impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
 macro_rules! impl_from {
     ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
         #[$attr]
-        #[doc = $doc]
         impl From<$Small> for $Large {
+            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+            // Rustdocs on functions do not.
+            #[doc = $doc]
             #[inline]
             fn from(small: $Small) -> Self {
                 small as Self
@@ -383,8 +385,10 @@ use crate::num::NonZeroUsize;
 macro_rules! nzint_impl_from {
     ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
         #[$attr]
-        #[doc = $doc]
         impl From<$Small> for $Large {
+            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+            // Rustdocs on functions do not.
+            #[doc = $doc]
             #[inline]
             fn from(small: $Small) -> Self {
                 // SAFETY: input type guarantees the value is non-zero
@@ -450,10 +454,12 @@ nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", si
 macro_rules! nzint_impl_try_from_int {
     ($Int: ty, $NonZeroInt: ty, #[$attr:meta], $doc: expr) => {
         #[$attr]
-        #[doc = $doc]
         impl TryFrom<$Int> for $NonZeroInt {
             type Error = TryFromIntError;
 
+            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+            // Rustdocs on functions do not.
+            #[doc = $doc]
             #[inline]
             fn try_from(value: $Int) -> Result<Self, Self::Error> {
                 Self::new(value).ok_or(TryFromIntError(()))
@@ -489,10 +495,12 @@ nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_fr
 macro_rules! nzint_impl_try_from_nzint {
     ($From:ty => $To:ty, $doc: expr) => {
         #[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
-        #[doc = $doc]
         impl TryFrom<$From> for $To {
             type Error = TryFromIntError;
 
+            // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+            // Rustdocs on functions do not.
+            #[doc = $doc]
             #[inline]
             fn try_from(value: $From) -> Result<Self, Self::Error> {
                 TryFrom::try_from(value.get()).map(|v| {
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 313729581acd9..f7aec73644921 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -154,7 +154,7 @@ pub fn spin_loop() {
 /// [`std::convert::identity`]: crate::convert::identity
 #[cfg_attr(not(miri), inline)]
 #[cfg_attr(miri, inline(never))]
-#[unstable(feature = "test", issue = "50297")]
+#[unstable(feature = "bench_black_box", issue = "64102")]
 #[cfg_attr(miri, allow(unused_mut))]
 pub fn black_box<T>(mut dummy: T) -> T {
     // We need to "use" the argument in some way LLVM can't introspect, and on
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 9efc7a480aeb4..54a47f1323ebf 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -1,5 +1,8 @@
 use crate::cmp;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
+use crate::iter::{
+    adapters::zip::try_get_unchecked, adapters::SourceIter, FusedIterator, InPlaceIterable,
+    TrustedLen, TrustedRandomAccess,
+};
 use crate::ops::{ControlFlow, Try};
 
 /// An iterator that only iterates over the first `n` iterations of `iter`.
@@ -111,6 +114,15 @@ where
 
         self.try_fold(init, ok(fold)).unwrap()
     }
+
+    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <I as Iterator>::Item
+    where
+        Self: TrustedRandomAccess,
+    {
+        // SAFETY: the caller must uphold the contract for
+        // `Iterator::__iterator_get_unchecked`.
+        unsafe { try_get_unchecked(&mut self.iter, idx) }
+    }
 }
 
 #[unstable(issue = "none", feature = "inplace_iteration")]
@@ -207,3 +219,12 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl<I> TrustedRandomAccess for Take<I>
+where
+    I: TrustedRandomAccess,
+{
+    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 089d43483fcb3..0ab9f490fd420 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -233,6 +233,7 @@
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(atomic_mut_ptr)]
+#![feature(bench_black_box)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_accessible)]
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 60be63c9543fa..2f0b32c90d0ee 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -2,9 +2,8 @@
 mod tests;
 
 use crate::fmt;
-use crate::sync::{mutex, MutexGuard, PoisonError};
+use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError};
 use crate::sys_common::condvar as sys;
-use crate::sys_common::poison::{self, LockResult};
 use crate::time::{Duration, Instant};
 
 /// A type indicating whether a timed wait on a condition variable returned
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index b6699910b07cf..ee35598bab5fe 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -166,9 +166,9 @@ pub use self::mutex::{Mutex, MutexGuard};
 #[allow(deprecated)]
 pub use self::once::{Once, OnceState, ONCE_INIT};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
+pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
+pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
 pub mod mpsc;
 
@@ -176,4 +176,5 @@ mod barrier;
 mod condvar;
 mod mutex;
 mod once;
+mod poison;
 mod rwlock;
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index 98c34282e0c49..2615bea659253 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -6,8 +6,8 @@ use crate::fmt;
 use crate::mem;
 use crate::ops::{Deref, DerefMut};
 use crate::ptr;
+use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
 use crate::sys_common::mutex as sys;
-use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 
 /// A mutual exclusion primitive useful for protecting shared data
 ///
diff --git a/library/std/src/sys_common/poison.rs b/library/std/src/sync/poison.rs
similarity index 95%
rename from library/std/src/sys_common/poison.rs
rename to library/std/src/sync/poison.rs
index 1f71187f1b466..05e1833c3e567 100644
--- a/library/std/src/sys_common/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -3,9 +3,6 @@ use crate::fmt;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::thread;
 
-#[allow(unused_imports)] // for intra-doc links
-use crate::sync::{Mutex, RwLock};
-
 pub struct Flag {
     failed: AtomicBool,
 }
@@ -80,6 +77,8 @@ pub struct Guard {
 ///     }
 /// };
 /// ```
+/// [`Mutex`]: crate::sync::Mutex
+/// [`RwLock`]: crate::sync::RwLock
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PoisonError<T> {
     guard: T,
@@ -89,9 +88,11 @@ pub struct PoisonError<T> {
 /// can occur while trying to acquire a lock, from the [`try_lock`] method on a
 /// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`].
 ///
-/// [`try_lock`]: Mutex::try_lock
-/// [`try_read`]: RwLock::try_read
-/// [`try_write`]: RwLock::try_write
+/// [`try_lock`]: crate::sync::Mutex::try_lock
+/// [`try_read`]: crate::sync::RwLock::try_read
+/// [`try_write`]: crate::sync::RwLock::try_write
+/// [`Mutex`]: crate::sync::Mutex
+/// [`RwLock`]: crate::sync::RwLock
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryLockError<T> {
     /// The lock could not be acquired because another thread failed while holding
@@ -149,7 +150,8 @@ impl<T> Error for PoisonError<T> {
 impl<T> PoisonError<T> {
     /// Creates a `PoisonError`.
     ///
-    /// This is generally created by methods like [`Mutex::lock`] or [`RwLock::read`].
+    /// This is generally created by methods like [`Mutex::lock`](crate::sync::Mutex::lock)
+    /// or [`RwLock::read`](crate::sync::RwLock::read).
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn new(guard: T) -> PoisonError<T> {
         PoisonError { guard }
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 351804ec979e1..b01bcec1361d7 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -6,7 +6,7 @@ use crate::fmt;
 use crate::mem;
 use crate::ops::{Deref, DerefMut};
 use crate::ptr;
-use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
+use crate::sync::{poison, LockResult, TryLockError, TryLockResult};
 use crate::sys_common::rwlock as sys;
 
 /// A reader-writer lock
diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs
index a5e453034762c..f9536c4203df2 100644
--- a/library/std/src/sys/sgx/abi/mod.rs
+++ b/library/std/src/sys/sgx/abi/mod.rs
@@ -62,10 +62,12 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn {
     // FIXME: how to support TLS in library mode?
     let tls = Box::new(tls::Tls::new());
-    let _tls_guard = unsafe { tls.activate() };
+    let tls_guard = unsafe { tls.activate() };
 
     if secondary {
-        super::thread::Thread::entry();
+        let join_notifier = super::thread::Thread::entry();
+        drop(tls_guard);
+        drop(join_notifier);
 
         EntryReturn(0, 0)
     } else {
diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs
index 55ef460cc90c5..67e2e8b59d397 100644
--- a/library/std/src/sys/sgx/thread.rs
+++ b/library/std/src/sys/sgx/thread.rs
@@ -9,26 +9,37 @@ pub struct Thread(task_queue::JoinHandle);
 
 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
+pub use self::task_queue::JoinNotifier;
+
 mod task_queue {
-    use crate::sync::mpsc;
+    use super::wait_notify;
     use crate::sync::{Mutex, MutexGuard, Once};
 
-    pub type JoinHandle = mpsc::Receiver<()>;
+    pub type JoinHandle = wait_notify::Waiter;
+
+    pub struct JoinNotifier(Option<wait_notify::Notifier>);
+
+    impl Drop for JoinNotifier {
+        fn drop(&mut self) {
+            self.0.take().unwrap().notify();
+        }
+    }
 
     pub(super) struct Task {
         p: Box<dyn FnOnce()>,
-        done: mpsc::Sender<()>,
+        done: JoinNotifier,
     }
 
     impl Task {
         pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
-            let (done, recv) = mpsc::channel();
+            let (done, recv) = wait_notify::new();
+            let done = JoinNotifier(Some(done));
             (Task { p, done }, recv)
         }
 
-        pub(super) fn run(self) {
+        pub(super) fn run(self) -> JoinNotifier {
             (self.p)();
-            let _ = self.done.send(());
+            self.done
         }
     }
 
@@ -47,6 +58,48 @@ mod task_queue {
     }
 }
 
+/// This module provides a synchronization primitive that does not use thread
+/// local variables. This is needed for signaling that a thread has finished
+/// execution. The signal is sent once all TLS destructors have finished at
+/// which point no new thread locals should be created.
+pub mod wait_notify {
+    use super::super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
+    use crate::sync::Arc;
+
+    pub struct Notifier(Arc<SpinMutex<WaitVariable<bool>>>);
+
+    impl Notifier {
+        /// Notify the waiter. The waiter is either notified right away (if
+        /// currently blocked in `Waiter::wait()`) or later when it calls the
+        /// `Waiter::wait()` method.
+        pub fn notify(self) {
+            let mut guard = self.0.lock();
+            *guard.lock_var_mut() = true;
+            let _ = WaitQueue::notify_one(guard);
+        }
+    }
+
+    pub struct Waiter(Arc<SpinMutex<WaitVariable<bool>>>);
+
+    impl Waiter {
+        /// Wait for a notification. If `Notifier::notify()` has already been
+        /// called, this will return immediately, otherwise the current thread
+        /// is blocked until notified.
+        pub fn wait(self) {
+            let guard = self.0.lock();
+            if *guard.lock_var() {
+                return;
+            }
+            WaitQueue::wait(guard, || {});
+        }
+    }
+
+    pub fn new() -> (Notifier, Waiter) {
+        let inner = Arc::new(SpinMutex::new(WaitVariable::new(false)));
+        (Notifier(inner.clone()), Waiter(inner))
+    }
+}
+
 impl Thread {
     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
     pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
@@ -57,7 +110,7 @@ impl Thread {
         Ok(Thread(handle))
     }
 
-    pub(super) fn entry() {
+    pub(super) fn entry() -> JoinNotifier {
         let mut pending_tasks = task_queue::lock();
         let task = rtunwrap!(Some, pending_tasks.pop());
         drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary
@@ -78,7 +131,7 @@ impl Thread {
     }
 
     pub fn join(self) {
-        let _ = self.0.recv();
+        self.0.wait();
     }
 }
 
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 23a3a0e907dcf..4979bc0b5af77 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -59,7 +59,6 @@ pub mod mutex;
 // when generating documentation.
 #[cfg(any(doc, not(windows)))]
 pub mod os_str_bytes;
-pub mod poison;
 pub mod process;
 pub mod remutex;
 pub mod rwlock;
diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs
index 80e6798d847b1..98f525eafb0f6 100644
--- a/library/std/src/thread/local/tests.rs
+++ b/library/std/src/thread/local/tests.rs
@@ -1,5 +1,6 @@
 use crate::cell::{Cell, UnsafeCell};
-use crate::sync::mpsc::{channel, Sender};
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::mpsc::{self, channel, Sender};
 use crate::thread::{self, LocalKey};
 use crate::thread_local;
 
@@ -207,3 +208,55 @@ fn dtors_in_dtors_in_dtors_const_init() {
     });
     rx.recv().unwrap();
 }
+
+// This test tests that TLS destructors have run before the thread joins. The
+// test has no false positives (meaning: if the test fails, there's actually
+// an ordering problem). It may have false negatives, where the test passes but
+// join is not guaranteed to be after the TLS destructors. However, false
+// negatives should be exceedingly rare due to judicious use of
+// thread::yield_now and running the test several times.
+#[test]
+fn join_orders_after_tls_destructors() {
+    static THREAD2_LAUNCHED: AtomicBool = AtomicBool::new(false);
+
+    for _ in 0..10 {
+        let (tx, rx) = mpsc::sync_channel(0);
+        THREAD2_LAUNCHED.store(false, Ordering::SeqCst);
+
+        let jh = thread::spawn(move || {
+            struct RecvOnDrop(Cell<Option<mpsc::Receiver<()>>>);
+
+            impl Drop for RecvOnDrop {
+                fn drop(&mut self) {
+                    let rx = self.0.take().unwrap();
+                    while !THREAD2_LAUNCHED.load(Ordering::SeqCst) {
+                        thread::yield_now();
+                    }
+                    rx.recv().unwrap();
+                }
+            }
+
+            thread_local! {
+                static TL_RX: RecvOnDrop = RecvOnDrop(Cell::new(None));
+            }
+
+            TL_RX.with(|v| v.0.set(Some(rx)))
+        });
+
+        let tx_clone = tx.clone();
+        let jh2 = thread::spawn(move || {
+            THREAD2_LAUNCHED.store(true, Ordering::SeqCst);
+            jh.join().unwrap();
+            tx_clone.send(()).expect_err(
+                "Expecting channel to be closed because thread 1 TLS destructors must've run",
+            );
+        });
+
+        while !THREAD2_LAUNCHED.load(Ordering::SeqCst) {
+            thread::yield_now();
+        }
+        thread::yield_now();
+        tx.send(()).expect("Expecting channel to be live because thread 2 must block on join");
+        jh2.join().unwrap();
+    }
+}
diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs
index 169154187f250..7869ba2c04178 100644
--- a/library/test/src/bench.rs
+++ b/library/test/src/bench.rs
@@ -1,6 +1,4 @@
 //! Benchmarking module.
-pub use std::hint::black_box;
-
 use super::{
     event::CompletedTest,
     options::BenchMode,
@@ -16,6 +14,15 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::sync::{Arc, Mutex};
 use std::time::{Duration, Instant};
 
+/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
+/// `black_box` could do.
+///
+/// See [`std::hint::black_box`] for details.
+#[inline(always)]
+pub fn black_box<T>(dummy: T) -> T {
+    std::hint::black_box(dummy)
+}
+
 /// Manager of the benchmarking runs.
 ///
 /// This is fed into functions marked with `#[bench]` to allow for
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 2e0864f303cc9..9adc099aaa566 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -24,6 +24,7 @@
 #![feature(rustc_private)]
 #![feature(nll)]
 #![feature(available_concurrency)]
+#![feature(bench_black_box)]
 #![feature(internal_output_capture)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index f352746d3fbe9..25b56b96ed20f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -179,7 +179,7 @@ target | std | host | notes
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS
 `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+)
 `i686-pc-windows-msvc` | ✓ |  | 32-bit Windows XP support
-`i686-unknown-uefi` | ? |  | 32-bit UEFI
+`i686-unknown-uefi` | * |  | 32-bit UEFI
 `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
 `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
 `i686-unknown-openbsd` | ✓ | ✓ | 32-bit OpenBSD
@@ -228,7 +228,7 @@ target | std | host | notes
 `x86_64-unknown-none-hermitkernel` | ? |  | HermitCore kernel
 `x86_64-unknown-l4re-uclibc` | ? |  |
 `x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
-`x86_64-unknown-uefi` | ? |  |
+`x86_64-unknown-uefi` | * |  | 64-bit UEFI
 `x86_64-uwp-windows-gnu` | ✓ |  |
 `x86_64-uwp-windows-msvc` | ✓ |  |
 `x86_64-wrs-vxworks` | ? |  |
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 277ec91f15ed7..1da062f5747e2 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -15,7 +15,7 @@ use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
-use crate::clean::{self, Attributes, GetDefId, ToSource, TypeKind};
+use crate::clean::{self, Attributes, GetDefId, ToSource};
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
 
@@ -56,36 +56,36 @@ crate fn try_inline(
 
     let kind = match res {
         Res::Def(DefKind::Trait, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Trait);
+            record_extern_fqn(cx, did, ItemType::Trait);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::TraitItem(build_external_trait(cx, did))
         }
         Res::Def(DefKind::Fn, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Function);
+            record_extern_fqn(cx, did, ItemType::Function);
             clean::FunctionItem(build_external_function(cx, did))
         }
         Res::Def(DefKind::Struct, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Struct);
+            record_extern_fqn(cx, did, ItemType::Struct);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::StructItem(build_struct(cx, did))
         }
         Res::Def(DefKind::Union, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Union);
+            record_extern_fqn(cx, did, ItemType::Union);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::UnionItem(build_union(cx, did))
         }
         Res::Def(DefKind::TyAlias, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Typedef);
+            record_extern_fqn(cx, did, ItemType::Typedef);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::TypedefItem(build_type_alias(cx, did), false)
         }
         Res::Def(DefKind::Enum, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Enum);
+            record_extern_fqn(cx, did, ItemType::Enum);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::EnumItem(build_enum(cx, did))
         }
         Res::Def(DefKind::ForeignTy, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Foreign);
+            record_extern_fqn(cx, did, ItemType::ForeignType);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
             clean::ForeignTypeItem
         }
@@ -95,24 +95,24 @@ crate fn try_inline(
         // their constructors.
         Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()),
         Res::Def(DefKind::Mod, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Module);
+            record_extern_fqn(cx, did, ItemType::Module);
             clean::ModuleItem(build_module(cx, did, visited))
         }
         Res::Def(DefKind::Static, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Static);
+            record_extern_fqn(cx, did, ItemType::Static);
             clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
         }
         Res::Def(DefKind::Const, did) => {
-            record_extern_fqn(cx, did, clean::TypeKind::Const);
+            record_extern_fqn(cx, did, ItemType::Constant);
             clean::ConstantItem(build_const(cx, did))
         }
         Res::Def(DefKind::Macro(kind), did) => {
             let mac = build_macro(cx, did, name);
 
             let type_kind = match kind {
-                MacroKind::Bang => TypeKind::Macro,
-                MacroKind::Attr => TypeKind::Attr,
-                MacroKind::Derive => TypeKind::Derive,
+                MacroKind::Bang => ItemType::Macro,
+                MacroKind::Attr => ItemType::ProcAttribute,
+                MacroKind::Derive => ItemType::ProcDerive,
             };
             record_extern_fqn(cx, did, type_kind);
             mac
@@ -157,7 +157,7 @@ crate fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> {
 ///
 /// These names are used later on by HTML rendering to generate things like
 /// source links back to the original item.
-crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: clean::TypeKind) {
+crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
     let crate_name = cx.tcx.crate_name(did.krate).to_string();
 
     let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
@@ -165,7 +165,7 @@ crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: clean::Typ
         let s = elem.data.to_string();
         if !s.is_empty() { Some(s) } else { None }
     });
-    let fqn = if let clean::TypeKind::Macro = kind {
+    let fqn = if let ItemType::Macro = kind {
         // Check to see if it is a macro 2.0 or built-in macro
         if matches!(
             cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7d33cf210139c..416468095c407 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -36,6 +36,7 @@ use std::{mem, vec};
 
 use crate::core::{self, DocContext, ImplTraitParam};
 use crate::doctree;
+use crate::formats::item_type::ItemType;
 
 use utils::*;
 
@@ -273,7 +274,7 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
 impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let (trait_ref, bounds) = *self;
-        inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
+        inline::record_extern_fqn(cx, trait_ref.def_id, ItemType::Trait);
         let path = external_path(
             cx,
             cx.tcx.item_name(trait_ref.def_id),
@@ -1028,12 +1029,6 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
     }
 }
 
-impl Clean<TypeKind> for hir::def::DefKind {
-    fn clean(&self, _: &mut DocContext<'_>) -> TypeKind {
-        (*self).into()
-    }
-}
-
 impl Clean<Item> for hir::TraitItem<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let local_did = self.def_id.to_def_id();
@@ -1568,16 +1563,16 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::Adt(def, substs) => {
                 let did = def.did;
                 let kind = match def.adt_kind() {
-                    AdtKind::Struct => TypeKind::Struct,
-                    AdtKind::Union => TypeKind::Union,
-                    AdtKind::Enum => TypeKind::Enum,
+                    AdtKind::Struct => ItemType::Struct,
+                    AdtKind::Union => ItemType::Union,
+                    AdtKind::Enum => ItemType::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
                 let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
                 ResolvedPath { path, param_names: None, did, is_generic: false }
             }
             ty::Foreign(did) => {
-                inline::record_extern_fqn(cx, did, TypeKind::Foreign);
+                inline::record_extern_fqn(cx, did, ItemType::ForeignType);
                 let path = external_path(
                     cx,
                     cx.tcx.item_name(did),
@@ -1602,7 +1597,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     _ => cx.tcx.intern_substs(&[]),
                 };
 
-                inline::record_extern_fqn(cx, did, TypeKind::Trait);
+                inline::record_extern_fqn(cx, did, ItemType::Trait);
 
                 let mut param_names = vec![];
                 if let Some(b) = reg.clean(cx) {
@@ -1612,7 +1607,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     let empty = cx.tcx.intern_substs(&[]);
                     let path =
                         external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
-                    inline::record_extern_fqn(cx, did, TypeKind::Trait);
+                    inline::record_extern_fqn(cx, did, ItemType::Trait);
                     let bound = GenericBound::TraitBound(
                         PolyTrait {
                             trait_: ResolvedPath {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 675de640c7010..9bbb6c0145aae 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -976,7 +976,7 @@ impl GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
         let empty = cx.tcx.intern_substs(&[]);
         let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
-        inline::record_extern_fqn(cx, did, TypeKind::Trait);
+        inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
             PolyTrait {
                 trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
@@ -1315,62 +1315,6 @@ crate enum PrimitiveType {
     Never,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
-crate enum TypeKind {
-    Enum,
-    Function,
-    Module,
-    Const,
-    Static,
-    Struct,
-    Union,
-    Trait,
-    Typedef,
-    Foreign,
-    Macro,
-    Attr,
-    Derive,
-    TraitAlias,
-    Primitive,
-}
-
-impl From<hir::def::DefKind> for TypeKind {
-    fn from(other: hir::def::DefKind) -> Self {
-        match other {
-            hir::def::DefKind::Enum => Self::Enum,
-            hir::def::DefKind::Fn => Self::Function,
-            hir::def::DefKind::Mod => Self::Module,
-            hir::def::DefKind::Const => Self::Const,
-            hir::def::DefKind::Static => Self::Static,
-            hir::def::DefKind::Struct => Self::Struct,
-            hir::def::DefKind::Union => Self::Union,
-            hir::def::DefKind::Trait => Self::Trait,
-            hir::def::DefKind::TyAlias => Self::Typedef,
-            hir::def::DefKind::TraitAlias => Self::TraitAlias,
-            hir::def::DefKind::Macro(_) => Self::Macro,
-            hir::def::DefKind::ForeignTy
-            | hir::def::DefKind::Variant
-            | hir::def::DefKind::AssocTy
-            | hir::def::DefKind::TyParam
-            | hir::def::DefKind::ConstParam
-            | hir::def::DefKind::Ctor(..)
-            | hir::def::DefKind::AssocFn
-            | hir::def::DefKind::AssocConst
-            | hir::def::DefKind::ExternCrate
-            | hir::def::DefKind::Use
-            | hir::def::DefKind::ForeignMod
-            | hir::def::DefKind::AnonConst
-            | hir::def::DefKind::OpaqueTy
-            | hir::def::DefKind::Field
-            | hir::def::DefKind::LifetimeParam
-            | hir::def::DefKind::GlobalAsm
-            | hir::def::DefKind::Impl
-            | hir::def::DefKind::Closure
-            | hir::def::DefKind::Generator => Self::Foreign,
-        }
-    }
-}
-
 crate trait GetDefId {
     /// Use this method to get the [`DefId`] of a [`clean`] AST node.
     /// This will return [`None`] when called on a primitive [`clean::Type`].
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index c2a971d637513..8222e469f6218 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -3,9 +3,10 @@ use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
     ItemKind, Lifetime, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
-    TypeBinding, TypeKind,
+    TypeBinding,
 };
 use crate::core::DocContext;
+use crate::formats::item_type::ItemType;
 
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -431,29 +432,29 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
     debug!("register_res({:?})", res);
 
     let (did, kind) = match res {
-        Res::Def(DefKind::Fn, i) => (i, TypeKind::Function),
-        Res::Def(DefKind::TyAlias, i) => (i, TypeKind::Typedef),
-        Res::Def(DefKind::Enum, i) => (i, TypeKind::Enum),
-        Res::Def(DefKind::Trait, i) => (i, TypeKind::Trait),
+        Res::Def(DefKind::Fn, i) => (i, ItemType::Function),
+        Res::Def(DefKind::TyAlias, i) => (i, ItemType::Typedef),
+        Res::Def(DefKind::Enum, i) => (i, ItemType::Enum),
+        Res::Def(DefKind::Trait, i) => (i, ItemType::Trait),
         Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => {
-            (cx.tcx.parent(i).unwrap(), TypeKind::Trait)
+            (cx.tcx.parent(i).unwrap(), ItemType::Trait)
         }
-        Res::Def(DefKind::Struct, i) => (i, TypeKind::Struct),
-        Res::Def(DefKind::Union, i) => (i, TypeKind::Union),
-        Res::Def(DefKind::Mod, i) => (i, TypeKind::Module),
-        Res::Def(DefKind::ForeignTy, i) => (i, TypeKind::Foreign),
-        Res::Def(DefKind::Const, i) => (i, TypeKind::Const),
-        Res::Def(DefKind::Static, i) => (i, TypeKind::Static),
+        Res::Def(DefKind::Struct, i) => (i, ItemType::Struct),
+        Res::Def(DefKind::Union, i) => (i, ItemType::Union),
+        Res::Def(DefKind::Mod, i) => (i, ItemType::Module),
+        Res::Def(DefKind::ForeignTy, i) => (i, ItemType::ForeignType),
+        Res::Def(DefKind::Const, i) => (i, ItemType::Constant),
+        Res::Def(DefKind::Static, i) => (i, ItemType::Static),
         Res::Def(DefKind::Variant, i) => {
-            (cx.tcx.parent(i).expect("cannot get parent def id"), TypeKind::Enum)
+            (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum)
         }
         Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
-            MacroKind::Bang => (i, TypeKind::Macro),
-            MacroKind::Attr => (i, TypeKind::Attr),
-            MacroKind::Derive => (i, TypeKind::Derive),
+            MacroKind::Bang => (i, ItemType::Macro),
+            MacroKind::Attr => (i, ItemType::ProcAttribute),
+            MacroKind::Derive => (i, ItemType::ProcDerive),
         },
-        Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
-        Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
+        Res::Def(DefKind::TraitAlias, i) => (i, ItemType::TraitAlias),
+        Res::SelfTy(Some(def_id), _) => (def_id, ItemType::Trait),
         Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id,
         _ => return res.def_id(),
     };
@@ -461,7 +462,7 @@ crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
         return did;
     }
     inline::record_extern_fqn(cx, did, kind);
-    if let TypeKind::Trait = kind {
+    if let ItemType::Trait = kind {
         inline::record_extern_trait(cx, did);
     }
     did
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 460d4b907c09a..955de57dc0e5f 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -4,6 +4,7 @@ use std::fmt;
 
 use serde::{Serialize, Serializer};
 
+use rustc_hir::def::DefKind;
 use rustc_span::hygiene::MacroKind;
 
 use crate::clean;
@@ -19,7 +20,7 @@ use crate::clean;
 /// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
 /// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
 /// ordering based on a helper function inside `item_module`, in the same file.
-#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)]
+#[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
 crate enum ItemType {
     Module = 0,
     ExternCrate = 1,
@@ -102,24 +103,43 @@ impl<'a> From<&'a clean::Item> for ItemType {
     }
 }
 
-impl From<clean::TypeKind> for ItemType {
-    fn from(kind: clean::TypeKind) -> ItemType {
-        match kind {
-            clean::TypeKind::Struct => ItemType::Struct,
-            clean::TypeKind::Union => ItemType::Union,
-            clean::TypeKind::Enum => ItemType::Enum,
-            clean::TypeKind::Function => ItemType::Function,
-            clean::TypeKind::Trait => ItemType::Trait,
-            clean::TypeKind::Module => ItemType::Module,
-            clean::TypeKind::Static => ItemType::Static,
-            clean::TypeKind::Const => ItemType::Constant,
-            clean::TypeKind::Typedef => ItemType::Typedef,
-            clean::TypeKind::Foreign => ItemType::ForeignType,
-            clean::TypeKind::Macro => ItemType::Macro,
-            clean::TypeKind::Attr => ItemType::ProcAttribute,
-            clean::TypeKind::Derive => ItemType::ProcDerive,
-            clean::TypeKind::TraitAlias => ItemType::TraitAlias,
-            clean::TypeKind::Primitive => ItemType::Primitive,
+impl From<DefKind> for ItemType {
+    fn from(other: DefKind) -> Self {
+        match other {
+            DefKind::Enum => Self::Enum,
+            DefKind::Fn => Self::Function,
+            DefKind::Mod => Self::Module,
+            DefKind::Const => Self::Constant,
+            DefKind::Static => Self::Static,
+            DefKind::Struct => Self::Struct,
+            DefKind::Union => Self::Union,
+            DefKind::Trait => Self::Trait,
+            DefKind::TyAlias => Self::Typedef,
+            DefKind::TraitAlias => Self::TraitAlias,
+            DefKind::Macro(kind) => match kind {
+                MacroKind::Bang => ItemType::Macro,
+                MacroKind::Attr => ItemType::ProcAttribute,
+                MacroKind::Derive => ItemType::ProcDerive,
+            },
+            DefKind::ForeignTy
+            | DefKind::Variant
+            | DefKind::AssocTy
+            | DefKind::TyParam
+            | DefKind::ConstParam
+            | DefKind::Ctor(..)
+            | DefKind::AssocFn
+            | DefKind::AssocConst
+            | DefKind::ExternCrate
+            | DefKind::Use
+            | DefKind::ForeignMod
+            | DefKind::AnonConst
+            | DefKind::OpaqueTy
+            | DefKind::Field
+            | DefKind::LifetimeParam
+            | DefKind::GlobalAsm
+            | DefKind::Impl
+            | DefKind::Closure
+            | DefKind::Generator => Self::ForeignType,
         }
     }
 }
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 2265905dcbaf4..9838285680809 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -7,7 +7,7 @@ use rustc_span::symbol::{sym, Symbol};
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 
 use crate::clean::types::{
-    FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, TypeKind, WherePredicate,
+    FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
 };
 use crate::clean::{self, AttributesExt};
 use crate::formats::cache::Cache;
@@ -315,15 +315,15 @@ crate fn get_real_types<'tcx>(
     arg: &Type,
     tcx: TyCtxt<'tcx>,
     recurse: i32,
-    res: &mut FxHashSet<(Type, TypeKind)>,
+    res: &mut FxHashSet<(Type, ItemType)>,
 ) -> usize {
-    fn insert(res: &mut FxHashSet<(Type, TypeKind)>, tcx: TyCtxt<'_>, ty: Type) -> usize {
+    fn insert(res: &mut FxHashSet<(Type, ItemType)>, tcx: TyCtxt<'_>, ty: Type) -> usize {
         if let Some(kind) = ty.def_id().map(|did| tcx.def_kind(did).into()) {
             res.insert((ty, kind));
             1
         } else if ty.is_primitive() {
             // This is a primitive, let's store it as such.
-            res.insert((ty, TypeKind::Primitive));
+            res.insert((ty, ItemType::Primitive));
             1
         } else {
             0
@@ -393,7 +393,7 @@ crate fn get_all_types<'tcx>(
     generics: &Generics,
     decl: &FnDecl,
     tcx: TyCtxt<'tcx>,
-) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
+) -> (Vec<(Type, ItemType)>, Vec<(Type, ItemType)>) {
     let mut all_types = FxHashSet::default();
     for arg in decl.inputs.values.iter() {
         if arg.type_.is_self_type() {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d773f37ad90a3..f1d0ba9319a79 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -54,7 +54,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
 
-use crate::clean::{self, GetDefId, RenderedLink, SelfTy, TypeKind};
+use crate::clean::{self, GetDefId, RenderedLink, SelfTy};
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -182,11 +182,11 @@ impl Serialize for IndexItemFunctionType {
 #[derive(Debug)]
 crate struct TypeWithKind {
     ty: RenderType,
-    kind: TypeKind,
+    kind: ItemType,
 }
 
-impl From<(RenderType, TypeKind)> for TypeWithKind {
-    fn from(x: (RenderType, TypeKind)) -> TypeWithKind {
+impl From<(RenderType, ItemType)> for TypeWithKind {
+    fn from(x: (RenderType, ItemType)) -> TypeWithKind {
         TypeWithKind { ty: x.0, kind: x.1 }
     }
 }
@@ -196,7 +196,7 @@ impl Serialize for TypeWithKind {
     where
         S: Serializer,
     {
-        (&self.ty.name, ItemType::from(self.kind)).serialize(serializer)
+        (&self.ty.name, self.kind).serialize(serializer)
     }
 }
 
diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js
index eb232a9608122..9fab435de49c8 100644
--- a/src/librustdoc/html/static/search.js
+++ b/src/librustdoc/html/static/search.js
@@ -935,6 +935,9 @@ window.initSearch = function(rawSearchIndex) {
                 });
                 current += 1;
             });
+            var SHIFT = 16;
+            var CTRL = 17;
+            var ALT = 18;
 
             var currentTab = searchState.currentTab;
             if (e.which === 38) { // up
@@ -967,10 +970,10 @@ window.initSearch = function(rawSearchIndex) {
                 e.preventDefault();
             } else if (e.which === 13) { // return
                 if (actives[currentTab].length) {
-                    document.location.href =
-                        actives[currentTab][0].getElementsByTagName("a")[0].href;
+                    var elem = actives[currentTab][0].getElementsByTagName("a")[0];
+                    document.location.href = elem.href;
                 }
-            } else if (e.which === 16) { // shift
+            } else if ([SHIFT, CTRL, ALT].indexOf(e.which) !== -1) {
                 // Does nothing, it's just to avoid losing "focus" on the highlighted element.
             } else if (actives[currentTab].length > 0) {
                 removeClass(actives[currentTab][0], "highlighted");
diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr
index 9b6bbb68a71f7..e9915ba9e96a5 100644
--- a/src/test/ui/associated-consts/associated-const-dead-code.stderr
+++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr
@@ -2,8 +2,11 @@ error: associated constant is never used: `BAR`
   --> $DIR/associated-const-dead-code.rs:6:5
    |
 LL |     const BAR: u32 = 1;
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^---^^^^^^^^^^
+   |           |
+   |           help: if this is intentional, prefix it with an underscore: `_BAR`
    |
+   = note: the leading underscore signals that this associated constant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/associated-const-dead-code.rs:1:9
    |
diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
index 769b6e952dc9c..6514409698e3e 100644
--- a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
+++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
new file mode 100644
index 0000000000000..e0e2b6c69f280
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:6:34
+   |
+LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
+   |                                  ^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:10:21
+   |
+LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+   |                     ^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
new file mode 100644
index 0000000000000..58abd8db9f09f
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
@@ -0,0 +1,20 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/complex-generic-default-expr.rs:6:47
+   |
+LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
+   |                                               ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/complex-generic-default-expr.rs:10:62
+   |
+LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+   |                                                              ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
new file mode 100644
index 0000000000000..a7b712f7b4b86
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
@@ -0,0 +1,14 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
+
+struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs
index 150c70770ae51..4fa21b8b1fb78 100644
--- a/src/test/ui/const-generics/defaults/const-default.rs
+++ b/src/test/ui/const-generics/defaults/const-default.rs
@@ -1,6 +1,6 @@
 // run-pass
-
-#![feature(const_generics)]
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
new file mode 100644
index 0000000000000..59ac261f44fd5
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = N>([u8; N], [u8; M]);
+
+fn foo<const N: usize>() -> Foo<N> {
+    let x = [0; N];
+    Foo(x, x)
+}
+
+// To check that we actually apply the correct substs for const param defaults.
+fn concrete_foo() -> Foo<13> {
+    Foo(Default::default(), Default::default())
+}
+
+
+fn main() {
+    let val = foo::<13>();
+    assert_eq!(val.0, val.1);
+
+    let val = concrete_foo();
+    assert_eq!(val.0, val.1);
+}
diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
new file mode 100644
index 0000000000000..3f534ca0308ba
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, T = [u8; N]>(T);
+
+impl<const N: usize> Foo<N> {
+    fn new() -> Self {
+        Foo([0; N])
+    }
+}
+
+fn main() {
+    assert_eq!(Foo::new().0, [0; 10]);
+}
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.full.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr
new file mode 100644
index 0000000000000..c417a26842ed1
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr
@@ -0,0 +1,8 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/default-on-impl.rs:8:12
+   |
+LL | impl<const N: usize = 1> Foo<N> {}
+   |            ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr
new file mode 100644
index 0000000000000..c417a26842ed1
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr
@@ -0,0 +1,8 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/default-on-impl.rs:8:12
+   |
+LL | impl<const N: usize = 1> Foo<N> {}
+   |            ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs
new file mode 100644
index 0000000000000..735549defeaf0
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.rs
@@ -0,0 +1,11 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize = 1> Foo<N> {}
+//~^ ERROR defaults for const parameters are only allowed
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs
new file mode 100644
index 0000000000000..4bb56c6a1c08c
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs
@@ -0,0 +1,5 @@
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: u8 = { 255 + 1 }>;
+//~^ ERROR evaluation of constant value failed
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr
new file mode 100644
index 0000000000000..8464ea98bf695
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/default-param-wf-concrete.rs:3:28
+   |
+LL | struct Foo<const N: u8 = { 255 + 1 }>;
+   |                            ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs
index b39e69ab10b66..32acf567cf2b9 100644
--- a/src/test/ui/const-generics/defaults/external.rs
+++ b/src/test/ui/const-generics/defaults/external.rs
@@ -1,5 +1,7 @@
 // aux-build:const_defaulty.rs
 // check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
index c4a666a829d8c..29d835e36c6eb 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
@@ -1,5 +1,5 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:28
+  --> $DIR/intermixed-lifetime.rs:7:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
    |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
index 69a490978d1df..985e7b655ece9 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
@@ -1,26 +1,14 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:28
+  --> $DIR/intermixed-lifetime.rs:7:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
+   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
 
-error: type parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:32
-   |
-LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: lifetime parameters must be declared prior to const parameters
+error: lifetime parameters must be declared prior to type parameters
   --> $DIR/intermixed-lifetime.rs:10:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: type parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:10:28
-   |
-LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
+   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
index 9e83bf92a59b9..307e3aaf1fbf3 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
@@ -1,15 +1,13 @@
-// revisions: full min
 // Checks that lifetimes cannot be interspersed between consts and types.
+// revisions: full min
 #![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 
 struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
 //~^ Error lifetime parameters must be declared prior to const parameters
-//[min]~^^ Error type parameters must be declared prior to const parameters
 
 struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-//[full]~^ Error lifetime parameters must be declared prior to type parameters
-//[min]~^^ Error type parameters must be declared prior to const parameters
-//[min]~| Error lifetime parameters must be declared prior to const parameters
+//~^ Error lifetime parameters must be declared prior to type parameters
 
 fn main() {}
diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr
similarity index 90%
rename from src/test/ui/const-generics/defaults/mismatch.stderr
rename to src/test/ui/const-generics/defaults/mismatch.full.stderr
index ff72c71c40f0f..be4f364d8ee62 100644
--- a/src/test/ui/const-generics/defaults/mismatch.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:11:28
+  --> $DIR/mismatch.rs:12:28
    |
 LL |     let e: Example::<13> = ();
    |            -------------   ^^ expected struct `Example`, found `()`
@@ -7,7 +7,7 @@ LL |     let e: Example::<13> = ();
    |            expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:13:34
+  --> $DIR/mismatch.rs:14:34
    |
 LL |     let e: Example2::<u32, 13> = ();
    |            -------------------   ^^ expected struct `Example2`, found `()`
@@ -18,7 +18,7 @@ LL |     let e: Example2::<u32, 13> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:34
+  --> $DIR/mismatch.rs:16:34
    |
 LL |     let e: Example3::<13, u32> = ();
    |            -------------------   ^^ expected struct `Example3`, found `()`
@@ -29,7 +29,7 @@ LL |     let e: Example3::<13, u32> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:17:28
+  --> $DIR/mismatch.rs:18:28
    |
 LL |     let e: Example3::<7> = ();
    |            -------------   ^^ expected struct `Example3`, found `()`
@@ -40,7 +40,7 @@ LL |     let e: Example3::<7> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:28
+  --> $DIR/mismatch.rs:22:28
    |
 LL |     let e: Example4::<7> = ();
    |            -------------   ^^ expected struct `Example4`, found `()`
diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr
new file mode 100644
index 0000000000000..be4f364d8ee62
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:12:28
+   |
+LL |     let e: Example::<13> = ();
+   |            -------------   ^^ expected struct `Example`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:14:34
+   |
+LL |     let e: Example2::<u32, 13> = ();
+   |            -------------------   ^^ expected struct `Example2`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example2`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:16:34
+   |
+LL |     let e: Example3::<13, u32> = ();
+   |            -------------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example3`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:18:28
+   |
+LL |     let e: Example3::<7> = ();
+   |            -------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example3<7_usize>`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:22:28
+   |
+LL |     let e: Example4::<7> = ();
+   |            -------------   ^^ expected struct `Example4`, found `()`
+   |            |
+   |            expected due to this
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs
index d85b756f538dc..68a640c0a08b3 100644
--- a/src/test/ui/const-generics/defaults/mismatch.rs
+++ b/src/test/ui/const-generics/defaults/mismatch.rs
@@ -1,4 +1,5 @@
-#![feature(const_generics)]
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
index a25d4baca1a97..7a57950dfc924 100644
--- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
+++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
@@ -10,4 +10,4 @@ trait Foo<const KIND: bool = true> {}
 
 fn foo<const SIZE: usize = 5>() {}
 
-struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = {FROM + LEN}>;
+struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>;
diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
index f7a1d2ca4b2ef..f549993c413d4 100644
--- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
+++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
@@ -17,4 +17,4 @@ trait Foo<const KIND : bool = true> { }
 fn foo<const SIZE : usize = 5>() { }
 
 struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
-             { FROM + LEN }>;
+             FROM>;
diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
index 18ecf46729977..c64c2974c8f8f 100644
--- a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
+++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -6,7 +6,7 @@
 #![allow(incomplete_features)]
 
 #[repr(C)]
-pub struct Loaf<T: Sized, const N: usize = 1usize> {
+pub struct Loaf<T: Sized, const N: usize = 1> {
     head: [T; N],
     slice: [T],
 }
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
deleted file mode 100644
index 0746c64ac8cf4..0000000000000
--- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameters must be declared prior to const parameters
-  --> $DIR/simple-defaults.rs:8:40
-   |
-LL | struct FixedOutput<'a, const N: usize, T=u32> {
-   |                   ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs
index cb66c7769bb23..c003cb2c5a6ee 100644
--- a/src/test/ui/const-generics/defaults/simple-defaults.rs
+++ b/src/test/ui/const-generics/defaults/simple-defaults.rs
@@ -1,12 +1,12 @@
-// [full] run-pass
-// revisions: min full
-// Checks some basic test cases for defaults.
+// run-pass
+// Checks that type param defaults are allowed after const params.
+// revisions: full min
 #![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 #![allow(dead_code)]
 
 struct FixedOutput<'a, const N: usize, T=u32> {
-    //[min]~^ ERROR type parameters must be declared prior to const parameters
     out: &'a [T; N],
 }
 
diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs
new file mode 100644
index 0000000000000..e68075ee3c627
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs
@@ -0,0 +1,19 @@
+// check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct N;
+
+struct Foo<const N: usize = 1, T = N>(T);
+
+impl Foo {
+    fn new() -> Self {
+        Foo(N)
+    }
+}
+
+fn main() {
+    let Foo::<1, N>(N) = Foo::new();
+}
diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
index accc73134d899..eb0bcb2821556 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr
+++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
@@ -1,19 +1,8 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:4:10
+  --> $DIR/wrong-order.rs:6:10
    |
 LL | struct A<T = u32, const N: usize> {
    |          ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/wrong-order.rs:2:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
index c8f1d471b244b..eb0bcb2821556 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr
+++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
@@ -1,10 +1,8 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:4:10
+  --> $DIR/wrong-order.rs:6:10
    |
 LL | struct A<T = u32, const N: usize> {
    |          ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs
index 5c2d9b8ad4751..88e9e96ba43f9 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.rs
+++ b/src/test/ui/const-generics/defaults/wrong-order.rs
@@ -1,5 +1,7 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 
 struct A<T = u32, const N: usize> {
     //~^ ERROR generic parameters with a default must be trailing
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
index c2b7b206653a6..e8fd9e7769b79 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
@@ -1,22 +1,17 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
    |
    = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
-   |
-LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-   |                                            ^ the anonymous constant must not depend on the parameter `T`
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
+   |                     ^ defaulted generic parameters cannot be forward declared
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
index 4a462c328bf64..5fa6423306c5a 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
@@ -1,5 +1,5 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
@@ -7,7 +7,7 @@ LL | struct Bar<T = [u8; N], const N: usize>(T);
    = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
 error: generic parameters may not be used in const operations
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44
    |
 LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
@@ -15,11 +15,12 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    = note: type parameters may not be used in const expressions
    = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
+   |                     ^ defaulted generic parameters cannot be forward declared
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
index c7be8bdaf9c3d..76c1b84aef557 100644
--- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
+++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
@@ -1,15 +1,12 @@
 // revisions: full min
-
 #![cfg_attr(full, feature(const_generics))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-//[full]~^ ERROR constant values inside of type parameter defaults
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
-// FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
 struct Bar<T = [u8; N], const N: usize>(T);
-//~^ ERROR constant values inside of type parameter defaults
+//~^ ERROR generic parameters with a default cannot use forward declared identifiers
 //~| ERROR generic parameters with a default
 
 fn main() {}
diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index 9c02d232e134b..66b76627c02e6 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,6 +1,6 @@
 // run-pass
 // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32.
-#![feature(test)]
+#![feature(bench_black_box)]
 use std::hint::black_box;
 
 #[derive(Copy, Clone)]
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index d016d236dbf81..a47f6af02965b 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![feature(const_discriminant)]
-#![feature(test)]
+#![feature(bench_black_box)]
 #![allow(dead_code)]
 
 use std::mem::{discriminant, Discriminant};
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
index 72607629d3c10..ff8fb9953fb53 100644
--- a/src/test/ui/derive-uninhabited-enum-38885.stderr
+++ b/src/test/ui/derive-uninhabited-enum-38885.stderr
@@ -2,8 +2,11 @@ warning: variant is never constructed: `Void`
   --> $DIR/derive-uninhabited-enum-38885.rs:13:5
    |
 LL |     Void(Void),
-   |     ^^^^^^^^^^
+   |     ----^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_Void`
    |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
    = note: `-W dead-code` implied by `-W unused`
 
 warning: 1 warning emitted
diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs
index cb2bb2832b70e..16ea71d48c825 100644
--- a/src/test/ui/generics/generic-non-trailing-defaults.rs
+++ b/src/test/ui/generics/generic-non-trailing-defaults.rs
@@ -5,5 +5,6 @@ struct Vec<A = Heap, T>(A, T);
 
 struct Foo<A, B = Vec<C>, C>(A, B, C);
 //~^ ERROR generic parameters with a default must be trailing
+//~| ERROR generic parameters with a default cannot use
 
 fn main() {}
diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr
index 6d76861750335..713ba091b861c 100644
--- a/src/test/ui/generics/generic-non-trailing-defaults.stderr
+++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr
@@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
    |               ^
 
-error: aborting due to 2 previous errors
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/generic-non-trailing-defaults.rs:6:23
+   |
+LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
+   |                       ^ defaulted generic parameters cannot be forward declared
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr
index 204a39bc8e8e9..3223554a5b778 100644
--- a/src/test/ui/issues/issue-37515.stderr
+++ b/src/test/ui/issues/issue-37515.stderr
@@ -2,8 +2,11 @@ warning: type alias is never used: `Z`
   --> $DIR/issue-37515.rs:5:1
    |
 LL | type Z = dyn for<'x> Send;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^-^^^^^^^^^^^^^^^^^^^^
+   |      |
+   |      help: if this is intentional, prefix it with an underscore: `_Z`
    |
+   = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/issue-37515.rs:3:9
    |
diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr
index f7b9b9c613ae0..8264d0736e03e 100644
--- a/src/test/ui/lint/dead-code/basic.stderr
+++ b/src/test/ui/lint/dead-code/basic.stderr
@@ -2,8 +2,9 @@ error: function is never used: `foo`
   --> $DIR/basic.rs:4:4
    |
 LL | fn foo() {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_foo`
    |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/basic.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/const-and-self.stderr b/src/test/ui/lint/dead-code/const-and-self.stderr
index c0e406189e8ab..e7233f386cc68 100644
--- a/src/test/ui/lint/dead-code/const-and-self.stderr
+++ b/src/test/ui/lint/dead-code/const-and-self.stderr
@@ -2,8 +2,9 @@ warning: variant is never constructed: `B`
   --> $DIR/const-and-self.rs:33:5
    |
 LL |     B,
-   |     ^
+   |     ^ help: if this is intentional, prefix it with an underscore: `_B`
    |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/const-and-self.rs:3:9
    |
@@ -14,7 +15,9 @@ warning: variant is never constructed: `C`
   --> $DIR/const-and-self.rs:34:5
    |
 LL |     C,
-   |     ^
+   |     ^ help: if this is intentional, prefix it with an underscore: `_C`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 warning: 2 warnings emitted
 
diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs
new file mode 100644
index 0000000000000..d28b6430bc587
--- /dev/null
+++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.rs
@@ -0,0 +1,42 @@
+//! The field `guard` is never used directly, but it is still useful for its side effect when
+//! dropped. Since rustc doesn't consider a `Drop` impl as a use, we want to make sure we at least
+//! produce a helpful diagnostic that points the user to what they can do if they indeed intended to
+//! have a field that is only used for its `Drop` side effect.
+//!
+//! Issue: https://github.com/rust-lang/rust/issues/81658
+
+#![deny(dead_code)]
+
+use std::sync::{Mutex, MutexGuard};
+
+/// Holds a locked value until it is dropped
+pub struct Locked<'a, T> {
+    // Field is kept for its affect when dropped, but otherwise unused
+    guard: MutexGuard<'a, T>, //~ ERROR field is never read
+}
+
+impl<'a, T> Locked<'a, T> {
+    pub fn new(value: &'a Mutex<T>) -> Self {
+        Self {
+            guard: value.lock().unwrap(),
+        }
+    }
+}
+
+fn main() {
+    let items = Mutex::new(vec![1, 2, 3]);
+
+    // Hold a lock on items while doing something else
+    let result = {
+        // The lock will be released at the end of this scope
+        let _lock = Locked::new(&items);
+
+        do_something_else()
+    };
+
+    println!("{}", result);
+}
+
+fn do_something_else() -> i32 {
+    1 + 1
+}
diff --git a/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr
new file mode 100644
index 0000000000000..f379a0941166f
--- /dev/null
+++ b/src/test/ui/lint/dead-code/drop-only-field-issue-81658.stderr
@@ -0,0 +1,17 @@
+error: field is never read: `guard`
+  --> $DIR/drop-only-field-issue-81658.rs:15:5
+   |
+LL |     guard: MutexGuard<'a, T>,
+   |     -----^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_guard`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
+note: the lint level is defined here
+  --> $DIR/drop-only-field-issue-81658.rs:8:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr
index ed9a7ccd14b21..5c06cd5a6a0b2 100644
--- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr
+++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr
@@ -2,8 +2,9 @@ error: enum is never used: `E`
   --> $DIR/empty-unused-enum.rs:3:6
    |
 LL | enum E {}
-   |      ^
+   |      ^ help: if this is intentional, prefix it with an underscore: `_E`
    |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/empty-unused-enum.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs
new file mode 100644
index 0000000000000..12eafe6ae4958
--- /dev/null
+++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.rs
@@ -0,0 +1,50 @@
+//! The field `items` is being "used" by FFI (implicitly through pointers). However, since rustc
+//! doesn't know how to detect that, we produce a message that says the field is unused. This can
+//! cause some confusion and we want to make sure our diagnostics help as much as they can.
+//!
+//! Issue: https://github.com/rust-lang/rust/issues/81658
+
+#![deny(dead_code)]
+
+/// A struct for holding on to data while it is being used in our FFI code
+pub struct FFIData<T> {
+    /// These values cannot be dropped while the pointers to each item
+    /// are still in use
+    items: Option<Vec<T>>, //~ ERROR field is never read
+}
+
+impl<T> FFIData<T> {
+    pub fn new() -> Self {
+        Self {items: None}
+    }
+
+    /// Load items into this type and return pointers to each item that can
+    /// be passed to FFI
+    pub fn load(&mut self, items: Vec<T>) -> Vec<*const T> {
+        let ptrs = items.iter().map(|item| item as *const _).collect();
+
+        self.items = Some(items);
+
+        ptrs
+    }
+}
+
+extern {
+    /// The FFI code that uses items
+    fn process_item(item: *const i32);
+}
+
+fn main() {
+    // Data cannot be dropped until the end of this scope or else the items
+    // will be dropped before they are processed
+    let mut data = FFIData::new();
+
+    let ptrs = data.load(vec![1, 2, 3, 4, 5]);
+
+    for ptr in ptrs {
+        // Safety: This pointer is valid as long as the arena is in scope
+        unsafe { process_item(ptr); }
+    }
+
+    // Items will be safely freed at the end of this scope
+}
diff --git a/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr
new file mode 100644
index 0000000000000..d6a247d98e292
--- /dev/null
+++ b/src/test/ui/lint/dead-code/field-used-in-ffi-issue-81658.stderr
@@ -0,0 +1,17 @@
+error: field is never read: `items`
+  --> $DIR/field-used-in-ffi-issue-81658.rs:13:5
+   |
+LL |     items: Option<Vec<T>>,
+   |     -----^^^^^^^^^^^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_items`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
+note: the lint level is defined here
+  --> $DIR/field-used-in-ffi-issue-81658.rs:7:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr
index 09b6d08eb8fb8..fb18eb2819f76 100644
--- a/src/test/ui/lint/dead-code/impl-trait.stderr
+++ b/src/test/ui/lint/dead-code/impl-trait.stderr
@@ -2,8 +2,11 @@ error: type alias is never used: `Unused`
   --> $DIR/impl-trait.rs:12:1
    |
 LL | type Unused = ();
-   | ^^^^^^^^^^^^^^^^^
+   | ^^^^^------^^^^^^
+   |      |
+   |      help: if this is intentional, prefix it with an underscore: `_Unused`
    |
+   = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/impl-trait.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
index af97ea98b2b6d..15448448e1169 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
@@ -2,8 +2,9 @@ error: struct is never constructed: `Bar`
   --> $DIR/lint-dead-code-1.rs:12:16
    |
 LL |     pub struct Bar;
-   |                ^^^
+   |                ^^^ help: if this is intentional, prefix it with an underscore: `_Bar`
    |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/lint-dead-code-1.rs:5:9
    |
@@ -14,55 +15,77 @@ error: static is never used: `priv_static`
   --> $DIR/lint-dead-code-1.rs:20:1
    |
 LL | static priv_static: isize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^-----------^^^^^^^^^^^^
+   |        |
+   |        help: if this is intentional, prefix it with an underscore: `_priv_static`
+   |
+   = note: the leading underscore signals that this static serves some other purpose even if it isn't used in a way that we can detect.
 
 error: constant is never used: `priv_const`
   --> $DIR/lint-dead-code-1.rs:27:1
    |
 LL | const priv_const: isize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^----------^^^^^^^^^^^^
+   |       |
+   |       help: if this is intentional, prefix it with an underscore: `_priv_const`
+   |
+   = note: the leading underscore signals that this constant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: struct is never constructed: `PrivStruct`
   --> $DIR/lint-dead-code-1.rs:35:8
    |
 LL | struct PrivStruct;
-   |        ^^^^^^^^^^
+   |        ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_PrivStruct`
+   |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 
 error: enum is never used: `priv_enum`
   --> $DIR/lint-dead-code-1.rs:64:6
    |
 LL | enum priv_enum { foo2, bar2 }
-   |      ^^^^^^^^^
+   |      ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_enum`
+   |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 
 error: variant is never constructed: `bar3`
   --> $DIR/lint-dead-code-1.rs:67:5
    |
 LL |     bar3
-   |     ^^^^
+   |     ^^^^ help: if this is intentional, prefix it with an underscore: `_bar3`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `priv_fn`
   --> $DIR/lint-dead-code-1.rs:88:4
    |
 LL | fn priv_fn() {
-   |    ^^^^^^^
+   |    ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_priv_fn`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `foo`
   --> $DIR/lint-dead-code-1.rs:93:4
    |
 LL | fn foo() {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_foo`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `bar`
   --> $DIR/lint-dead-code-1.rs:98:4
    |
 LL | fn bar() {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_bar`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `baz`
   --> $DIR/lint-dead-code-1.rs:102:4
    |
 LL | fn baz() -> impl Copy {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_baz`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr
index b01ba57f98580..5e19c7d02ffd3 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr
@@ -2,8 +2,9 @@ error: function is never used: `dead_fn`
   --> $DIR/lint-dead-code-2.rs:22:4
    |
 LL | fn dead_fn() {}
-   |    ^^^^^^^
+   |    ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn`
    |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/lint-dead-code-2.rs:2:9
    |
@@ -14,13 +15,17 @@ error: function is never used: `dead_fn2`
   --> $DIR/lint-dead-code-2.rs:25:4
    |
 LL | fn dead_fn2() {}
-   |    ^^^^^^^^
+   |    ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dead_fn2`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `main`
   --> $DIR/lint-dead-code-2.rs:38:4
    |
 LL | fn main() {
-   |    ^^^^
+   |    ^^^^ help: if this is intentional, prefix it with an underscore: `_main`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
index cf8f01ea19f0c..d32fde5872d99 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
@@ -2,8 +2,9 @@ error: struct is never constructed: `Foo`
   --> $DIR/lint-dead-code-3.rs:14:8
    |
 LL | struct Foo;
-   |        ^^^
+   |        ^^^ help: if this is intentional, prefix it with an underscore: `_Foo`
    |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/lint-dead-code-3.rs:4:9
    |
@@ -14,25 +15,35 @@ error: associated function is never used: `foo`
   --> $DIR/lint-dead-code-3.rs:16:8
    |
 LL |     fn foo(&self) {
-   |        ^^^
+   |        ^^^ help: if this is intentional, prefix it with an underscore: `_foo`
+   |
+   = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `bar`
   --> $DIR/lint-dead-code-3.rs:21:4
    |
 LL | fn bar() {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_bar`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: enum is never used: `c_void`
   --> $DIR/lint-dead-code-3.rs:60:6
    |
 LL | enum c_void {}
-   |      ^^^^^^
+   |      ^^^^^^ help: if this is intentional, prefix it with an underscore: `_c_void`
+   |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `free`
   --> $DIR/lint-dead-code-3.rs:62:5
    |
 LL |     fn free(p: *const c_void);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^----^^^^^^^^^^^^^^^^^^^
+   |        |
+   |        help: if this is intentional, prefix it with an underscore: `_free`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
index 3905d1a06bdfe..2785faa29f5d9 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
@@ -2,8 +2,11 @@ error: field is never read: `b`
   --> $DIR/lint-dead-code-4.rs:7:5
    |
 LL |     b: bool,
-   |     ^^^^^^^
+   |     -^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_b`
    |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 note: the lint level is defined here
   --> $DIR/lint-dead-code-4.rs:3:9
    |
@@ -14,59 +17,88 @@ error: variant is never constructed: `X`
   --> $DIR/lint-dead-code-4.rs:15:5
    |
 LL |     X,
-   |     ^
+   |     ^ help: if this is intentional, prefix it with an underscore: `_X`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: variant is never constructed: `Y`
   --> $DIR/lint-dead-code-4.rs:16:5
    |
-LL | /     Y {
+LL |       Y {
+   |       ^ help: if this is intentional, prefix it with an underscore: `_Y`
+   |  _____|
+   | |
 LL | |         a: String,
 LL | |         b: i32,
 LL | |         c: i32,
 LL | |     },
    | |_____^
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: enum is never used: `ABC`
   --> $DIR/lint-dead-code-4.rs:24:6
    |
 LL | enum ABC {
-   |      ^^^
+   |      ^^^ help: if this is intentional, prefix it with an underscore: `_ABC`
+   |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 
 error: variant is never constructed: `I`
   --> $DIR/lint-dead-code-4.rs:36:5
    |
 LL |     I,
-   |     ^
+   |     ^ help: if this is intentional, prefix it with an underscore: `_I`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: field is never read: `b`
   --> $DIR/lint-dead-code-4.rs:39:9
    |
 LL |         b: i32,
-   |         ^^^^^^
+   |         -^^^^^
+   |         |
+   |         help: if this is intentional, prefix it with an underscore: `_b`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `c`
   --> $DIR/lint-dead-code-4.rs:40:9
    |
 LL |         c: i32,
-   |         ^^^^^^
+   |         -^^^^^
+   |         |
+   |         help: if this is intentional, prefix it with an underscore: `_c`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: variant is never constructed: `K`
   --> $DIR/lint-dead-code-4.rs:42:5
    |
 LL |     K
-   |     ^
+   |     ^ help: if this is intentional, prefix it with an underscore: `_K`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: field is never read: `x`
   --> $DIR/lint-dead-code-4.rs:61:5
    |
 LL |     x: usize,
-   |     ^^^^^^^^
+   |     -^^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_x`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `c`
   --> $DIR/lint-dead-code-4.rs:63:5
    |
 LL |     c: bool,
-   |     ^^^^^^^
+   |     -^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_c`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
index 519add826273f..6375d98d35cb2 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
@@ -2,8 +2,9 @@ error: variant is never constructed: `Variant2`
   --> $DIR/lint-dead-code-5.rs:6:5
    |
 LL |     Variant2
-   |     ^^^^^^^^
+   |     ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant2`
    |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/lint-dead-code-5.rs:2:9
    |
@@ -14,19 +15,29 @@ error: variant is never constructed: `Variant5`
   --> $DIR/lint-dead-code-5.rs:13:5
    |
 LL |     Variant5 { _x: isize },
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     --------^^^^^^^^^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_Variant5`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: variant is never constructed: `Variant6`
   --> $DIR/lint-dead-code-5.rs:14:5
    |
 LL |     Variant6(isize),
-   |     ^^^^^^^^^^^^^^^
+   |     --------^^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_Variant6`
+   |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 
 error: enum is never used: `Enum3`
   --> $DIR/lint-dead-code-5.rs:35:6
    |
 LL | enum Enum3 {
-   |      ^^^^^
+   |      ^^^^^ help: if this is intentional, prefix it with an underscore: `_Enum3`
+   |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr
index 7dc60730d6aad..ef26fe54ab589 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr
@@ -2,8 +2,9 @@ error: struct is never constructed: `UnusedStruct`
   --> $DIR/lint-dead-code-6.rs:3:8
    |
 LL | struct UnusedStruct;
-   |        ^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_UnusedStruct`
    |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/lint-dead-code-6.rs:1:9
    |
@@ -14,19 +15,25 @@ error: associated function is never used: `unused_impl_fn_1`
   --> $DIR/lint-dead-code-6.rs:5:8
    |
 LL |     fn unused_impl_fn_1() {
-   |        ^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_1`
+   |
+   = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: associated function is never used: `unused_impl_fn_2`
   --> $DIR/lint-dead-code-6.rs:9:8
    |
 LL |     fn unused_impl_fn_2(var: i32) {
-   |        ^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_2`
+   |
+   = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: associated function is never used: `unused_impl_fn_3`
   --> $DIR/lint-dead-code-6.rs:13:8
    |
 LL |     fn unused_impl_fn_3(
-   |        ^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_impl_fn_3`
+   |
+   = note: the leading underscore signals that this associated function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr
index fd74405f2b648..5bd566be35e01 100644
--- a/src/test/ui/lint/dead-code/newline-span.stderr
+++ b/src/test/ui/lint/dead-code/newline-span.stderr
@@ -2,8 +2,9 @@ error: function is never used: `unused`
   --> $DIR/newline-span.rs:3:4
    |
 LL | fn unused() {
-   |    ^^^^^^
+   |    ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
    |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/newline-span.rs:1:9
    |
@@ -14,13 +15,17 @@ error: function is never used: `unused2`
   --> $DIR/newline-span.rs:7:4
    |
 LL | fn unused2(var: i32) {
-   |    ^^^^^^^
+   |    ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused2`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: function is never used: `unused3`
   --> $DIR/newline-span.rs:11:4
    |
 LL | fn unused3(
-   |    ^^^^^^^
+   |    ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused3`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr
index b2acd5d4213b3..1e7a030de3aa7 100644
--- a/src/test/ui/lint/dead-code/type-alias.stderr
+++ b/src/test/ui/lint/dead-code/type-alias.stderr
@@ -2,8 +2,11 @@ error: type alias is never used: `Unused`
   --> $DIR/type-alias.rs:4:1
    |
 LL | type Unused = u8;
-   | ^^^^^^^^^^^^^^^^^
+   | ^^^^^------^^^^^^
+   |      |
+   |      help: if this is intentional, prefix it with an underscore: `_Unused`
    |
+   = note: the leading underscore signals that this type alias serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/type-alias.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr
index 9f368fdd2f816..d536479c800ae 100644
--- a/src/test/ui/lint/dead-code/unused-enum.stderr
+++ b/src/test/ui/lint/dead-code/unused-enum.stderr
@@ -2,8 +2,9 @@ error: struct is never constructed: `F`
   --> $DIR/unused-enum.rs:3:8
    |
 LL | struct F;
-   |        ^
+   |        ^ help: if this is intentional, prefix it with an underscore: `_F`
    |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/unused-enum.rs:1:9
    |
@@ -15,13 +16,17 @@ error: struct is never constructed: `B`
   --> $DIR/unused-enum.rs:4:8
    |
 LL | struct B;
-   |        ^
+   |        ^ help: if this is intentional, prefix it with an underscore: `_B`
+   |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 
 error: enum is never used: `E`
   --> $DIR/unused-enum.rs:6:6
    |
 LL | enum E {
-   |      ^
+   |      ^ help: if this is intentional, prefix it with an underscore: `_E`
+   |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr
index b93d6d4ac1866..394ced3e81001 100644
--- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr
+++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr
@@ -2,8 +2,11 @@ error: variant is never constructed: `Bar`
   --> $DIR/unused-struct-variant.rs:8:5
    |
 LL |     Bar(B),
-   |     ^^^^^^
+   |     ---^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_Bar`
    |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/unused-struct-variant.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr
index a547f5af4b082..7dcb79d0490c1 100644
--- a/src/test/ui/lint/dead-code/unused-variant.stderr
+++ b/src/test/ui/lint/dead-code/unused-variant.stderr
@@ -2,8 +2,9 @@ error: variant is never constructed: `Variant1`
   --> $DIR/unused-variant.rs:5:5
    |
 LL |     Variant1,
-   |     ^^^^^^^^
+   |     ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_Variant1`
    |
+   = note: the leading underscore signals that this variant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/unused-variant.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr
index 2c63e60d67609..1bde434069ee7 100644
--- a/src/test/ui/lint/dead-code/with-core-crate.stderr
+++ b/src/test/ui/lint/dead-code/with-core-crate.stderr
@@ -2,8 +2,9 @@ error: function is never used: `foo`
   --> $DIR/with-core-crate.rs:7:4
    |
 LL | fn foo() {
-   |    ^^^
+   |    ^^^ help: if this is intentional, prefix it with an underscore: `_foo`
    |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/with-core-crate.rs:1:9
    |
diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr
index a191d22c8b94c..13a21bb1193de 100644
--- a/src/test/ui/lint/dead-code/write-only-field.stderr
+++ b/src/test/ui/lint/dead-code/write-only-field.stderr
@@ -2,8 +2,11 @@ error: field is never read: `f`
   --> $DIR/write-only-field.rs:4:5
    |
 LL |     f: i32,
-   |     ^^^^^^
+   |     -^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_f`
    |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 note: the lint level is defined here
   --> $DIR/write-only-field.rs:1:9
    |
@@ -14,31 +17,51 @@ error: field is never read: `sub`
   --> $DIR/write-only-field.rs:5:5
    |
 LL |     sub: Sub,
-   |     ^^^^^^^^
+   |     ---^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_sub`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `f`
   --> $DIR/write-only-field.rs:9:5
    |
 LL |     f: i32,
-   |     ^^^^^^
+   |     -^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_f`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `y`
   --> $DIR/write-only-field.rs:28:9
    |
 LL |         y: bool,
-   |         ^^^^^^^
+   |         -^^^^^^
+   |         |
+   |         help: if this is intentional, prefix it with an underscore: `_y`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `u`
   --> $DIR/write-only-field.rs:58:9
    |
 LL |         u: u32,
-   |         ^^^^^^
+   |         -^^^^^
+   |         |
+   |         help: if this is intentional, prefix it with an underscore: `_u`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `v`
   --> $DIR/write-only-field.rs:59:9
    |
 LL |         v: u32,
-   |         ^^^^^^
+   |         -^^^^^
+   |         |
+   |         help: if this is intentional, prefix it with an underscore: `_v`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
index ce4ebcb5e3ef6..e880006e114c1 100644
--- a/src/test/ui/lint/issue-17718-const-naming.stderr
+++ b/src/test/ui/lint/issue-17718-const-naming.stderr
@@ -2,8 +2,11 @@ error: constant is never used: `foo`
   --> $DIR/issue-17718-const-naming.rs:4:1
    |
 LL | const foo: isize = 3;
-   | ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^---^^^^^^^^^^^^
+   |       |
+   |       help: if this is intentional, prefix it with an underscore: `_foo`
    |
+   = note: the leading underscore signals that this constant serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/issue-17718-const-naming.rs:2:9
    |
diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr
index 45cf5f8688cd1..f94a9e30a3dfa 100644
--- a/src/test/ui/span/macro-span-replacement.stderr
+++ b/src/test/ui/span/macro-span-replacement.stderr
@@ -2,11 +2,14 @@ warning: struct is never constructed: `S`
   --> $DIR/macro-span-replacement.rs:7:14
    |
 LL |         $b $a;
-   |              ^
+   |            --^
+   |            |
+   |            help: if this is intentional, prefix it with an underscore: `_S`
 ...
 LL |     m!(S struct);
    |     ------------- in this macro invocation
    |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/macro-span-replacement.rs:3:9
    |
diff --git a/src/test/ui/span/unused-warning-point-at-identifier.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr
index 6ef877da122f5..3bf342f197252 100644
--- a/src/test/ui/span/unused-warning-point-at-identifier.stderr
+++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr
@@ -2,8 +2,9 @@ warning: enum is never used: `Enum`
   --> $DIR/unused-warning-point-at-identifier.rs:5:6
    |
 LL | enum Enum {
-   |      ^^^^
+   |      ^^^^ help: if this is intentional, prefix it with an underscore: `_Enum`
    |
+   = note: the leading underscore signals that this enum serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/unused-warning-point-at-identifier.rs:3:9
    |
@@ -15,19 +16,25 @@ warning: struct is never constructed: `Struct`
   --> $DIR/unused-warning-point-at-identifier.rs:12:8
    |
 LL | struct Struct {
-   |        ^^^^^^
+   |        ^^^^^^ help: if this is intentional, prefix it with an underscore: `_Struct`
+   |
+   = note: the leading underscore signals that this struct serves some other purpose even if it isn't used in a way that we can detect.
 
 warning: function is never used: `func`
   --> $DIR/unused-warning-point-at-identifier.rs:19:4
    |
 LL | fn func() -> usize {
-   |    ^^^^
+   |    ^^^^ help: if this is intentional, prefix it with an underscore: `_func`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 warning: function is never used: `func_complete_span`
   --> $DIR/unused-warning-point-at-identifier.rs:24:1
    |
 LL | func_complete_span()
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_func_complete_span`
+   |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 
 warning: 4 warnings emitted
 
diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr
index d3bcea2951364..e5a8dee6ccb68 100644
--- a/src/test/ui/test-attrs/test-warns-dead-code.stderr
+++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr
@@ -2,8 +2,9 @@ error: function is never used: `dead`
   --> $DIR/test-warns-dead-code.rs:5:4
    |
 LL | fn dead() {}
-   |    ^^^^
+   |    ^^^^ help: if this is intentional, prefix it with an underscore: `_dead`
    |
+   = note: the leading underscore signals that this function serves some other purpose even if it isn't used in a way that we can detect.
 note: the lint level is defined here
   --> $DIR/test-warns-dead-code.rs:3:9
    |
diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr
index 87621cc01b1b9..3595bf6dce688 100644
--- a/src/test/ui/union/union-fields-1.stderr
+++ b/src/test/ui/union/union-fields-1.stderr
@@ -2,8 +2,11 @@ error: field is never read: `c`
   --> $DIR/union-fields-1.rs:6:5
    |
 LL |     c: u8,
-   |     ^^^^^
+   |     -^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_c`
    |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 note: the lint level is defined here
   --> $DIR/union-fields-1.rs:1:9
    |
@@ -14,19 +17,31 @@ error: field is never read: `a`
   --> $DIR/union-fields-1.rs:9:5
    |
 LL |     a: u8,
-   |     ^^^^^
+   |     -^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_a`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `a`
   --> $DIR/union-fields-1.rs:13:20
    |
 LL | union NoDropLike { a: u8 }
-   |                    ^^^^^
+   |                    -^^^^
+   |                    |
+   |                    help: if this is intentional, prefix it with an underscore: `_a`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: field is never read: `c`
   --> $DIR/union-fields-1.rs:18:5
    |
 LL |     c: u8,
-   |     ^^^^^
+   |     -^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_c`
+   |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr
index 7de70ec33801f..8ead9cde9b333 100644
--- a/src/test/ui/union/union-lint-dead-code.stderr
+++ b/src/test/ui/union/union-lint-dead-code.stderr
@@ -2,8 +2,11 @@ error: field is never read: `b`
   --> $DIR/union-lint-dead-code.rs:5:5
    |
 LL |     b: bool,
-   |     ^^^^^^^
+   |     -^^^^^^
+   |     |
+   |     help: if this is intentional, prefix it with an underscore: `_b`
    |
+   = note: the leading underscore signals that this field serves some other purpose even if it isn't used in a way that we can detect. (e.g. for its effect when dropped or in foreign code)
 note: the lint level is defined here
   --> $DIR/union-lint-dead-code.rs:1:9
    |