about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs11
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs38
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs53
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs7
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs21
-rw-r--r--compiler/rustc_macros/src/serialize.rs4
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs9
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs4
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs40
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs33
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs87
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs2
-rw-r--r--compiler/rustc_passes/src/layout_test.rs1
-rw-r--r--compiler/rustc_passes/src/liveness.rs1
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs75
-rw-r--r--compiler/rustc_session/src/config.rs12
-rw-r--r--compiler/rustc_span/src/symbol.rs9
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs1
-rw-r--r--compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs56
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/sync.rs6
-rw-r--r--library/core/src/ffi/c_str.rs4
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/num/int_macros.rs1
-rw-r--r--library/core/src/num/uint_macros.rs1
-rw-r--r--library/std/src/collections/hash/map.rs6
-rw-r--r--library/std/src/collections/hash/set.rs7
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/f32.rs10
-rw-r--r--library/std/src/f64.rs10
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/windows/os.rs8
-rw-r--r--library/std/src/sys_common/thread_parking/id.rs17
-rw-r--r--src/doc/rustdoc/src/lints.md34
-rw-r--r--src/librustdoc/html/markdown.rs107
-rw-r--r--src/librustdoc/lint.rs12
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs109
-rw-r--r--src/librustdoc/passes/lint.rs2
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs352
m---------src/tools/cargo0
-rw-r--r--tests/run-make/optimization-remarks-dir-pgo/Makefile1
-rw-r--r--tests/rustdoc-ui/lints/inline-doc-link.rs13
-rw-r--r--tests/rustdoc-ui/lints/no-redundancy.rs7
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.fixed158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.rs158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.stderr1007
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.rs1
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.stderr128
-rw-r--r--tests/rustdoc/description.rs1
-rw-r--r--tests/rustdoc/intra-doc/basic.rs2
-rw-r--r--tests/rustdoc/intra-doc/generic-params.rs1
-rw-r--r--tests/rustdoc/intra-doc/issue-108459.rs1
-rw-r--r--tests/ui/abi/relocation_model_pic.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr12
-rw-r--r--tests/ui/inline-const/required-const.rs13
-rw-r--r--tests/ui/inline-const/required-const.stderr11
-rw-r--r--tests/ui/macros/macro-interpolation.rs4
-rw-r--r--tests/ui/macros/macro-interpolation.stderr16
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs14
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr19
-rw-r--r--tests/ui/or-patterns/missing-bindings.stderr68
-rw-r--r--tests/ui/resolve/resolve-inconsistent-names.stderr18
-rw-r--r--tests/ui/span/issue-39698.stderr20
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs73
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs75
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr9
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr37
-rw-r--r--triagebot.toml2
91 files changed, 2697 insertions, 459 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 068b255e9f2..58ce73047bc 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -150,6 +150,8 @@ pub fn print_crate<'a>(
 /// and also addresses some specific regressions described in #63896 and #73345.
 fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     if let TokenTree::Token(token, _) = prev {
+        // No space after these tokens, e.g. `x.y`, `$e`
+        // (The carets point to `prev`.)       ^     ^
         if matches!(token.kind, token::Dot | token::Dollar) {
             return false;
         }
@@ -158,10 +160,19 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
         }
     }
     match tt {
+        // No space before these tokens, e.g. `foo,`, `println!`, `x.y`
+        // (The carets point to `token`.)         ^           ^     ^
+        //
+        // FIXME: having `Not` here works well for macro invocations like
+        // `println!()`, but is bad when `!` means "logical not" or "the never
+        // type", where the lack of space causes ugliness like this:
+        // `Fn() ->!`, `x =! y`, `if! x { f(); }`.
         TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
+        // No space before parentheses if preceded by these tokens, e.g. `foo(...)`
         TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
         }
+        // No space before brackets if preceded by these tokens, e.g. `#[...]`
         TokenTree::Delimited(_, Delimiter::Bracket, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
         }
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index d257145373f..becfa535a59 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -30,7 +30,7 @@ pub use super::{
 /// will be retrieved.
 #[derive(Debug, Copy, Clone)]
 pub enum ConsumerOptions {
-    /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
+    /// Retrieve the [`Body`] along with the [`BorrowSet`]
     /// and [`RegionInferenceContext`]. If you would like the body only, use
     /// [`TyCtxt::mir_promoted`].
     ///
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 4c9094bf1f5..b6c01545f30 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -128,7 +128,10 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attr
 
         // The function name varies on platforms.
         // See test/CodeGen/mcount.c in clang.
-        let mcount_name = cx.sess().target.mcount.as_ref();
+        let mcount_name = match &cx.sess().target.llvm_mcount_intrinsic {
+            Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
+            None => cx.sess().target.mcount.as_ref(),
+        };
 
         attrs.push(llvm::CreateAttrStringValue(
             cx.llcx,
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 0be84c9fa83..4c854740753 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -16,6 +16,7 @@ use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
 use rustc_session::Session;
+use rustc_span::sym;
 use rustc_target::abi::Endian;
 use rustc_target::spec::{ef_avr_arch, RelocModel, Target};
 
@@ -272,35 +273,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Architecture::Riscv32 | Architecture::Riscv64 => {
             // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
             let mut e_flags: u32 = 0x0;
-            let features = &sess.target.options.features;
+
             // Check if compressed is enabled
-            if features.contains("+c") {
+            // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::c) {
                 e_flags |= elf::EF_RISCV_RVC;
             }
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE;
-            } else {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `RISCVELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "" | "ilp32" | "lp64" => (),
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
+                "ilp32e" => e_flags |= elf::EF_RISCV_RVE,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::LoongArch64 => {
             // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
             let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
-            let features = &sess.target.options.features;
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT;
-            } else {
-                e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `LoongArchELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::Avr => {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 032f4be6c99..b740b79d162 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -427,52 +427,41 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
+        orig_instance: ty::Instance<'tcx>,
         _abi: CallAbi,
         args: &[FnArg<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
-        debug!("find_mir_or_eval_fn: {:?}", instance);
+        debug!("find_mir_or_eval_fn: {:?}", orig_instance);
+
+        // Replace some functions.
+        let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
+            // Call has already been handled.
+            return Ok(None);
+        };
 
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def) = instance.def {
             // Execution might have wandered off into other crates, so we cannot do a stability-
-            // sensitive check here. But we can at least rule out functions that are not const
-            // at all.
-            if !ecx.tcx.is_const_fn_raw(def) {
-                // allow calling functions inside a trait marked with #[const_trait].
-                if !ecx.tcx.is_const_default_method(def) {
-                    // We certainly do *not* want to actually call the fn
-                    // though, so be sure we return here.
-                    throw_unsup_format!("calling non-const function `{}`", instance)
-                }
-            }
-
-            let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
-                return Ok(None);
-            };
-
-            if new_instance != instance {
-                // We call another const fn instead.
-                // However, we return the *original* instance to make backtraces work out
-                // (and we hope this does not confuse the FnAbi checks too much).
-                return Ok(Self::find_mir_or_eval_fn(
-                    ecx,
-                    new_instance,
-                    _abi,
-                    args,
-                    dest,
-                    ret,
-                    _unwind,
-                )?
-                .map(|(body, _instance)| (body, instance)));
+            // sensitive check here. But we can at least rule out functions that are not const at
+            // all. That said, we have to allow calling functions inside a trait marked with
+            // #[const_trait]. These *are* const-checked!
+            // FIXME: why does `is_const_fn_raw` not classify them as const?
+            if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
+                || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
+            {
+                // We certainly do *not* want to actually call the fn
+                // though, so be sure we return here.
+                throw_unsup_format!("calling non-const function `{}`", instance)
             }
         }
 
         // This is a const fn. Call it.
-        Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
+        // In case of replacement, we return the *original* instance to make backtraces work out
+        // (and we hope this does not confuse the FnAbi checks too much).
+        Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
     }
 
     fn call_intrinsic(
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7d660d2dbaa..34518b53759 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -452,11 +452,11 @@ struct HandlerInner {
     /// have been converted.
     check_unstable_expect_diagnostics: bool,
 
-    /// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
+    /// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
     /// the lint level. [`LintExpectationId`]s created early during the compilation
     /// (before `HirId`s have been defined) are not stable and can therefore not be
     /// stored on disk. This buffer stores these diagnostics until the ID has been
-    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
+    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the
     /// submitted for storage and added to the list of fulfilled expectations.
     unstable_expect_diagnostics: Vec<Diagnostic>,
 
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 05c0cd952b8..7e85beaadcb 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -81,7 +81,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorGuaranteed;
 use rustc_lint_defs::pluralize;
-use rustc_parse::parser::{NtOrTt, Parser};
+use rustc_parse::parser::{ParseNtResult, Parser};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
@@ -692,8 +692,8 @@ impl TtParser {
                             Ok(nt) => nt,
                         };
                         let m = match nt {
-                            NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
-                            NtOrTt::Tt(tt) => MatchedTokenTree(tt),
+                            ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+                            ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
                         };
                         mp.push_match(next_metavar, seq_depth, m);
                         mp.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index ce8b4621720..a5959d68fbc 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1328,7 +1328,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatWithOr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index b6382dcb894..7c37aadc67a 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -93,7 +93,17 @@ fn parse_count<'sess>(
     span: Span,
 ) -> PResult<'sess, MetaVarExpr> {
     let ident = parse_ident(iter, sess, span)?;
-    let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None };
+    let depth = if try_eat_comma(iter) {
+        if iter.look_ahead(0).is_none() {
+            return Err(sess.span_diagnostic.struct_span_err(
+                span,
+                "`count` followed by a comma must have an associated index indicating its depth",
+            ));
+        }
+        Some(parse_depth(iter, sess, span)?)
+    } else {
+        None
+    };
     Ok(MetaVarExpr::Count(ident, depth))
 }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a5f83b88f7e..15e7ab3fe3e 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -220,16 +220,15 @@ pub(super) fn transcribe<'a>(
                         MatchedTokenTree(tt) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
                             // without wrapping them into groups.
-                            let token = tt.clone();
-                            result.push(token);
+                            result.push(tt.clone());
                         }
                         MatchedNonterminal(nt) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::Invisible` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
                             marker.visit_span(&mut sp);
-                            let token = TokenTree::token_alone(token::Interpolated(nt.clone()), sp);
-                            result.push(token);
+                            result
+                                .push(TokenTree::token_alone(token::Interpolated(nt.clone()), sp));
                         }
                         MatchedSeq(..) => {
                             // We were unable to descend far enough. This is an error.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 953ea1bf523..f5708f933d5 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -352,6 +352,8 @@ declare_features! (
     (active, c_variadic, "1.34.0", Some(44930), None),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
     (active, cfg_overflow_checks, "1.71.0", Some(111466), None),
+    /// Provides the relocation model information as cfg entry
+    (active, cfg_relocation_model, "CURRENT_RUSTC_VERSION", Some(114929), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index a183cfd8776..2f7cff3ce5c 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -35,6 +35,7 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
     (sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
+    (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 5bc0e2ee86c..31a03fabe4f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
                     if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     fcx.tcx.lifetimes.re_erased,
                                     TypeAndMut { ty: expr_ty, mutbl },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
                     } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
                         && expr_mutbl == Mutability::Not
                         && mutbl == Mutability::Mut
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     expr_reg,
                                     TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg_mutref = true;
                     }
@@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     if !sugg_mutref
                         && sugg == None
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                     }
                 } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
                     && fcx
-                        .try_coerce(
-                            self.expr,
+                        .can_coerce(
                             Ty::new_ref(fcx.tcx,
                                 fcx.tcx.lifetimes.re_erased,
                                 TypeAndMut { ty: self.expr_ty, mutbl },
                             ),
                             self.cast_ty,
-                            AllowTwoPhase::No,
-                            None,
                         )
-                        .is_ok()
                 {
                     sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                 }
@@ -760,7 +744,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     ty::FnDef(..) => {
                         // Attempt a coercion to a fn pointer type.
                         let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
-                        let res = fcx.try_coerce(
+                        let res = fcx.coerce(
                             self.expr,
                             self.expr_ty,
                             Ty::new_fn_ptr(fcx.tcx, f),
@@ -860,7 +844,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
             (_, DynStar) => {
                 if fcx.tcx.features().dyn_star {
-                    bug!("should be handled by `try_coerce`")
+                    bug!("should be handled by `coerce`")
                 } else {
                     Err(CastError::IllegalCast)
                 }
@@ -956,7 +940,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
                 // Coerce to a raw pointer so that we generate AddressOf in MIR.
                 let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr);
-                fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
+                fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
                     .unwrap_or_else(|_| {
                         bug!(
                         "could not cast from reference to array to pointer to array ({:?} to {:?})",
@@ -992,7 +976,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> {
-        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
+        match fcx.coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
             Ok(_) => Ok(()),
             Err(err) => Err(err),
         }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 726914a995b..fca675ea9d8 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// adjusted type of the expression, if successful.
     /// Adjustments are only recorded if the coercion succeeded.
     /// The expressions *must not* have any preexisting adjustments.
-    pub fn try_coerce(
+    pub fn coerce(
         &self,
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    /// Same as `try_coerce()`, but without side-effects.
+    /// Same as `coerce()`, but without side-effects.
     ///
     /// Returns false if the coercion creates any obligations that result in
     /// errors.
@@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 // Special-case the first expression we are coercing.
                 // To be honest, I'm not entirely sure why we do this.
                 // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
-                fcx.try_coerce(
+                fcx.coerce(
                     expression,
                     expression_ty,
                     self.expected_ty,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 6aeabc1bebb..2c16f21b491 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
         let expected = self.resolve_vars_with_obligations(expected);
 
-        let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
+        let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
             Ok(ty) => return (ty, None),
             Err(e) => e,
         };
@@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 {
                     let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; };
                     let arg_ty = arg_ty.fold_with(&mut fudger);
-                    let _ = self.try_coerce(
+                    let _ = self.coerce(
                         arg_expr,
                         arg_ty,
                         *expected_arg_ty,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 004c8affcf0..4def7867384 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -260,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // fulfillment error to be more accurate.
             let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
 
-            let coerce_error = self
-                .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
-                .err();
+            let coerce_error =
+                self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
 
             if coerce_error.is_some() {
                 return Compatibility::Incompatible(coerce_error);
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 5b19a4c525f..3f1dca5b1de 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -14,6 +14,7 @@ use rustc_span::symbol::kw::{Empty, Underscore};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
+use std::fmt::Write;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(super) fn lint_dot_call_from_2018(
@@ -143,16 +144,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
                     if precise {
-                        let args = args
-                            .iter()
-                            .map(|arg| {
-                                let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
-                                format!(
-                                    ", {}",
-                                    self.sess().source_map().span_to_snippet(span).unwrap()
-                                )
-                            })
-                            .collect::<String>();
+                        let args = args.iter().fold(String::new(), |mut string, arg| {
+                            let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
+                            write!(
+                                string,
+                                ", {}",
+                                self.sess().source_map().span_to_snippet(span).unwrap()
+                            )
+                            .unwrap();
+                            string
+                        });
 
                         lint.span_suggestion(
                             sp,
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index f1e7b8eb6c7..ba75517d7a6 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -59,14 +59,14 @@ fn decodable_body(
                 })
                 .collect();
             let message = format!(
-                "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                "invalid enum variant tag while decoding `{}`, expected 0..{}, actual {{}}",
                 ty_name,
                 variants.len()
             );
             quote! {
                 match ::rustc_serialize::Decoder::read_usize(__decoder) {
                     #match_inner
-                    _ => panic!(#message),
+                    n => panic!(#message, n),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index e8fd469e1fb..0da8fe9cca7 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -164,18 +164,15 @@ pub fn provide(providers: &mut Providers) {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
     providers.def_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
     };
     providers.def_ident_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_ident_span(hir_id)
     };
-    providers.fn_arg_names = |tcx, id| {
+    providers.fn_arg_names = |tcx, def_id| {
         let hir = tcx.hir();
-        let def_id = id;
         let hir_id = hir.local_def_id_to_hir_id(def_id);
         if let Some(body_id) = hir.maybe_body_owned_by(def_id) {
             tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
@@ -190,7 +187,7 @@ pub fn provide(providers: &mut Providers) {
         {
             idents
         } else {
-            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
+            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id);
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id);
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index e71482326da..5db9b775a0f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,6 +1,7 @@
 //! Diagnostics related methods for `Ty`.
 
 use std::borrow::Cow;
+use std::fmt::Write;
 use std::ops::ControlFlow;
 
 use crate::ty::{
@@ -335,10 +336,10 @@ pub fn suggest_constraining_type_params<'a>(
             //                                           - insert: `, X: Bar`
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
-                constraints
-                    .iter()
-                    .map(|&(constraint, _)| format!(", {param_name}: {constraint}"))
-                    .collect::<String>(),
+                constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
+                    write!(string, ", {param_name}: {constraint}").unwrap();
+                    string
+                }),
                 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
             ));
             continue;
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index d2c0c4ba069..083f1f8aef6 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -199,9 +199,9 @@ impl DebugOptions {
 
 fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool {
     if let Some(val) = some_strval {
-        if vec!["yes", "y", "on", "true"].contains(&val) {
+        if ["yes", "y", "on", "true"].contains(&val) {
             true
-        } else if vec!["no", "n", "off", "false"].contains(&val) {
+        } else if ["no", "n", "off", "false"].contains(&val) {
             false
         } else {
             bug!(
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e409c7c6781..e308e5b3420 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -193,13 +193,7 @@ impl<'a> Parser<'a> {
 
         self.expected_tokens.push(TokenType::Operator);
         while let Some(op) = self.check_assoc_op() {
-            // Adjust the span for interpolated LHS to point to the `$lhs` token
-            // and not to what it refers to.
-            let lhs_span = match self.prev_token.kind {
-                TokenKind::Interpolated(..) => self.prev_token.span,
-                _ => lhs.span,
-            };
-
+            let lhs_span = self.interpolated_or_expr_span(&lhs);
             let cur_op_span = self.token.span;
             let restrictions = if op.node.is_assign_like() {
                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
@@ -626,8 +620,8 @@ impl<'a> Parser<'a> {
 
     fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
         self.bump();
-        let expr = self.parse_expr_prefix(None);
-        let (span, expr) = self.interpolated_or_expr_span(expr)?;
+        let expr = self.parse_expr_prefix(None)?;
+        let span = self.interpolated_or_expr_span(&expr);
         Ok((lo.to(span), expr))
     }
 
@@ -702,20 +696,12 @@ impl<'a> Parser<'a> {
         self.parse_expr_unary(lo, UnOp::Not)
     }
 
-    /// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
-    fn interpolated_or_expr_span(
-        &self,
-        expr: PResult<'a, P<Expr>>,
-    ) -> PResult<'a, (Span, P<Expr>)> {
-        expr.map(|e| {
-            (
-                match self.prev_token.kind {
-                    TokenKind::Interpolated(..) => self.prev_token.span,
-                    _ => e.span,
-                },
-                e,
-            )
-        })
+    /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
+    fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
+        match self.prev_token.kind {
+            TokenKind::Interpolated(..) => self.prev_token.span,
+            _ => expr.span,
+        }
     }
 
     fn parse_assoc_op_cast(
@@ -898,8 +884,8 @@ impl<'a> Parser<'a> {
             self.parse_expr_prefix_range(None)
         } else {
             self.parse_expr_prefix(None)
-        };
-        let (hi, expr) = self.interpolated_or_expr_span(expr)?;
+        }?;
+        let hi = self.interpolated_or_expr_span(&expr);
         let span = lo.to(hi);
         if let Some(lt) = lifetime {
             self.error_remove_borrow_lifetime(span, lt.ident.span);
@@ -930,8 +916,8 @@ impl<'a> Parser<'a> {
     fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
         self.collect_tokens_for_expr(attrs, |this, attrs| {
-            let base = this.parse_expr_bottom();
-            let (span, base) = this.interpolated_or_expr_span(base)?;
+            let base = this.parse_expr_bottom()?;
+            let span = this.interpolated_or_expr_span(&base);
             this.parse_expr_dot_or_call_with(base, span, attrs)
         })
     }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ce4d4a60551..77c59bb3881 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1052,33 +1052,48 @@ impl<'a> Parser<'a> {
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
-    /// When `dist == 0` then the current token is looked at.
+    /// When `dist == 0` then the current token is looked at. `Eof` will be
+    /// returned if the look-ahead is any distance past the end of the tokens.
     pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
         if dist == 0 {
             return looker(&self.token);
         }
 
-        let tree_cursor = &self.token_cursor.tree_cursor;
         if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
             && delim != Delimiter::Invisible
         {
+            // We are not in the outermost token stream, and the token stream
+            // we are in has non-skipped delimiters. Look for skipped
+            // delimiters in the lookahead range.
+            let tree_cursor = &self.token_cursor.tree_cursor;
             let all_normal = (0..dist).all(|i| {
                 let token = tree_cursor.look_ahead(i);
                 !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
             });
             if all_normal {
+                // There were no skipped delimiters. Do lookahead by plain indexing.
                 return match tree_cursor.look_ahead(dist - 1) {
-                    Some(tree) => match tree {
-                        TokenTree::Token(token, _) => looker(token),
-                        TokenTree::Delimited(dspan, delim, _) => {
-                            looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                    Some(tree) => {
+                        // Indexing stayed within the current token stream.
+                        match tree {
+                            TokenTree::Token(token, _) => looker(token),
+                            TokenTree::Delimited(dspan, delim, _) => {
+                                looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                            }
                         }
-                    },
-                    None => looker(&Token::new(token::CloseDelim(delim), span.close)),
+                    }
+                    None => {
+                        // Indexing went past the end of the current token
+                        // stream. Use the close delimiter, no matter how far
+                        // ahead `dist` went.
+                        looker(&Token::new(token::CloseDelim(delim), span.close))
+                    }
                 };
             }
         }
 
+        // We are in a more complex case. Just clone the token cursor and use
+        // `next`, skipping delimiters as necessary. Slow but simple.
         let mut cursor = self.token_cursor.clone();
         let mut i = 0;
         let mut token = Token::dummy();
@@ -1476,7 +1491,7 @@ pub enum FlatToken {
 }
 
 #[derive(Debug)]
-pub enum NtOrTt {
+pub enum ParseNtResult {
     Nt(Nonterminal),
     Tt(TokenTree),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index f5681532b3a..ff059a7e865 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
+use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
 use rustc_errors::IntoDiagnostic;
@@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Ident};
 
 use crate::errors::UnexpectedNonterminal;
 use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
@@ -20,10 +20,21 @@ impl<'a> Parser<'a> {
     pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
-            !matches!(
-                *nt,
-                token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_)
-            )
+            match nt {
+                NtStmt(_)
+                | NtPat(_)
+                | NtExpr(_)
+                | NtTy(_)
+                | NtIdent(..)
+                | NtLiteral(_) // `true`, `false`
+                | NtMeta(_)
+                | NtPath(_) => true,
+
+                NtItem(_)
+                | NtBlock(_)
+                | NtVis(_)
+                | NtLifetime(_) => false,
+            }
         }
 
         match kind {
@@ -44,27 +55,19 @@ impl<'a> Parser<'a> {
             },
             NonterminalKind::Block => match &token.kind {
                 token::OpenDelim(Delimiter::Brace) => true,
-                token::Interpolated(nt) => !matches!(
-                    **nt,
-                    token::NtItem(_)
-                        | token::NtPat(_)
-                        | token::NtTy(_)
-                        | token::NtIdent(..)
-                        | token::NtMeta(_)
-                        | token::NtPath(_)
-                        | token::NtVis(_)
-                ),
+                token::Interpolated(nt) => match **nt {
+                    NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
+                    NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
+                    | NtVis(_) => false,
+                },
                 _ => false,
             },
             NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
                 token::ModSep | token::Ident(..) => true,
-                token::Interpolated(nt) => match **nt {
-                    token::NtPath(_) | token::NtMeta(_) => true,
-                    _ => may_be_ident(&nt),
-                },
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
                 match &token.kind {
                 token::Ident(..) |                          // box, ref, mut, and other identifiers (can stricten)
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
@@ -79,7 +82,7 @@ impl<'a> Parser<'a> {
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) =>  matches!(kind, NonterminalKind::PatWithOr {..}),
+                token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             }
@@ -87,7 +90,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Lifetime => match &token.kind {
                 token::Lifetime(_) => true,
                 token::Interpolated(nt) => {
-                    matches!(**nt, token::NtLifetime(_))
+                    matches!(**nt, NtLifetime(_))
                 }
                 _ => false,
             },
@@ -100,18 +103,16 @@ impl<'a> Parser<'a> {
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
     /// site.
     #[inline]
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
-        // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
-        // needs to have them force-captured here.
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
         let mut nt = match kind {
             // Note that TT is treated differently to all the others.
-            NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
+            NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
-                Some(item) => token::NtItem(item),
+                Some(item) => NtItem(item),
                 None => {
                     return Err(UnexpectedNonterminal::Item(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
@@ -120,19 +121,19 @@ impl<'a> Parser<'a> {
             NonterminalKind::Block => {
                 // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
                 // the ':block' matcher does not support them
-                token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
+                NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
-                Some(s) => token::NtStmt(P(s)),
+                Some(s) => NtStmt(P(s)),
                 None => {
                     return Err(UnexpectedNonterminal::Statement(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
                 }
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
-                token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
+                NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
-                    NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+                    NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
                         RecoverColon::No,
@@ -142,16 +143,16 @@ impl<'a> Parser<'a> {
                 })?)
             }
 
-            NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?),
+            NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?),
             NonterminalKind::Literal => {
                 // The `:literal` matcher does not support attributes
-                token::NtLiteral(
+                NtLiteral(
                     self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
                 )
             }
 
-            NonterminalKind::Ty => token::NtTy(
-                self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+            NonterminalKind::Ty => NtTy(
+                self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
             ),
 
             // this could be handled like a token, since it is one
@@ -159,7 +160,7 @@ impl<'a> Parser<'a> {
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
             {
                 self.bump();
-                token::NtIdent(ident, is_raw)
+                NtIdent(ident, is_raw)
             }
             NonterminalKind::Ident => {
                 return Err(UnexpectedNonterminal::Ident {
@@ -167,16 +168,16 @@ impl<'a> Parser<'a> {
                     token: self.token.clone(),
                 }.into_diagnostic(&self.sess.span_diagnostic));
             }
-            NonterminalKind::Path => token::NtPath(
+            NonterminalKind::Path => NtPath(
                 P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
             ),
-            NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
-            NonterminalKind::Vis => token::NtVis(
+            NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)),
+            NonterminalKind::Vis => NtVis(
                 P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?),
             ),
             NonterminalKind::Lifetime => {
                 if self.check_lifetime() {
-                    token::NtLifetime(self.expect_lifetime().ident)
+                    NtLifetime(self.expect_lifetime().ident)
                 } else {
                     return Err(UnexpectedNonterminal::Lifetime {
                         span: self.token.span,
@@ -196,7 +197,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(NtOrTt::Nt(nt))
+        Ok(ParseNtResult::Nt(nt))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 27b1e9c0f11..2d888efb1f3 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -180,7 +180,7 @@ impl<'a> Parser<'a> {
         )
     }
 
-    pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 0463ee2914b..a7a8af864ac 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -27,7 +27,6 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
 }
 
 fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let tcx = tcx;
     let param_env = tcx.param_env(item_def_id);
     let ty = tcx.type_of(item_def_id).instantiate_identity();
     match tcx.layout_of(param_env.and(ty)) {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 0c0b8b6d094..20e996eaec4 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1105,7 +1105,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 }
 
                 // Then do a second pass for inputs
-                let mut succ = succ;
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. } => {
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index d433391f272..ba7417b6dda 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,4 +1,4 @@
-use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag};
 use rustc_ast as ast;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_data_structures::fx::FxHashMap;
@@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s
     let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
     let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
 
-    Parser::new_with_broken_link_callback(
+    parse_links(&doc)
+}
+
+/// Similiar version of `markdown_links` from rustdoc.
+/// This will collect destination links and display text if exists.
+fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         &doc,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .filter_map(|event| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            Some(preprocess_link(&dest))
+    .into_iter();
+    let mut links = Vec::new();
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    if let Some(display_text) = collect_link_data(&mut event_iter) {
+                        links.push(display_text);
+                    }
+                }
+
+                links.push(preprocess_link(&dest));
+            }
+            _ => {}
+        }
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut Parser<'input, 'callback>,
+) -> Option<Box<str>> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    display_text.map(String::into_boxed_str)
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 28ae88424ab..f00472f181d 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -12,7 +12,7 @@ use crate::{EarlyErrorHandler, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_target::abi::Align;
-use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
 use crate::parse::{CrateCheckConfig, CrateConfig};
@@ -1193,6 +1193,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let os = &sess.target.os;
     let env = &sess.target.env;
     let abi = &sess.target.abi;
+    let relocation_model = sess.target.relocation_model.desc_symbol();
     let vendor = &sess.target.vendor;
     let min_atomic_width = sess.target.min_atomic_width();
     let max_atomic_width = sess.target.max_atomic_width();
@@ -1218,6 +1219,9 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
     ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
+    if sess.is_nightly_build() {
+        ret.insert((sym::relocation_model, Some(relocation_model)));
+    }
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
     if sess.target.has_thread_local {
         ret.insert((sym::target_thread_local, None));
@@ -1415,6 +1419,8 @@ impl CrateCheckConfig {
             .into_iter()
             .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
 
+        let relocation_model_values = RelocModel::all();
+
         // Unknown possible values:
         //  - `feature`
         //  - `target_feature`
@@ -1453,6 +1459,10 @@ impl CrateCheckConfig {
             .entry(sym::target_has_atomic_equal_alignment)
             .or_insert_with(no_values)
             .extend(atomic_values);
+        self.expecteds
+            .entry(sym::relocation_model)
+            .or_insert_with(empty_values)
+            .extend(relocation_model_values);
 
         // Target specific values
         {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index edbf51e9b33..28a2dfebcfe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -445,6 +445,7 @@ symbols! {
         bridge,
         bswap,
         builtin_syntax,
+        c,
         c_str,
         c_str_literals,
         c_unwind,
@@ -468,6 +469,7 @@ symbols! {
         cfg_hide,
         cfg_overflow_checks,
         cfg_panic,
+        cfg_relocation_model,
         cfg_sanitize,
         cfg_target_abi,
         cfg_target_compact,
@@ -661,6 +663,7 @@ symbols! {
         dyn_metadata,
         dyn_star,
         dyn_trait,
+        dynamic_no_pic: "dynamic-no-pic",
         e,
         edition_panic,
         effects,
@@ -1115,6 +1118,8 @@ symbols! {
         path,
         pattern_parentheses,
         phantom_data,
+        pic,
+        pie,
         pin,
         platform_intrinsics,
         plugin,
@@ -1223,6 +1228,7 @@ symbols! {
         register_tool,
         relaxed_adts,
         relaxed_struct_unsize,
+        relocation_model,
         rem,
         rem_assign,
         repr,
@@ -1243,6 +1249,8 @@ symbols! {
         rintf64,
         riscv_target_feature,
         rlib,
+        ropi,
+        ropi_rwpi: "ropi-rwpi",
         rotate_left,
         rotate_right,
         roundevenf32,
@@ -1354,6 +1362,7 @@ symbols! {
         rustdoc_missing_doc_code_examples,
         rustfmt,
         rvalue_static_promotion,
+        rwpi,
         s,
         safety,
         sanitize,
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
index c0f1827ad3f..400030ca0c6 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
index 79b8958c22a..6228fb15a83 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
index 4836f3cf720..1d66515a72e 100644
--- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             endian: Endian::Big,
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
index 1de63a920c8..cffebcc9581 100644
--- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             has_thumb_interworking: true,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
index b7cfccc8b3d..4a8aa31576f 100644
--- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             features: "+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::freebsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
index 903042d7e7a..73ae212a7a6 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index af2b96ccb51..31b6961bb62 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -42,7 +42,7 @@ use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_fs_util::try_canonicalize;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 use serde_json::Value;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
@@ -655,6 +655,43 @@ pub enum RelocModel {
     RopiRwpi,
 }
 
+impl RelocModel {
+    pub fn desc(&self) -> &str {
+        match *self {
+            RelocModel::Static => "static",
+            RelocModel::Pic => "pic",
+            RelocModel::Pie => "pie",
+            RelocModel::DynamicNoPic => "dynamic-no-pic",
+            RelocModel::Ropi => "ropi",
+            RelocModel::Rwpi => "rwpi",
+            RelocModel::RopiRwpi => "ropi-rwpi",
+        }
+    }
+    pub const fn desc_symbol(&self) -> Symbol {
+        match *self {
+            RelocModel::Static => kw::Static,
+            RelocModel::Pic => sym::pic,
+            RelocModel::Pie => sym::pie,
+            RelocModel::DynamicNoPic => sym::dynamic_no_pic,
+            RelocModel::Ropi => sym::ropi,
+            RelocModel::Rwpi => sym::rwpi,
+            RelocModel::RopiRwpi => sym::ropi_rwpi,
+        }
+    }
+
+    pub const fn all() -> [Symbol; 7] {
+        [
+            RelocModel::Static.desc_symbol(),
+            RelocModel::Pic.desc_symbol(),
+            RelocModel::Pie.desc_symbol(),
+            RelocModel::DynamicNoPic.desc_symbol(),
+            RelocModel::Ropi.desc_symbol(),
+            RelocModel::Rwpi.desc_symbol(),
+            RelocModel::RopiRwpi.desc_symbol(),
+        ]
+    }
+}
+
 impl FromStr for RelocModel {
     type Err = ();
 
@@ -674,16 +711,7 @@ impl FromStr for RelocModel {
 
 impl ToJson for RelocModel {
     fn to_json(&self) -> Json {
-        match *self {
-            RelocModel::Static => "static",
-            RelocModel::Pic => "pic",
-            RelocModel::Pie => "pie",
-            RelocModel::DynamicNoPic => "dynamic-no-pic",
-            RelocModel::Ropi => "ropi",
-            RelocModel::Rwpi => "rwpi",
-            RelocModel::RopiRwpi => "ropi-rwpi",
-        }
-        .to_json()
+        self.desc().to_json()
     }
 }
 
@@ -1922,6 +1950,9 @@ pub struct TargetOptions {
     /// Use platform dependent mcount function
     pub mcount: StaticCow<str>,
 
+    /// Use LLVM intrinsic for mcount function name
+    pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
+
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
     pub llvm_abiname: StaticCow<str>,
 
@@ -2183,6 +2214,7 @@ impl Default for TargetOptions {
             override_export_symbols: None,
             merge_functions: MergeFunctions::Aliases,
             mcount: "mcount".into(),
+            llvm_mcount_intrinsic: None,
             llvm_abiname: "".into(),
             relax_elf_relocations: false,
             llvm_args: cvs![],
@@ -2840,6 +2872,7 @@ impl Target {
         key!(override_export_symbols, opt_list);
         key!(merge_functions, MergeFunctions)?;
         key!(mcount = "target-mcount");
+        key!(llvm_mcount_intrinsic, optional);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
         key!(llvm_args, list);
@@ -3096,6 +3129,7 @@ impl ToJson for Target {
         target_option_val!(override_export_symbols);
         target_option_val!(merge_functions);
         target_option_val!(mcount, "target-mcount");
+        target_option_val!(llvm_mcount_intrinsic);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
         target_option_val!(llvm_args);
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 0990b9bee90..523841951b0 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // created inside of the query directly instead of returning them to the
         // caller.
         let prev_universe = self.infcx.universe();
-        let universes_created_in_query = response.max_universe.index() + 1;
+        let universes_created_in_query = response.max_universe.index();
         for _ in 0..universes_created_in_query {
             self.infcx.create_next_universe();
         }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 41aac02eaa9..ffe6d637387 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -89,6 +89,7 @@
 #![allow(explicit_outlives_requirements)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index e2a2fe932ab..476a4fea54f 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -153,7 +153,7 @@ macro_rules! acquire {
 ///
 /// ## `Deref` behavior
 ///
-/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
+/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
 /// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
 /// functions, called using [fully qualified syntax]:
@@ -187,7 +187,6 @@ macro_rules! acquire {
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
 /// [atomic]: core::sync::atomic
-/// [deref]: core::ops::Deref
 /// [downgrade]: Arc::downgrade
 /// [upgrade]: Weak::upgrade
 /// [RefCell\<T>]: core::cell::RefCell
@@ -1495,7 +1494,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// alignment as `T`. This is trivially true if `U` is `T`.
     /// Note that if `U` is not `T` but has the same size and alignment, this is
     /// basically like transmuting references of different types. See
-    /// [`mem::transmute`][transmute] for more information on what
+    /// [`mem::transmute`] for more information on what
     /// restrictions apply in this case.
     ///
     /// The raw pointer must point to a block of memory allocated by `alloc`
@@ -1507,7 +1506,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// even if the returned `Arc<T>` is never accessed.
     ///
     /// [into_raw]: Arc::into_raw
-    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 92e38df4049..163a65c909e 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -253,7 +253,7 @@ impl CStr {
     /// ```
     ///
     /// [valid]: core::ptr#safety
-    #[inline]
+    #[inline] // inline is necessary for codegen to see strlen.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
@@ -280,6 +280,8 @@ impl CStr {
                 len
             }
 
+            // `inline` is necessary for codegen to see strlen.
+            #[inline]
             fn strlen_rt(s: *const c_char) -> usize {
                 extern "C" {
                     /// Provided by libc or compiler_builtins.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 48c3c1f2123..a2729b3743c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -97,6 +97,8 @@
 #![allow(incomplete_features)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+// Do not check link redundancy on bootstraping phase
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 1199d09b563..1f43520e1b3 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2126,6 +2126,7 @@ macro_rules! int_impl {
         /// assert_eq!(a.rem_euclid(-b), 3);
         /// assert_eq!((-a).rem_euclid(-b), 1);
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 2136d29255f..81148c7cc51 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2024,6 +2024,7 @@ macro_rules! uint_impl {
         /// ```
         #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")]
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index a083b65604d..be173a7ace6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -49,12 +49,14 @@ use crate::sys;
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashMap` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 959403e1644..6d85b26af5f 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -24,13 +24,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashSet` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 7bc3af1793e..375ff2d2450 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -10,7 +10,7 @@ use crate::fmt::{self, Write};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::error::Error;
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
-pub use core::error::{request_ref, Request};
+pub use core::error::{request_ref, request_value, Request};
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index a53b8535213..a659b552f47 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -61,6 +61,7 @@ impl f32 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f32 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f32 {
     /// // limitation due to round-off error
     /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -904,6 +911,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +934,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +959,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= 1e-5);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index a1cec22c97a..721e1fb754e 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -61,6 +61,7 @@ impl f64 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f64 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f64 {
     /// // limitation due to round-off error
     /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -904,6 +911,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +934,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +959,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ac4ce222fba..58684ffe500 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -223,6 +223,7 @@
 #![cfg_attr(not(bootstrap), allow(internal_features))]
 #![deny(rustc::existing_doc_keyword)]
 #![deny(fuzzy_provenance_casts)]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs
index 2329426ad1d..58afca088ef 100644
--- a/library/std/src/sys/windows/os.rs
+++ b/library/std/src/sys/windows/os.rs
@@ -25,10 +25,6 @@ pub fn errno() -> i32 {
 
 /// Gets a detailed string description for the given error number.
 pub fn error_string(mut errnum: i32) -> String {
-    // This value is calculated from the macro
-    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
-    let langId = 0x0800 as c::DWORD;
-
     let mut buf = [0 as c::WCHAR; 2048];
 
     unsafe {
@@ -56,13 +52,13 @@ pub fn error_string(mut errnum: i32) -> String {
             flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
             module,
             errnum as c::DWORD,
-            langId,
+            0,
             buf.as_mut_ptr(),
             buf.len() as c::DWORD,
             ptr::null(),
         ) as usize;
         if res == 0 {
-            // Sometimes FormatMessageW can fail e.g., system doesn't like langId,
+            // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
             let fm_err = errno();
             return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
         }
diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs
index 15042fc3bee..04667439660 100644
--- a/library/std/src/sys_common/thread_parking/id.rs
+++ b/library/std/src/sys_common/thread_parking/id.rs
@@ -56,18 +56,14 @@ impl Parker {
         self.init_tid();
 
         // Changes NOTIFIED to EMPTY and EMPTY to PARKED.
-        let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1);
-        if state == PARKED {
+        let state = self.state.fetch_sub(1, Acquire);
+        if state == EMPTY {
             // Loop to guard against spurious wakeups.
-            while state == PARKED {
+            // The state must be reset with acquire ordering to ensure that all
+            // calls to `unpark` synchronize with this thread.
+            while self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed).is_err() {
                 park(self.state.as_ptr().addr());
-                state = self.state.load(Acquire);
             }
-
-            // Since the state change has already been observed with acquire
-            // ordering, the state can be reset with a relaxed store instead
-            // of a swap.
-            self.state.store(EMPTY, Relaxed);
         }
     }
 
@@ -78,8 +74,7 @@ impl Parker {
         if state == PARKED {
             park_timeout(dur, self.state.as_ptr().addr());
             // Swap to ensure that we observe all state changes with acquire
-            // ordering, even if the state has been changed after the timeout
-            // occurred.
+            // ordering.
             self.state.swap(EMPTY, Acquire);
         }
     }
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index fd57b079644..f15e6e451e7 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it
 
 warning: 1 warning emitted
 ```
+
+## `redundant_explicit_links`
+
+This lint is **warned by default**. It detects explicit links that are same
+as computed automatic links.
+This usually means the explicit links is removeable. For example:
+
+```rust
+#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default.
+
+/// add takes 2 [`usize`](usize) and performs addition
+/// on them, then returns result.
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+```
+
+Which will give:
+
+```text
+error: redundant explicit rustdoc link
+  --> src/lib.rs:3:27
+   |
+3  | /// add takes 2 [`usize`](usize) and performs addition
+   |                           ^^^^^
+   |
+   = note: Explicit link does not affect the original link
+note: the lint level is defined here
+  --> src/lib.rs:1:9
+   |
+1  | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: Remove explicit link instead
+```
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 0ba2d992392..98cc38a10d4 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
 use crate::html::toc::TocBuilder;
 
 use pulldown_cmark::{
-    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
 };
 
 #[cfg(test)]
@@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
 pub(crate) struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
+    pub display_text: Option<String>,
     pub range: MarkdownLinkRange,
 }
 
@@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
     }
 }
 
-pub(crate) fn markdown_links<R>(
-    md: &str,
+pub(crate) fn markdown_links<'md, R>(
+    md: &'md str,
     preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
 ) -> Vec<R> {
     if md.is_empty() {
@@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>(
         MarkdownLinkRange::Destination(range.clone())
     };
 
-    Parser::new_with_broken_link_callback(
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         md,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .into_offset_iter()
-    .filter_map(|(event, span)| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            let range = match link_type {
-                // Link is pulled from the link itself.
-                LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
-                    span_for_offset_backward(span, b'[', b']')
-                }
-                LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
-                LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
-                // Link is pulled from elsewhere in the document.
-                LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
-                    span_for_link(&dest, span)
+    .into_offset_iter();
+    let mut links = Vec::new();
+
+    while let Some((event, span)) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                let range = match link_type {
+                    // Link is pulled from the link itself.
+                    LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+                        span_for_offset_backward(span, b'[', b']')
+                    }
+                    LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+                    LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+                    // Link is pulled from elsewhere in the document.
+                    LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+                        span_for_link(&dest, span)
+                    }
+                    LinkType::Autolink | LinkType::Email => unreachable!(),
+                };
+
+                let display_text = if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    collect_link_data(&mut event_iter)
+                } else {
+                    None
+                };
+
+                if let Some(link) = preprocess_link(MarkdownLink {
+                    kind: link_type,
+                    link: dest.into_string(),
+                    display_text,
+                    range,
+                }) {
+                    links.push(link);
                 }
-                LinkType::Autolink | LinkType::Email => unreachable!(),
-            };
-            preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut OffsetIter<'input, 'callback>,
+) -> Option<String> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some((event, _span)) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    display_text
 }
 
 #[derive(Debug)]
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 749c1ff51bf..d45040e348a 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -185,6 +185,17 @@ declare_rustdoc_lint! {
    "detects unescaped backticks in doc comments"
 }
 
+declare_rustdoc_lint! {
+    /// This lint is **warned by default**. It detects explicit links that are same
+    /// as computed automatic links. This usually means the explicit links is removeable.
+    /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book].
+    ///
+    /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links
+    REDUNDANT_EXPLICIT_LINKS,
+    Warn,
+    "detects redundant explicit links in doc comments"
+}
+
 pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
     vec![
         BROKEN_INTRA_DOC_LINKS,
@@ -197,6 +208,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
         BARE_URLS,
         MISSING_CRATE_LEVEL_DOCS,
         UNESCAPED_BACKTICKS,
+        REDUNDANT_EXPLICIT_LINKS,
     ]
 });
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 26ff64f06a3..36872266ee1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -994,7 +994,7 @@ impl LinkCollector<'_, '_> {
                 _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
             };
             for md_link in preprocessed_markdown_links(&doc) {
-                let link = self.resolve_link(item, item_id, module_id, &doc, &md_link);
+                let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
                 if let Some(link) = link {
                     self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
                 }
@@ -1007,13 +1007,12 @@ impl LinkCollector<'_, '_> {
     /// FIXME(jynelson): this is way too many arguments
     fn resolve_link(
         &mut self,
+        dox: &String,
         item: &Item,
         item_id: DefId,
         module_id: DefId,
-        dox: &str,
-        link: &PreprocessedMarkdownLink,
+        PreprocessedMarkdownLink(pp_link, ori_link): &PreprocessedMarkdownLink,
     ) -> Option<ItemLink> {
-        let PreprocessedMarkdownLink(pp_link, ori_link) = link;
         trace!("considering link '{}'", ori_link.link);
 
         let diag_info = DiagnosticInfo {
@@ -1022,7 +1021,6 @@ impl LinkCollector<'_, '_> {
             ori_link: &ori_link.link,
             link_range: ori_link.range.clone(),
         };
-
         let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
             pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
         let disambiguator = *disambiguator;
@@ -1040,8 +1038,24 @@ impl LinkCollector<'_, '_> {
             // resolutions are cached, for other links we want to report an error every
             // time so they are not cached.
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+            false,
         )?;
 
+        if ori_link.display_text.is_some() {
+            self.resolve_display_text(
+                path_str,
+                ResolutionInfo {
+                    item_id,
+                    module_id,
+                    dis: disambiguator,
+                    path_str: ori_link.display_text.clone()?.into_boxed_str(),
+                    extra_fragment: extra_fragment.clone(),
+                },
+                &ori_link,
+                &diag_info,
+            );
+        }
+
         // Check for a primitive which might conflict with a module
         // Report the ambiguity and require that the user specify which one they meant.
         // FIXME: could there ever be a primitive not in the type namespace?
@@ -1221,6 +1235,9 @@ impl LinkCollector<'_, '_> {
         // If errors are cached then they are only reported on first occurrence
         // which we want in some cases but not in others.
         cache_errors: bool,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Option<(Res, Option<UrlFragment>)> {
         if let Some(res) = self.visited_links.get(&key) {
             if res.is_some() || cache_errors {
@@ -1228,7 +1245,7 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
+        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
 
         // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
         // However I'm not sure how to check that across crates.
@@ -1279,6 +1296,9 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Vec<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
@@ -1308,7 +1328,9 @@ impl LinkCollector<'_, '_> {
                                 }
                             }
                         }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        if !recoverable {
+                            resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        }
                         return vec![];
                     }
                 }
@@ -1345,13 +1367,15 @@ impl LinkCollector<'_, '_> {
                     .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
 
                 if len == 0 {
-                    resolution_failure(
-                        self,
-                        diag,
-                        path_str,
-                        disambiguator,
-                        candidates.into_iter().filter_map(|res| res.err()).collect(),
-                    );
+                    if !recoverable {
+                        resolution_failure(
+                            self,
+                            diag,
+                            path_str,
+                            disambiguator,
+                            candidates.into_iter().filter_map(|res| res.err()).collect(),
+                        );
+                    }
                     return vec![];
                 } else if len == 1 {
                     candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
@@ -1372,6 +1396,63 @@ impl LinkCollector<'_, '_> {
             }
         }
     }
+
+    /// Resolve display text if the provided link has separated parts of links.
+    ///
+    /// For example:
+    /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has
+    /// separated parts of links.
+    fn resolve_display_text(
+        &mut self,
+        explicit_link: &Box<str>,
+        display_res_info: ResolutionInfo,
+        ori_link: &MarkdownLink,
+        diag_info: &DiagnosticInfo<'_>,
+    ) {
+        // Check if explicit resolution's path is same as resolution of original link's display text path, see
+        // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
+        //
+        // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
+        // into explicit path.
+        if !matches!(
+            ori_link.kind,
+            LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown
+        ) {
+            return;
+        }
+
+        // Algorithm to check if display text could possibly be the explicit link:
+        //
+        // Consider 2 links which are display text and explicit link, pick the shorter
+        // one as symbol and longer one as full qualified path, and tries to match symbol
+        // to the full qualified path's last symbol.
+        //
+        // Otherwise, check if 2 links are same, if so, skip the resolve process.
+        //
+        // Notice that this algorithm is passive, might possibly miss actual redudant cases.
+        let explicit_link = &explicit_link.to_string();
+        let display_text = ori_link.display_text.as_ref().unwrap();
+        let display_len = display_text.len();
+        let explicit_len = explicit_link.len();
+
+        if display_len == explicit_len {
+            // Whether they are same or not, skip the resolve process.
+            return;
+        }
+
+        if (explicit_len >= display_len
+            && &explicit_link[(explicit_len - display_len)..] == display_text)
+            || (display_len >= explicit_len
+                && &display_text[(display_len - explicit_len)..] == explicit_link)
+        {
+            self.resolve_with_disambiguator_cached(
+                display_res_info,
+                diag_info.clone(), // this struct should really be Copy, but Range is not :(
+                false,
+                true,
+            );
+        }
+    }
 }
 
 /// Get the section of a link between the backticks,
diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs
index e653207b9b6..c6d5b7bd346 100644
--- a/src/librustdoc/passes/lint.rs
+++ b/src/librustdoc/passes/lint.rs
@@ -4,6 +4,7 @@
 mod bare_urls;
 mod check_code_block_syntax;
 mod html_tags;
+mod redundant_explicit_links;
 mod unescaped_backticks;
 
 use super::Pass;
@@ -29,6 +30,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
         check_code_block_syntax::visit_item(self.cx, item);
         html_tags::visit_item(self.cx, item);
         unescaped_backticks::visit_item(self.cx, item);
+        redundant_explicit_links::visit_item(self.cx, item);
 
         self.visit_item_recur(item)
     }
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
new file mode 100644
index 00000000000..ef0f8716aa8
--- /dev/null
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -0,0 +1,352 @@
+use std::ops::Range;
+
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, OffsetIter, Parser, Tag};
+use rustc_ast::NodeId;
+use rustc_errors::SuggestionStyle;
+use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res};
+use rustc_hir::HirId;
+use rustc_lint_defs::Applicability;
+use rustc_span::Symbol;
+
+use crate::clean::utils::find_nearest_parent_module;
+use crate::clean::utils::inherits_doc_hidden;
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
+use crate::passes::source_span_for_markdown_range;
+
+#[derive(Debug)]
+struct LinkData {
+    resolvable_link: Option<String>,
+    resolvable_link_range: Option<Range<usize>>,
+    display_link: String,
+}
+
+pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
+    let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else {
+        // If non-local, no need to check anything.
+        return;
+    };
+
+    let doc = item.doc_value();
+    if doc.is_empty() {
+        return;
+    }
+
+    if item.link_names(&cx.cache).is_empty() {
+        // If there's no link names in this item,
+        // then we skip resolution querying to
+        // avoid from panicking.
+        return;
+    }
+
+    let Some(item_id) = item.def_id() else {
+        return;
+    };
+    let Some(local_item_id) = item_id.as_local() else {
+        return;
+    };
+
+    let is_hidden = !cx.render_options.document_hidden
+        && (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None));
+    if is_hidden {
+        return;
+    }
+    let is_private = !cx.render_options.document_private
+        && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id);
+    if is_private {
+        return;
+    }
+
+    check_redundant_explicit_link(cx, item, hir_id, &doc);
+}
+
+fn check_redundant_explicit_link<'md>(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &'md str,
+) -> Option<()> {
+    let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut offset_iter = Parser::new_with_broken_link_callback(
+        &doc,
+        main_body_opts(),
+        Some(&mut broken_line_callback),
+    )
+    .into_offset_iter();
+    let item_id = item.def_id()?;
+    let module_id = match cx.tcx.def_kind(item_id) {
+        DefKind::Mod if item.inner_docs(cx.tcx) => item_id,
+        _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(),
+    };
+    let resolutions = cx.tcx.doc_link_resolutions(module_id);
+
+    while let Some((event, link_range)) = offset_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) => {
+                let link_data = collect_link_data(&mut offset_iter);
+
+                if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
+                    if &link_data.display_link.replace("`", "") != resolvable_link {
+                        // Skips if display link does not match to actual
+                        // resolvable link, usually happens if display link
+                        // has several segments, e.g.
+                        // [this is just an `Option`](Option)
+                        continue;
+                    }
+                }
+
+                let explicit_link = dest.to_string();
+                let display_link = link_data.resolvable_link.clone()?;
+                let explicit_len = explicit_link.len();
+                let display_len = display_link.len();
+
+                if (explicit_len >= display_len
+                    && &explicit_link[(explicit_len - display_len)..] == display_link)
+                    || (display_len >= explicit_len
+                        && &display_link[(display_len - explicit_len)..] == explicit_link)
+                {
+                    match link_type {
+                        LinkType::Inline | LinkType::ReferenceUnknown => {
+                            check_inline_or_reference_unknown_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                dest.to_string(),
+                                link_data,
+                                if link_type == LinkType::Inline {
+                                    (b'(', b')')
+                                } else {
+                                    (b'[', b']')
+                                },
+                            );
+                        }
+                        LinkType::Reference => {
+                            check_reference_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                &dest,
+                                link_data,
+                            );
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_inline_or_reference_unknown_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: String,
+    link_data: LinkData,
+    (open, close): (u8, u8),
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range, open, close),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_reference_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: &CowStr<'_>,
+    link_data: LinkData,
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range.clone(), b'[', b']'),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+        let def_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_reference_def_range(doc, dest, link_range),
+            &item.attrs,
+        )?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .span_note(def_span, "referenced explicit link target defined here")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+fn find_resolution(resolutions: &DocLinkResMap, path: &str) -> Option<Res<NodeId>> {
+    [Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS]
+        .into_iter()
+        .find_map(|ns| resolutions.get(&(Symbol::intern(path), ns)).copied().flatten())
+}
+
+/// Collects all neccessary data of link.
+fn collect_link_data(offset_iter: &mut OffsetIter<'_, '_>) -> LinkData {
+    let mut resolvable_link = None;
+    let mut resolvable_link_range = None;
+    let mut display_link = String::new();
+
+    while let Some((event, range)) = offset_iter.next() {
+        match event {
+            Event::Text(code) => {
+                let code = code.to_string();
+                display_link.push_str(&code);
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::Code(code) => {
+                let code = code.to_string();
+                display_link.push('`');
+                display_link.push_str(&code);
+                display_link.push('`');
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    LinkData { resolvable_link, resolvable_link_range, display_link }
+}
+
+fn offset_explicit_range(md: &str, link_range: Range<usize>, open: u8, close: u8) -> Range<usize> {
+    let mut open_brace = !0;
+    let mut close_brace = !0;
+    for (i, b) in md.as_bytes()[link_range.clone()].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            close_brace = i;
+            break;
+        }
+    }
+
+    if close_brace < link_range.start || close_brace >= link_range.end {
+        return link_range;
+    }
+
+    let mut nesting = 1;
+
+    for (i, b) in md.as_bytes()[link_range.start..close_brace].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            nesting += 1;
+        }
+        if b == open {
+            nesting -= 1;
+        }
+        if nesting == 0 {
+            open_brace = i;
+            break;
+        }
+    }
+
+    assert!(open_brace != close_brace);
+
+    if open_brace < link_range.start || open_brace >= link_range.end {
+        return link_range;
+    }
+    // do not actually include braces in the span
+    (open_brace + 1)..close_brace
+}
+
+fn offset_reference_def_range(
+    md: &str,
+    dest: &CowStr<'_>,
+    link_range: Range<usize>,
+) -> Range<usize> {
+    // For diagnostics, we want to underline the link's definition but `span` will point at
+    // where the link is used. This is a problem for reference-style links, where the definition
+    // is separate from the usage.
+
+    match dest {
+        // `Borrowed` variant means the string (the link's destination) may come directly from
+        // the markdown text and we can locate the original link destination.
+        // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
+        // so `locate()` can fall back to use `span`.
+        CowStr::Borrowed(s) => {
+            // FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
+            unsafe {
+                let s_start = dest.as_ptr();
+                let s_end = s_start.add(s.len());
+                let md_start = md.as_ptr();
+                let md_end = md_start.add(md.len());
+                if md_start <= s_start && s_end <= md_end {
+                    let start = s_start.offset_from(md_start) as usize;
+                    let end = s_end.offset_from(md_start) as usize;
+                    start..end
+                } else {
+                    link_range
+                }
+            }
+        }
+
+        // For anything else, we can only use the provided range.
+        CowStr::Boxed(_) | CowStr::Inlined(_) => link_range,
+    }
+}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7c3904d6c3ed54e8a413023519b55a536ad44d5
+Subproject 80eca0e58fb2ff52c1e94fc191b55b37ed73e0e
diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile
index c88ec1e6cb3..3bc3d7d1428 100644
--- a/tests/run-make/optimization-remarks-dir-pgo/Makefile
+++ b/tests/run-make/optimization-remarks-dir-pgo/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/rustdoc-ui/lints/inline-doc-link.rs b/tests/rustdoc-ui/lints/inline-doc-link.rs
new file mode 100644
index 00000000000..596f89be3d6
--- /dev/null
+++ b/tests/rustdoc-ui/lints/inline-doc-link.rs
@@ -0,0 +1,13 @@
+// Regression test for <https://github.com/rust-lang/rust/pull/113167>
+
+// check-pass
+#![deny(rustdoc::redundant_explicit_links)]
+
+mod m {
+    pub enum ValueEnum {}
+}
+mod m2 {
+    /// [`ValueEnum`]
+    pub use crate::m::ValueEnum;
+}
+pub use m2::ValueEnum;
diff --git a/tests/rustdoc-ui/lints/no-redundancy.rs b/tests/rustdoc-ui/lints/no-redundancy.rs
new file mode 100644
index 00000000000..e3358728b1b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/no-redundancy.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+/// [Vec][std::vec::Vec#examples] should not warn, because it's not actually redundant!
+/// [This is just an `Option`][std::option::Option] has different display content to actual link!
+pub fn func() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
new file mode 100644
index 00000000000..900234e31e9
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
new file mode 100644
index 00000000000..13feb85e051
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target](dummy_target)
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target)
+//~^ ERROR redundant explicit link target
+///
+/// [Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+///
+/// [usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
new file mode 100644
index 00000000000..34ec9be6646
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
@@ -0,0 +1,1007 @@
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:7:20
+   |
+LL | /// [dummy_target](dummy_target)
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+note: the lint level is defined here
+  --> $DIR/redundant_explicit_links.rs:3:9
+   |
+LL | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:9:22
+   |
+LL | /// [`dummy_target`](dummy_target)
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:12:11
+   |
+LL | /// [Vec](Vec)
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:14:13
+   |
+LL | /// [`Vec`](Vec)
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:16:11
+   |
+LL | /// [Vec](std::vec::Vec)
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:18:13
+   |
+LL | /// [`Vec`](std::vec::Vec)
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:20:21
+   |
+LL | /// [std::vec::Vec](Vec)
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:22:23
+   |
+LL | /// [`std::vec::Vec`](Vec)
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:24:21
+   |
+LL | /// [std::vec::Vec](std::vec::Vec)
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:26:23
+   |
+LL | /// [`std::vec::Vec`](std::vec::Vec)
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:29:13
+   |
+LL | /// [usize](usize)
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:31:15
+   |
+LL | /// [`usize`](usize)
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:33:13
+   |
+LL | /// [usize](std::primitive::usize)
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:35:15
+   |
+LL | /// [`usize`](std::primitive::usize)
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:37:29
+   |
+LL | /// [std::primitive::usize](usize)
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:39:31
+   |
+LL | /// [`std::primitive::usize`](usize)
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:41:29
+   |
+LL | /// [std::primitive::usize](std::primitive::usize)
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:43:31
+   |
+LL | /// [`std::primitive::usize`](std::primitive::usize)
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:46:20
+   |
+LL | /// [dummy_target](dummy_target) TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:48:22
+   |
+LL | /// [`dummy_target`](dummy_target) TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:56:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:58:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:61:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:63:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:65:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:67:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:69:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:71:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:73:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:75:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:78:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:80:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:82:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:84:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:86:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:88:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:90:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:92:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:95:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:97:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:105:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:107:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:110:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:112:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:114:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:116:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:118:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:120:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:122:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:124:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:127:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:129:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:131:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:133:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:135:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:137:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:139:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:141:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:144:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:146:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: aborting due to 60 previous errors
+
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index e99cd1f3d58..e960e9f59e9 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -1,6 +1,7 @@
 #![deny(rustdoc::unescaped_backticks)]
 #![allow(rustdoc::broken_intra_doc_links)]
 #![allow(rustdoc::invalid_html_tags)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 ///
 pub fn empty() {}
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index bf1f18889c4..83822f778d0 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -1,5 +1,5 @@
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:186:70
+  --> $DIR/unescaped_backticks.rs:187:70
    |
 LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
    |                                                                      ^
@@ -19,7 +19,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c
    |                                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:231:13
+  --> $DIR/unescaped_backticks.rs:232:13
    |
 LL |         //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
    |             ^
@@ -34,7 +34,7 @@ LL |         //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:236:13
+  --> $DIR/unescaped_backticks.rs:237:13
    |
 LL |         /// `cfg=...
    |             ^
@@ -49,7 +49,7 @@ LL |         /// \`cfg=...
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:240:42
+  --> $DIR/unescaped_backticks.rs:241:42
    |
 LL |         /// `cfg=... and not `#[cfg_attr]`
    |                                          ^
@@ -64,7 +64,7 @@ LL |         /// `cfg=... and not `#[cfg_attr]\`
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:192:91
+  --> $DIR/unescaped_backticks.rs:193:91
    |
 LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
    |                                                                                           ^
@@ -79,7 +79,7 @@ LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug`
    |                                                                                           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:201:34
+  --> $DIR/unescaped_backticks.rs:202:34
    |
 LL |         /// in `nt_to_tokenstream`
    |                                  ^
@@ -94,7 +94,7 @@ LL |         /// in `nt_to_tokenstream\`
    |                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:207:62
+  --> $DIR/unescaped_backticks.rs:208:62
    |
 LL |     /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
    |                                                              ^
@@ -109,7 +109,7 @@ LL |     /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_inde
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:215:52
+  --> $DIR/unescaped_backticks.rs:216:52
    |
 LL |     /// also avoids the need to import `OpenOptions`.
    |                                                    ^
@@ -124,7 +124,7 @@ LL |     /// also avoids the need to import `OpenOptions\`.
    |                                                    +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:220:46
+  --> $DIR/unescaped_backticks.rs:221:46
    |
 LL |     /// `HybridBitSet`. Has no effect if `row` does not exist.
    |                                              ^
@@ -139,7 +139,7 @@ LL |     /// `HybridBitSet`. Has no effect if `row\` does not exist.
    |                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:246:12
+  --> $DIR/unescaped_backticks.rs:247:12
    |
 LL |     /// RWU`s can get very large, so it uses a more compact representation.
    |            ^
@@ -154,7 +154,7 @@ LL |     /// RWU\`s can get very large, so it uses a more compact representation
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:253:15
+  --> $DIR/unescaped_backticks.rs:254:15
    |
 LL |     /// in `U2`.
    |               ^
@@ -169,7 +169,7 @@ LL |     /// in `U2\`.
    |               +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:270:42
+  --> $DIR/unescaped_backticks.rs:271:42
    |
 LL |     /// because it contains `[type error]`. Yuck! (See issue #29857 for
    |                                          ^
@@ -184,7 +184,7 @@ LL |     /// because it contains `[type error]\`. Yuck! (See issue #29857 for
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:280:53
+  --> $DIR/unescaped_backticks.rs:281:53
    |
 LL |     /// well as the second instance of `A: AutoTrait`) to suppress
    |                                                     ^
@@ -199,7 +199,7 @@ LL |     /// well as the second instance of `A: AutoTrait\`) to suppress
    |                                                     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:290:40
+  --> $DIR/unescaped_backticks.rs:291:40
    |
 LL |     /// `'a` with `'b` and not `'static`. But it will have to do for
    |                                        ^
@@ -211,7 +211,7 @@ LL |     /// `'a` with `'b` and not `'static\`. But it will have to do for
    |                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:299:54
+  --> $DIR/unescaped_backticks.rs:300:54
    |
 LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
    |                                                      ^
@@ -226,7 +226,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.
    |                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:303:13
+  --> $DIR/unescaped_backticks.rs:304:13
    |
 LL | /// or `None` if it isn't.
    |             ^
@@ -238,7 +238,7 @@ LL | /// or `None\` if it isn't.
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:307:14
+  --> $DIR/unescaped_backticks.rs:308:14
    |
 LL | /// `on_event` should be called.
    |              ^
@@ -253,7 +253,7 @@ LL | /// `on_event\` should be called.
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:312:29
+  --> $DIR/unescaped_backticks.rs:313:29
    |
 LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
    |                             ^
@@ -268,7 +268,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m
    |                             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -287,7 +287,7 @@ LL | |     /// level changes.
            to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -304,7 +304,7 @@ LL | |     /// level changes.
            to this: or `None\` if it isn't.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -323,7 +323,7 @@ LL | |     /// level changes.
            to this: `on_event\` should be called.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -342,7 +342,7 @@ LL | |     /// level changes.
            to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:348:56
+  --> $DIR/unescaped_backticks.rs:349:56
    |
 LL |     /// instead and use [`CloneCounterObserver::counter`] to increment.
    |                                                        ^
@@ -354,7 +354,7 @@ LL |     /// instead and use [`CloneCounterObserver::counter\`] to increment.
    |                                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:11:5
+  --> $DIR/unescaped_backticks.rs:12:5
    |
 LL | /// `
    |     ^
@@ -366,7 +366,7 @@ LL | /// \`
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:18:7
+  --> $DIR/unescaped_backticks.rs:19:7
    |
 LL | /// \`
    |       ^
@@ -381,7 +381,7 @@ LL | /// \\`
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:25:6
+  --> $DIR/unescaped_backticks.rs:26:6
    |
 LL | /// [`link1]
    |      ^
@@ -396,7 +396,7 @@ LL | /// [\`link1]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:29:11
+  --> $DIR/unescaped_backticks.rs:30:11
    |
 LL | /// [link2`]
    |           ^
@@ -411,7 +411,7 @@ LL | /// [link2\`]
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:33:6
+  --> $DIR/unescaped_backticks.rs:34:6
    |
 LL | /// [`link_long](link_long)
    |      ^
@@ -426,7 +426,7 @@ LL | /// [\`link_long](link_long)
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:37:6
+  --> $DIR/unescaped_backticks.rs:38:6
    |
 LL | /// [`broken-link]
    |      ^
@@ -441,7 +441,7 @@ LL | /// [\`broken-link]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:44:8
+  --> $DIR/unescaped_backticks.rs:45:8
    |
 LL | /// <x:`>
    |        ^
@@ -456,7 +456,7 @@ LL | /// <x:\`>
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:54:6
+  --> $DIR/unescaped_backticks.rs:55:6
    |
 LL | /// 🦀`🦀
    |       ^
@@ -475,7 +475,7 @@ LL | /// 🦀\`🦀
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:58:5
+  --> $DIR/unescaped_backticks.rs:59:5
    |
 LL | /// `foo(
    |     ^
@@ -490,7 +490,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:64:14
+  --> $DIR/unescaped_backticks.rs:65:14
    |
 LL | /// `foo `bar`
    |              ^
@@ -505,7 +505,7 @@ LL | /// `foo `bar\`
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:70:5
+  --> $DIR/unescaped_backticks.rs:71:5
    |
 LL | /// `foo(
    |     ^
@@ -520,7 +520,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:75:83
+  --> $DIR/unescaped_backticks.rs:76:83
    |
 LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
    |                                                                                   ^
@@ -535,7 +535,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:79:51
+  --> $DIR/unescaped_backticks.rs:80:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
    |                                                   ^
@@ -550,7 +550,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:83:83
+  --> $DIR/unescaped_backticks.rs:84:83
    |
 LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
    |                                                                                   ^
@@ -565,7 +565,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:87:51
+  --> $DIR/unescaped_backticks.rs:88:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -580,7 +580,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:91:83
+  --> $DIR/unescaped_backticks.rs:92:83
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
    |                                                                                   ^
@@ -595,7 +595,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:95:50
+  --> $DIR/unescaped_backticks.rs:96:50
    |
 LL | /// or even to add a number `n` to 42 (add(42, n)`)!
    |                                                  ^
@@ -610,7 +610,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)!
    |                                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:99:74
+  --> $DIR/unescaped_backticks.rs:100:74
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
    |                                                                          ^
@@ -625,7 +625,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`
    |                                                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:103:51
+  --> $DIR/unescaped_backticks.rs:104:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -640,7 +640,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:107:1
+  --> $DIR/unescaped_backticks.rs:108:1
    |
 LL | #[doc = "`"]
    | ^^^^^^^^^^^^
@@ -651,7 +651,7 @@ LL | #[doc = "`"]
            to this: \`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:114:1
+  --> $DIR/unescaped_backticks.rs:115:1
    |
 LL | #[doc = concat!("\\", "`")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -664,7 +664,7 @@ LL | #[doc = concat!("\\", "`")]
            to this: \\`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:118:1
+  --> $DIR/unescaped_backticks.rs:119:1
    |
 LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -677,7 +677,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a
            to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:122:1
+  --> $DIR/unescaped_backticks.rs:123:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -690,7 +690,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a
            to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:126:1
+  --> $DIR/unescaped_backticks.rs:127:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -703,7 +703,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:130:1
+  --> $DIR/unescaped_backticks.rs:131:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -716,7 +716,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:135:5
+  --> $DIR/unescaped_backticks.rs:136:5
    |
 LL | /// `foo
    |     ^
@@ -731,7 +731,7 @@ LL | /// \`foo
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:139:7
+  --> $DIR/unescaped_backticks.rs:140:7
    |
 LL | /// # `(heading
    |       ^
@@ -746,7 +746,7 @@ LL | /// # \`(heading
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:141:17
+  --> $DIR/unescaped_backticks.rs:142:17
    |
 LL | /// ## heading2)`
    |                 ^
@@ -761,7 +761,7 @@ LL | /// ## heading2)\`
    |                 +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:144:11
+  --> $DIR/unescaped_backticks.rs:145:11
    |
 LL | /// multi `(
    |           ^
@@ -776,7 +776,7 @@ LL | /// multi \`(
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:150:10
+  --> $DIR/unescaped_backticks.rs:151:10
    |
 LL | /// para)`(graph
    |          ^
@@ -795,7 +795,7 @@ LL | /// para)\`(graph
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:153:10
+  --> $DIR/unescaped_backticks.rs:154:10
    |
 LL | /// para)`(graph2
    |          ^
@@ -814,7 +814,7 @@ LL | /// para)\`(graph2
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:156:12
+  --> $DIR/unescaped_backticks.rs:157:12
    |
 LL | /// 1. foo)`
    |            ^
@@ -829,7 +829,7 @@ LL | /// 1. foo)\`
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:158:8
+  --> $DIR/unescaped_backticks.rs:159:8
    |
 LL | /// 2. `(bar
    |        ^
@@ -844,7 +844,7 @@ LL | /// 2. \`(bar
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:160:11
+  --> $DIR/unescaped_backticks.rs:161:11
    |
 LL | /// * baz)`
    |           ^
@@ -859,7 +859,7 @@ LL | /// * baz)\`
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:162:7
+  --> $DIR/unescaped_backticks.rs:163:7
    |
 LL | /// * `(quux
    |       ^
@@ -874,7 +874,7 @@ LL | /// * \`(quux
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:165:5
+  --> $DIR/unescaped_backticks.rs:166:5
    |
 LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
    |     ^
@@ -889,7 +889,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:168:62
+  --> $DIR/unescaped_backticks.rs:169:62
    |
 LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
    |                                                              ^
@@ -904,7 +904,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:7
+  --> $DIR/unescaped_backticks.rs:174:7
    |
 LL | /// | `table( | )head` |
    |       ^
@@ -919,7 +919,7 @@ LL | /// | \`table( | )head` |
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:22
+  --> $DIR/unescaped_backticks.rs:174:22
    |
 LL | /// | `table( | )head` |
    |                      ^
@@ -934,7 +934,7 @@ LL | /// | `table( | )head\` |
    |                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:12
+  --> $DIR/unescaped_backticks.rs:178:12
    |
 LL | /// | table`( | )`body |
    |            ^
@@ -949,7 +949,7 @@ LL | /// | table\`( | )`body |
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:18
+  --> $DIR/unescaped_backticks.rs:178:18
    |
 LL | /// | table`( | )`body |
    |                  ^
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
index 43cd59ebd09..aabbb4c4c8f 100644
--- a/tests/rustdoc/description.rs
+++ b/tests/rustdoc/description.rs
@@ -1,4 +1,5 @@
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 //! # Description test crate
 //!
 //! This is the contents of the test crate docstring.
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
index 96e21137b2d..c88a7887f11 100644
--- a/tests/rustdoc/intra-doc/basic.rs
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -1,3 +1,5 @@
+#![allow(rustdoc::redundant_explicit_links)]
+
 // @has basic/index.html
 // @has - '//a/@href' 'struct.ThisType.html'
 // @has - '//a/@title' 'struct basic::ThisType'
diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs
index fbc9fc6a9bc..359f775f97f 100644
--- a/tests/rustdoc/intra-doc/generic-params.rs
+++ b/tests/rustdoc/intra-doc/generic-params.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
index eb1c7a05e54..b8cd478b4df 100644
--- a/tests/rustdoc/intra-doc/issue-108459.rs
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -1,4 +1,5 @@
 #![deny(rustdoc::broken_intra_doc_links)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 pub struct S;
 pub mod char {}
diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs
new file mode 100644
index 00000000000..0cfc44cd09d
--- /dev/null
+++ b/tests/ui/abi/relocation_model_pic.rs
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags: -C relocation-model=pic
+// ignore-emscripten no pic
+// ignore-wasm
+
+#![feature(cfg_relocation_model)]
+
+#[cfg(relocation_model = "pic")]
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
new file mode 100644
index 00000000000..7529014ece2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
@@ -0,0 +1,4 @@
+#[cfg(relocation_model = "pic")] //~ ERROR
+fn _foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
new file mode 100644
index 00000000000..592768a4203
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(relocation_model)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-relocation-model.rs:1:7
+   |
+LL | #[cfg(relocation_model = "pic")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #114929 <https://github.com/rust-lang/rust/issues/114929> for more information
+   = help: add `#![feature(cfg_relocation_model)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs
new file mode 100644
index 00000000000..0483410662b
--- /dev/null
+++ b/tests/ui/inline-const/required-const.rs
@@ -0,0 +1,13 @@
+// build-fail
+// compile-flags: -Zmir-opt-level=3
+#![feature(inline_const)]
+
+fn foo<T>() {
+    if false {
+        const { panic!() } //~ ERROR E0080
+    }
+}
+
+fn main() {
+    foo::<i32>();
+}
diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr
new file mode 100644
index 00000000000..d6948e7acc0
--- /dev/null
+++ b/tests/ui/inline-const/required-const.stderr
@@ -0,0 +1,11 @@
+error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
+  --> $DIR/required-const.rs:7:17
+   |
+LL |         const { panic!() }
+   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs
index 35003a79ad7..48c1f19e777 100644
--- a/tests/ui/macros/macro-interpolation.rs
+++ b/tests/ui/macros/macro-interpolation.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 macro_rules! overly_complicated {
     ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) =>
     ({
@@ -21,12 +19,14 @@ macro_rules! qpath {
 
     (ty, <$type:ty as $trait:ty>::$name:ident) => {
         <$type as $trait>::$name
+        //~^ ERROR expected identifier, found `!`
     };
 }
 
 pub fn main() {
     let _: qpath!(path, <str as ToOwned>::Owned);
     let _: qpath!(ty, <str as ToOwned>::Owned);
+    let _: qpath!(ty, <str as !>::Owned);
 
     assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
                                Some(8), Some(y), y) == 8)
diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr
new file mode 100644
index 00000000000..7ef1fcbbce3
--- /dev/null
+++ b/tests/ui/macros/macro-interpolation.stderr
@@ -0,0 +1,16 @@
+error: expected identifier, found `!`
+  --> $DIR/macro-interpolation.rs:21:19
+   |
+LL |         <$type as $trait>::$name
+   |                   ^^^^^^ expected identifier
+...
+LL |     let _: qpath!(ty, <str as !>::Owned);
+   |            -----------------------------
+   |            |
+   |            this macro call doesn't expand to a type
+   |            in this macro invocation
+   |
+   = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
new file mode 100644
index 00000000000..9cc572c23a1
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
@@ -0,0 +1,14 @@
+#![feature(macro_metavar_expr)]
+
+macro_rules! foo {
+    ( $( $($t:ident),* );* ) => { ${count(t,)} }
+    //~^ ERROR `count` followed by a comma must have an associated
+    //~| ERROR expected expression, found `$`
+}
+
+fn test() {
+    foo!(a, a; b, b);
+}
+
+fn main() {
+}
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
new file mode 100644
index 00000000000..e9317a5c347
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
@@ -0,0 +1,19 @@
+error: `count` followed by a comma must have an associated index indicating its depth
+  --> $DIR/issue-111904.rs:4:37
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                     ^^^^^
+
+error: expected expression, found `$`
+  --> $DIR/issue-111904.rs:4:35
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                   ^ expected expression
+...
+LL |     foo!(a, a; b, b);
+   |     ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr
index 8fafa275b5c..4457b7893d5 100644
--- a/tests/ui/or-patterns/missing-bindings.stderr
+++ b/tests/ui/or-patterns/missing-bindings.stderr
@@ -79,6 +79,14 @@ LL |     let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
    |            |
    |            pattern doesn't bind `a`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:12
+   |
+LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
+   |            ^^^^^^^     - variable not in all patterns
+   |            |
+   |            pattern doesn't bind `c`
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:22
    |
@@ -96,12 +104,12 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 variable not in all patterns
 
 error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:12
+  --> $DIR/missing-bindings.rs:45:33
    |
 LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |            ^^^^^^^     - variable not in all patterns
-   |            |
-   |            pattern doesn't bind `c`
+   |                        -        ^^^^ pattern doesn't bind `c`
+   |                        |
+   |                        variable not in all patterns
 
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:33
@@ -135,14 +143,6 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 |
    |                 variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:33
-   |
-LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |                        -        ^^^^ pattern doesn't bind `c`
-   |                        |
-   |                        variable not in all patterns
-
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:61:29
    |
@@ -185,6 +185,28 @@ LL |                     B(b),
 LL |                 B(_)
    |                 ^^^^ pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:57:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL | /             V2(
+LL | |                 A(
+LL | |                     A(_, a) |
+LL | |                     B(b),
+...  |
+LL | |
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL |               V3(c),
+   |                  - variable not in all patterns
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:76:13
    |
@@ -215,28 +237,6 @@ LL |                       B(b),
 LL |               V3(c),
    |               ^^^^^ pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:57:13
-   |
-LL | /             V1(
-LL | |
-LL | |
-LL | |                 A(
-...  |
-LL | |                 B(Ok(a) | Err(a))
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL | /             V2(
-LL | |                 A(
-LL | |                     A(_, a) |
-LL | |                     B(b),
-...  |
-LL | |
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL |               V3(c),
-   |                  - variable not in all patterns
-
 error: aborting due to 26 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr
index 023db303dd0..42b7281d7b0 100644
--- a/tests/ui/resolve/resolve-inconsistent-names.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-names.stderr
@@ -14,6 +14,15 @@ LL |        a | b => {}
    |        |
    |        pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:19:9
+   |
+LL |         (A, B) | (ref B, c) | (c, A) => ()
+   |         ^^^^^^           -     - variable not in all patterns
+   |         |                |
+   |         |                variable not in all patterns
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `A` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:19:18
    |
@@ -37,15 +46,6 @@ LL |         (A, B) | (ref B, c) | (c, A) => ()
    |             |         variable not in all patterns
    |             variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/resolve-inconsistent-names.rs:19:9
-   |
-LL |         (A, B) | (ref B, c) | (c, A) => ()
-   |         ^^^^^^           -     - variable not in all patterns
-   |         |                |
-   |         |                variable not in all patterns
-   |         pattern doesn't bind `c`
-
 error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|`
   --> $DIR/resolve-inconsistent-names.rs:19:23
    |
diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr
index 25c35fd5479..81211b20a01 100644
--- a/tests/ui/span/issue-39698.stderr
+++ b/tests/ui/span/issue-39698.stderr
@@ -1,3 +1,13 @@
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
+   |         |             |                   |
+   |         |             |                   variable not in all patterns
+   |         |             pattern doesn't bind `c`
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/issue-39698.rs:10:37
    |
@@ -28,16 +38,6 @@ LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
    |         |                      variable not in all patterns
    |         pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/issue-39698.rs:10:9
-   |
-LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
-   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
-   |         |             |                   |
-   |         |             |                   variable not in all patterns
-   |         |             pattern doesn't bind `c`
-   |         pattern doesn't bind `c`
-
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
new file mode 100644
index 00000000000..b0b9b6bbd20
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// A minimization of an ambiguity when using typenum. See
+// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
+// for more details.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
+where
+    Ul: WithAssoc<Ur>,
+{
+    type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+// normalize self type to `Wrapper<Leaf>`
+//   This succeeds, HOWEVER, instantiating the query response previously
+//   incremented the universe index counter.
+// equate impl headers:
+//      <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
+//      <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
+// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+// add where bounds:
+// ~> Leaf: WithAssoc<?3t>
+// equate with assoc type:
+//      ?0t
+//      <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
+// ~> AliasRelate(
+//      <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
+// it after incrementing the universe index while normalizing the self type.
+//
+// evaluate_added_goals_and_make_query_response:
+//    AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+//      YES, constrains ?3t to Leaf
+//    AliasRelate(
+//      <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
+// results in ambiguity.
+fn main() {
+    bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
new file mode 100644
index 00000000000..94d645a9859
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
@@ -0,0 +1,75 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: trait-system-refactor-initiative#60
+
+// Generalizing a projection containing an inference variable
+// which cannot be named by the `root_vid` can result in ambiguity.
+//
+// Because we do not decrement the universe index when exiting a forall,
+// this can cause unexpected failures.
+//
+// See generalize-proj-new-universe-index-1.rs for more details.
+
+// For this reproduction we need:
+// - an inference variable with a lower universe
+// - enter a binder to increment the current universe
+// - create a new inference variable which is constrained by proving a goal
+// - equate a projection containing the new variable with the first variable
+// - generalization creates yet another inference variable which is then
+//   part of an alias-relate, resulting this to fail with ambiguity.
+//
+// Because we need to enter the binder in-between the creation of the first
+// and second inference variable, this is easiest via
+// `assemble_candidates_after_normalizing_self_ty` because eagerly call
+// `try_evaluate_added_goals` there before creating the inference variables
+// for the impl parameters.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+// By adding an higher ranked bound to the impl we currently
+// propagate this bound to the caller, forcing us to create a new
+// universe.
+trait IdHigherRankedBound {
+    type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> IdHigherRankedBound for T
+where
+    for<'a> T: 'a,
+{
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+struct Rigid;
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+
+impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
+where
+    Leaf: WithAssoc<Ur>,
+{
+    type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+fn main() {
+    bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
new file mode 100644
index 00000000000..9a8060133b8
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/generalize-proj-new-universe-index-2.rs:74:5
+   |
+LL |     bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index d48d9b89d1d..b612005fcb0 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
   --> $DIR/type-checking-test-1.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-1.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
-   |
-   = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index 7c7beec0809..afea8521e87 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) {
 fn test_unknown_version(x: &dyn Foo) {
     let _ = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
 }
 
 fn test_infer_version(x: &dyn Foo) {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
index 36b11dffdb1..b024b27750b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo<u32>) {
 fn test_specific3(x: &dyn Foo<i32>) {
     let _ = x as &dyn Bar<u32>; // Error
                                 //~^ ERROR non-primitive cast
-                                //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
 }
 
 fn test_infer_arg(x: &dyn Foo<u32>) {
     let a = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
     let _ = a.bar();
 }
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index 856303ef4dd..3e59b9d3363 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
   --> $DIR/type-checking-test-2.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^^^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<u32>; // Error
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
-   |
-   = note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>`
+   |             ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-2.rs:25:13
+  --> $DIR/type-checking-test-2.rs:24:13
    |
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let a = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:25:13
-   |
-LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
-   |
-   = note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/triagebot.toml b/triagebot.toml
index 2c71b650f68..a06195cc334 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -489,7 +489,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789", "oli-obk"]
+users_on_vacation = ["jyn514", "clubby789", "oli-obk"]
 
 [assign.adhoc_groups]
 compiler-team = [