about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-02 12:57:06 +0000
committerbors <bors@rust-lang.org>2021-03-02 12:57:06 +0000
commit67342b830ebeca05ebafc09d8c7ed71b2ad821e1 (patch)
tree4f22db53302ec9f0e7961f6ae92c28f79e87f5df
parentedeee915b1c52f97411e57ef6b1a8bd46548a37a (diff)
parent97f9b186ae6fbd03d9bf4892ec0320f17c623b6b (diff)
downloadrust-67342b830ebeca05ebafc09d8c7ed71b2ad821e1.tar.gz
rust-67342b830ebeca05ebafc09d8c7ed71b2ad821e1.zip
Auto merge of #82698 - JohnTitor:rollup-htd533c, r=JohnTitor
Rollup of 10 pull requests

Successful merges:

 - #80189 (Convert primitives in the standard library to intra-doc links)
 - #80874 (Update intra-doc link documentation to match the implementation)
 - #82376 (Add option to enable MIR inlining independently of mir-opt-level)
 - #82516 (Add incomplete feature gate for inherent associate types.)
 - #82579 (Fix turbofish recovery with multiple generic args)
 - #82593 (Teach rustdoc how to display WASI.)
 - #82597 (Get TyCtxt from self instead of passing as argument in AutoTraitFinder)
 - #82627 (Erase late bound regions to avoid ICE)
 - #82661 (:arrow_up: rust-analyzer)
 - #82691 (Update books)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0202.md15
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs5
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs36
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs3
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs12
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs3
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs17
-rw-r--r--compiler/rustc_typeck/src/errors.rs7
-rw-r--r--library/alloc/src/lib.rs5
-rw-r--r--library/alloc/src/slice.rs22
-rw-r--r--library/alloc/src/str.rs2
-rw-r--r--library/alloc/src/string.rs2
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/src/alloc/layout.rs1
-rw-r--r--library/core/src/array/iter.rs2
-rw-r--r--library/core/src/array/mod.rs2
-rw-r--r--library/core/src/char/mod.rs3
-rw-r--r--library/core/src/convert/mod.rs3
-rw-r--r--library/core/src/ffi.rs1
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/mem/maybe_uninit.rs2
-rw-r--r--library/core/src/mem/mod.rs3
-rw-r--r--library/core/src/num/f32.rs28
-rw-r--r--library/core/src/num/f64.rs30
-rw-r--r--library/core/src/num/shells/i128.rs2
-rw-r--r--library/core/src/num/shells/i16.rs2
-rw-r--r--library/core/src/num/shells/i32.rs2
-rw-r--r--library/core/src/num/shells/i64.rs2
-rw-r--r--library/core/src/num/shells/i8.rs2
-rw-r--r--library/core/src/num/shells/int_macros.rs6
-rw-r--r--library/core/src/num/shells/isize.rs2
-rw-r--r--library/core/src/num/shells/u128.rs2
-rw-r--r--library/core/src/num/shells/u16.rs2
-rw-r--r--library/core/src/num/shells/u32.rs2
-rw-r--r--library/core/src/num/shells/u64.rs2
-rw-r--r--library/core/src/num/shells/u8.rs2
-rw-r--r--library/core/src/num/shells/usize.rs2
-rw-r--r--library/core/src/ops/function.rs6
-rw-r--r--library/core/src/ptr/const_ptr.rs2
-rw-r--r--library/core/src/ptr/mod.rs4
-rw-r--r--library/core/src/ptr/mut_ptr.rs4
-rw-r--r--library/core/src/ptr/non_null.rs2
-rw-r--r--library/core/src/result.rs3
-rw-r--r--library/core/src/slice/index.rs4
-rw-r--r--library/core/src/slice/iter.rs104
-rw-r--r--library/core/src/slice/raw.rs2
-rw-r--r--library/core/src/str/converts.rs4
-rw-r--r--library/core/src/str/traits.rs4
-rw-r--r--library/core/src/sync/atomic.rs60
-rw-r--r--library/std/src/ffi/c_str.rs6
-rw-r--r--library/std/src/io/mod.rs3
-rw-r--r--library/std/src/keyword_docs.rs8
-rw-r--r--library/std/src/lib.rs12
-rw-r--r--library/std/src/primitive_docs.rs6
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustdoc/src/linking-to-items-by-name.md75
-rw-r--r--src/librustdoc/clean/auto_trait.rs27
-rw-r--r--src/librustdoc/clean/cfg.rs1
-rw-r--r--src/librustdoc/clean/cfg/tests.rs4
-rw-r--r--src/test/rustdoc/doc-cfg.rs32
-rw-r--r--src/test/ui/assoc-inherent.rs17
-rw-r--r--src/test/ui/assoc-inherent.stderr20
-rw-r--r--src/test/ui/feature-gates/feature-gate-inherent_associated_types.rs10
-rw-r--r--src/test/ui/feature-gates/feature-gate-inherent_associated_types.stderr12
-rw-r--r--src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs8
-rw-r--r--src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr22
-rw-r--r--src/test/ui/return/issue-82612-return-mutable-reference.rs24
-rw-r--r--src/test/ui/return/issue-82612-return-mutable-reference.stderr28
-rw-r--r--src/test/ui/suggestions/issue-82566-1.rs21
-rw-r--r--src/test/ui/suggestions/issue-82566-1.stderr35
-rw-r--r--src/test/ui/suggestions/issue-82566-2.rs31
-rw-r--r--src/test/ui/suggestions/issue-82566-2.stderr35
m---------src/tools/rust-analyzer32
85 files changed, 608 insertions, 328 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index c4330694504..4b529734328 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -103,7 +103,6 @@ E0198: include_str!("./error_codes/E0198.md"),
 E0199: include_str!("./error_codes/E0199.md"),
 E0200: include_str!("./error_codes/E0200.md"),
 E0201: include_str!("./error_codes/E0201.md"),
-E0202: include_str!("./error_codes/E0202.md"),
 E0203: include_str!("./error_codes/E0203.md"),
 E0204: include_str!("./error_codes/E0204.md"),
 E0205: include_str!("./error_codes/E0205.md"),
diff --git a/compiler/rustc_error_codes/src/error_codes/E0202.md b/compiler/rustc_error_codes/src/error_codes/E0202.md
deleted file mode 100644
index afc61ec2e48..00000000000
--- a/compiler/rustc_error_codes/src/error_codes/E0202.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Inherent associated types were part of [RFC 195] but are not yet implemented.
-See [the tracking issue][iss8995] for the status of this implementation.
-
-Erroneous code example:
-
-```compile_fail,E0202
-struct Foo;
-
-impl Foo {
-    type Bar = isize; // error!
-}
-```
-
-[RFC 195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md
-[iss8995]: https://github.com/rust-lang/rust/issues/8995
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 6960b735f33..8ee995a59d8 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -641,6 +641,9 @@ declare_features! (
     /// Allows `pub` on `macro_rules` items.
     (active, pub_macro_rules, "1.52.0", Some(78855), None),
 
+    /// Allows associated types in inherent impls.
+    (active, inherent_associated_types, "1.52.0", Some(8995), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -666,6 +669,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::unsized_locals,
     sym::capture_disjoint_fields,
     sym::const_generics_defaults,
+    sym::inherent_associated_types,
 ];
 
 /// Some features are not allowed to be used together at the same time, if
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index a2e96146568..9a11b534887 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -557,8 +557,9 @@ fn test_debugging_options_tracking_hash() {
     tracked!(function_sections, Some(false));
     tracked!(human_readable_cgu_names, true);
     tracked!(inline_in_all_cgus, Some(true));
-    tracked!(inline_mir_threshold, 123);
-    tracked!(inline_mir_hint_threshold, 123);
+    tracked!(inline_mir, Some(true));
+    tracked!(inline_mir_threshold, Some(123));
+    tracked!(inline_mir_hint_threshold, Some(123));
     tracked!(insert_sideeffect, true);
     tracked!(instrument_coverage, true);
     tracked!(instrument_mcount, true);
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 16279040a1c..16410175bd2 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -37,21 +37,27 @@ struct CallSite<'tcx> {
     source_info: SourceInfo,
 }
 
+/// Returns true if MIR inlining is enabled in the current compilation session.
+crate fn is_enabled(tcx: TyCtxt<'_>) -> bool {
+    if tcx.sess.opts.debugging_opts.instrument_coverage {
+        // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
+        // counters can be invalidated, such as by merging coverage counter statements from
+        // a pre-inlined function into a different function. This kind of change is invalid,
+        // so inlining must be skipped. Note: This check is performed here so inlining can
+        // be disabled without preventing other optimizations (regardless of `mir_opt_level`).
+        return false;
+    }
+
+    if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir {
+        return enabled;
+    }
+
+    tcx.sess.opts.debugging_opts.mir_opt_level >= 2
+}
+
 impl<'tcx> MirPass<'tcx> for Inline {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        // If you change this optimization level, also change the level in
-        // `mir_drops_elaborated_and_const_checked` for the call to `mir_inliner_callees`.
-        // Otherwise you will get an ICE about stolen MIR.
-        if tcx.sess.opts.debugging_opts.mir_opt_level < 2 {
-            return;
-        }
-
-        if tcx.sess.opts.debugging_opts.instrument_coverage {
-            // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
-            // counters can be invalidated, such as by merging coverage counter statements from
-            // a pre-inlined function into a different function. This kind of change is invalid,
-            // so inlining must be skipped. Note: This check is performed here so inlining can
-            // be disabled without preventing other optimizations (regardless of `mir_opt_level`).
+        if !is_enabled(tcx) {
             return;
         }
 
@@ -343,9 +349,9 @@ impl Inliner<'tcx> {
         let tcx = self.tcx;
 
         let mut threshold = if callee_attrs.requests_inline() {
-            self.tcx.sess.opts.debugging_opts.inline_mir_hint_threshold
+            self.tcx.sess.opts.debugging_opts.inline_mir_hint_threshold.unwrap_or(100)
         } else {
-            self.tcx.sess.opts.debugging_opts.inline_mir_threshold
+            self.tcx.sess.opts.debugging_opts.inline_mir_threshold.unwrap_or(50)
         };
 
         // Give a bonus functions with a small number of blocks,
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index cc6b2ff5fd4..9cb8abf75c4 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -430,8 +430,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
         let def = ty::WithOptConstParam::unknown(did);
 
         // Do not compute the mir call graph without said call graph actually being used.
-        // Keep this in sync with the mir inliner's optimization level.
-        if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+        if inline::is_enabled(tcx) {
             let _ = tcx.mir_inliner_callees(ty::InstanceDef::Item(def));
         }
     }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 5b4939b7407..f4ab3260d1a 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -662,7 +662,7 @@ impl<'a> Parser<'a> {
                     let x = self.parse_seq_to_before_end(
                         &token::Gt,
                         SeqSep::trailing_allowed(token::Comma),
-                        |p| p.parse_ty(),
+                        |p| p.parse_generic_arg(),
                     );
                     match x {
                         Ok((_, _, false)) => {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 6b7059eecf4..9cc600d9ede 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -545,7 +545,7 @@ impl<'a> Parser<'a> {
 
     /// Parse a generic argument in a path segment.
     /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
-    fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
+    pub(super) fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
         let start = self.token.span;
         let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
             // Parse lifetime argument.
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 9553f5d09e8..8f03bfd4c3a 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -360,12 +360,20 @@ impl<'a> Parser<'a> {
             }
             Err(err) => return Err(err),
         };
+
         let ty = if self.eat(&token::Semi) {
-            TyKind::Array(elt_ty, self.parse_anon_const_expr()?)
+            let mut length = self.parse_anon_const_expr()?;
+            if let Err(e) = self.expect(&token::CloseDelim(token::Bracket)) {
+                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
+                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
+                self.expect(&token::CloseDelim(token::Bracket))?;
+            }
+            TyKind::Array(elt_ty, length)
         } else {
+            self.expect(&token::CloseDelim(token::Bracket))?;
             TyKind::Slice(elt_ty)
         };
-        self.expect(&token::CloseDelim(token::Bracket))?;
+
         Ok(ty)
     }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d439753d042..e2b6b1dc243 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -957,9 +957,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         (default: no)"),
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify incr. comp. hashes of green query instances (default: no)"),
-    inline_mir_threshold: usize = (50, parse_uint, [TRACKED],
+    inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "enable MIR inlining (default: no)"),
+    inline_mir_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
         "a default MIR inlining threshold (default: 50)"),
-    inline_mir_hint_threshold: usize = (100, parse_uint, [TRACKED],
+    inline_mir_hint_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
         "inlining threshold for functions with inline hint (default: 100)"),
     inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "control whether `#[inline]` functions are in all CGUs"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f87267da9f6..27bb45bcc85 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -634,6 +634,7 @@ symbols! {
         index_mut,
         infer_outlives_requirements,
         infer_static_outlives_requirements,
+        inherent_associated_types,
         inlateout,
         inline,
         inline_const,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 97cc258d425..6510c9464e1 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -77,7 +77,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         ty: Ty<'tcx>,
         orig_env: ty::ParamEnv<'tcx>,
         trait_did: DefId,
-        mut auto_trait_callback: impl FnMut(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A,
+        mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A,
     ) -> AutoTraitResult<A> {
         let tcx = self.tcx;
 
@@ -211,7 +211,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
 
             let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
 
-            AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info))
+            AutoTraitResult::PositiveImpl(auto_trait_callback(info))
         })
     }
 }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 1f50ad5779e..9f15993e471 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -11,7 +11,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, ItemKind, Node};
 use rustc_infer::infer;
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Binder, Ty};
 use rustc_span::symbol::kw;
 
 use std::iter;
@@ -487,6 +487,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let found = self.resolve_vars_with_obligations(found);
         if let hir::FnRetTy::Return(ty) = fn_decl.output {
             let ty = AstConv::ast_ty_to_ty(self, ty);
+            let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty));
             let ty = self.normalize_associated_types_in(expr.span, ty);
             if self.can_coerce(found, ty) {
                 err.multipart_suggestion(
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index a2aa3b308ec..e6f771cfd53 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -1,4 +1,3 @@
-use crate::errors::AssocTypeOnInherentImpl;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, ErrorReported, StashKey};
 use rustc_hir as hir;
@@ -294,7 +293,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
             ImplItemKind::TyAlias(ref ty) => {
                 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
-                    report_assoc_ty_on_inherent_impl(tcx, item.span);
+                    check_feature_inherent_assoc_ty(tcx, item.span);
                 }
 
                 icx.to_ty(ty)
@@ -746,6 +745,16 @@ fn infer_placeholder_type(
     })
 }
 
-fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
-    tcx.sess.emit_err(AssocTypeOnInherentImpl { span });
+fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
+    if !tcx.features().inherent_associated_types {
+        use rustc_session::parse::feature_err;
+        use rustc_span::symbol::sym;
+        feature_err(
+            &tcx.sess.parse_sess,
+            sym::inherent_associated_types,
+            span,
+            "inherent associated types are unstable",
+        )
+        .emit();
+    }
 }
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index a769e48d2ca..5068242692a 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -83,13 +83,6 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(SessionDiagnostic)]
-#[error = "E0202"]
-pub struct AssocTypeOnInherentImpl {
-    #[message = "associated types are not yet supported in inherent impls (see #8995)"]
-    pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
 #[error = "E0203"]
 pub struct MultipleRelaxedDefaultBounds {
     #[message = "type parameter has more than one relaxed default bound, only one is supported"]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 7cce6ae3400..e702e02d2e4 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -104,6 +104,11 @@
 #![feature(fundamental)]
 #![feature(inplace_iteration)]
 #![feature(int_bits_const)]
+// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
+// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
+// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
+// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
+#![feature(intra_doc_pointers)]
 #![feature(lang_items)]
 #![feature(layout_for_ptr)]
 #![feature(maybe_uninit_ref)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 9924f60ff77..0c911cea1bb 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -1,6 +1,6 @@
 //! A dynamically-sized view into a contiguous sequence, `[T]`.
 //!
-//! *[See also the slice primitive type](../../std/primitive.slice.html).*
+//! *[See also the slice primitive type](slice).*
 //!
 //! Slices are a view into a block of memory represented as a pointer and a
 //! length.
@@ -71,12 +71,12 @@
 //!   [`.chunks`], [`.windows`] and more.
 //!
 //! [`Hash`]: core::hash::Hash
-//! [`.iter`]: ../../std/primitive.slice.html#method.iter
-//! [`.iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
-//! [`.split`]: ../../std/primitive.slice.html#method.split
-//! [`.splitn`]: ../../std/primitive.slice.html#method.splitn
-//! [`.chunks`]: ../../std/primitive.slice.html#method.chunks
-//! [`.windows`]: ../../std/primitive.slice.html#method.windows
+//! [`.iter`]: slice::iter
+//! [`.iter_mut`]: slice::iter_mut
+//! [`.split`]: slice::split
+//! [`.splitn`]: slice::splitn
+//! [`.chunks`]: slice::chunks
+//! [`.windows`]: slice::windows
 #![stable(feature = "rust1", since = "1.0.0")]
 // Many of the usings in this module are only used in the test configuration.
 // It's cleaner to just turn off the unused_imports warning than to fix them.
@@ -673,7 +673,7 @@ impl [u8] {
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat).
+/// Helper trait for [`[T]::concat`](slice::concat).
 ///
 /// Note: the `Item` type parameter is not used in this trait,
 /// but it allows impls to be more generic.
@@ -708,19 +708,19 @@ pub trait Concat<Item: ?Sized> {
     /// The resulting type after concatenation
     type Output;
 
-    /// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat)
+    /// Implementation of [`[T]::concat`](slice::concat)
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
     fn concat(slice: &Self) -> Self::Output;
 }
 
-/// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join)
+/// Helper trait for [`[T]::join`](slice::join)
 #[unstable(feature = "slice_concat_trait", issue = "27747")]
 pub trait Join<Separator> {
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
     /// The resulting type after concatenation
     type Output;
 
-    /// Implementation of [`[T]::join`](../../std/primitive.slice.html#method.join)
+    /// Implementation of [`[T]::join`](slice::join)
     #[unstable(feature = "slice_concat_trait", issue = "27747")]
     fn join(slice: &Self, sep: Separator) -> Self::Output;
 }
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 70e0c7dba5e..8c64bc08012 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -1,6 +1,6 @@
 //! Unicode string slices.
 //!
-//! *[See also the `str` primitive type](../../std/primitive.str.html).*
+//! *[See also the `str` primitive type](str).*
 //!
 //! The `&str` type is one of the two main string types, the other being `String`.
 //! Unlike its `String` counterpart, its contents are borrowed.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 6fb3fcbb63b..b567d0a2fe2 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -495,7 +495,7 @@ impl String {
     /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: �
     ///
-    /// [byteslice]: ../../std/primitive.slice.html
+    /// [byteslice]: prim@slice
     /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
     ///
     /// If you are sure that the byte slice is valid UTF-8, and you don't want
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b1b26194283..01a3f9f9b59 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -216,7 +216,7 @@ mod spec_extend;
 /// # Slicing
 ///
 /// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
-/// To get a [slice], use [`&`]. Example:
+/// To get a [slice][prim@slice], use [`&`]. Example:
 ///
 /// ```
 /// fn read_slice(slice: &[usize]) {
@@ -369,8 +369,6 @@ mod spec_extend;
 /// [`reserve`]: Vec::reserve
 /// [`MaybeUninit`]: core::mem::MaybeUninit
 /// [owned slice]: Box
-/// [slice]: ../../std/primitive.slice.html
-/// [`&`]: ../../std/primitive.reference.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]
 pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
@@ -2517,7 +2515,7 @@ impl<T, A: Allocator> Vec<T, A> {
 /// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to
 /// append the entire slice at once.
 ///
-/// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice
+/// [`copy_from_slice`]: slice::copy_from_slice
 #[stable(feature = "extend_ref", since = "1.2.0")]
 impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec<T, A> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 9dc3f05dae5..8b95b70396b 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -164,7 +164,6 @@ impl Layout {
     ///       [`Layout::for_value`] on a reference to an extern type tail.
     ///     - otherwise, it is conservatively not allowed to call this function.
     ///
-    /// [slice]: ../../std/primitive.slice.html
     /// [trait object]: ../../book/ch17-02-trait-objects.html
     /// [extern type]: ../../unstable-book/language-features/extern-types.html
     #[unstable(feature = "layout_for_ptr", issue = "69835")]
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 535291471b1..4472fba26b9 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -9,8 +9,6 @@ use crate::{
 };
 
 /// A by-value [array] iterator.
-///
-/// [array]: ../../std/primitive.array.html
 #[stable(feature = "array_value_iter", since = "1.51.0")]
 pub struct IntoIter<T, const N: usize> {
     /// This is the array we are iterating over.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index d4fd7545d9b..20251edf6f7 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -2,7 +2,7 @@
 //! up to a certain length. Eventually, we should be able to generalize
 //! to all lengths.
 //!
-//! *[See also the array primitive type](../../std/primitive.array.html).*
+//! *[See also the array primitive type](array).*
 
 #![stable(feature = "core_array", since = "1.36.0")]
 
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 7a68de5e6af..788fafa0adc 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -9,8 +9,7 @@
 //! [Unicode code point]: http://www.unicode.org/glossary/#code_point
 //!
 //! This module exists for technical reasons, the primary documentation for
-//! `char` is directly on [the `char` primitive type](../../std/primitive.char.html)
-//! itself.
+//! `char` is directly on [the `char` primitive type][char] itself.
 //!
 //! This module is the home of the iterator implementations for the iterators
 //! implemented on `char`, as well as some useful constants and conversion
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index e1b19e4b73c..65af8508a68 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -463,7 +463,6 @@ pub trait TryInto<T>: Sized {
 /// ```
 ///
 /// [`try_from`]: TryFrom::try_from
-/// [`!`]: ../../std/primitive.never.html
 #[rustc_diagnostic_item = "try_from_trait"]
 #[stable(feature = "try_from", since = "1.34.0")]
 pub trait TryFrom<T>: Sized {
@@ -673,8 +672,6 @@ impl AsMut<str> for str {
 /// However when `Infallible` becomes an alias for the never type,
 /// the two `impl`s will start to overlap
 /// and therefore will be disallowed by the language’s trait coherence rules.
-///
-/// [never]: ../../std/primitive.never.html
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[derive(Copy)]
 pub enum Infallible {}
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index 4b303acfd3b..9302baa823b 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -21,7 +21,6 @@ use crate::ops::{Deref, DerefMut};
 /// compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
 /// this definition. For more information, please read [RFC 2521].
 ///
-/// [pointer]: ../../std/primitive.pointer.html
 /// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
 /// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
 // N.B., for LLVM to recognize the void pointer type and by extension
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 5274262ded2..afea8aa8ff2 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1093,8 +1093,7 @@ extern "rust-intrinsic" {
     /// bounds or arithmetic overflow occurs then any further use of the
     /// returned value will result in undefined behavior.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::pointer::offset`](../../std/primitive.pointer.html#method.offset).
+    /// The stabilized version of this intrinsic is [`pointer::offset`].
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
@@ -1111,8 +1110,7 @@ extern "rust-intrinsic" {
     /// object, and it wraps with two's complement arithmetic. The resulting
     /// value is not necessarily valid to be used to actually access memory.
     ///
-    /// The stabilized version of this intrinsic is
-    /// [`std::pointer::wrapping_offset`](../../std/primitive.pointer.html#method.wrapping_offset).
+    /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 64e2a951309..c50d9507a17 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -114,7 +114,7 @@
 #![feature(extended_key_value_attributes)]
 #![feature(extern_types)]
 #![feature(fundamental)]
-#![cfg_attr(not(bootstrap), feature(intra_doc_pointers))]
+#![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 3760f5c4794..26314213ff7 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -976,7 +976,6 @@ impl<T> MaybeUninit<T> {
     /// ```
     ///
     /// [`write_slice_cloned`]: MaybeUninit::write_slice_cloned
-    /// [`slice::copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice
     #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
     pub fn write_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
     where
@@ -1037,7 +1036,6 @@ impl<T> MaybeUninit<T> {
     /// ```
     ///
     /// [`write_slice`]: MaybeUninit::write_slice
-    /// [`slice::clone_from_slice`]: ../../std/primitive.slice.html#method.clone_from_slice
     #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
     pub fn write_slice_cloned<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
     where
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 87890f92759..afce6e55b8f 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -308,7 +308,6 @@ pub const fn size_of<T>() -> usize {
 /// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object],
 /// then `size_of_val` can be used to get the dynamically-known size.
 ///
-/// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 ///
 /// # Examples
@@ -355,7 +354,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 ///       [`size_of_val`] on a reference to a type with an extern type tail.
 ///     - otherwise, it is conservatively not allowed to call this function.
 ///
-/// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
 ///
@@ -494,7 +492,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 ///       [`align_of_val`] on a reference to a type with an extern type tail.
 ///     - otherwise, it is conservatively not allowed to call this function.
 ///
-/// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
 ///
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 80cfb5a0e3a..690247bc96d 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1,6 +1,6 @@
 //! Constants specific to the `f32` single-precision floating point type.
 //!
-//! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
+//! *[See also the `f32` primitive type][f32].*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
@@ -35,7 +35,7 @@ use crate::num::FpCategory;
 pub const RADIX: u32 = f32::RADIX;
 
 /// Number of significant digits in base 2.
-/// Use [`f32::MANTISSA_DIGITS`](../../std/primitive.f32.html#associatedconstant.MANTISSA_DIGITS) instead.
+/// Use [`f32::MANTISSA_DIGITS`] instead.
 ///
 /// # Examples
 ///
@@ -55,7 +55,7 @@ pub const RADIX: u32 = f32::RADIX;
 pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS;
 
 /// Approximate number of significant digits in base 10.
-/// Use [`f32::DIGITS`](../../std/primitive.f32.html#associatedconstant.DIGITS) instead.
+/// Use [`f32::DIGITS`] instead.
 ///
 /// # Examples
 ///
@@ -72,7 +72,7 @@ pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS;
 pub const DIGITS: u32 = f32::DIGITS;
 
 /// [Machine epsilon] value for `f32`.
-/// Use [`f32::EPSILON`](../../std/primitive.f32.html#associatedconstant.EPSILON) instead.
+/// Use [`f32::EPSILON`] instead.
 ///
 /// This is the difference between `1.0` and the next larger representable number.
 ///
@@ -96,7 +96,7 @@ pub const DIGITS: u32 = f32::DIGITS;
 pub const EPSILON: f32 = f32::EPSILON;
 
 /// Smallest finite `f32` value.
-/// Use [`f32::MIN`](../../std/primitive.f32.html#associatedconstant.MIN) instead.
+/// Use [`f32::MIN`] instead.
 ///
 /// # Examples
 ///
@@ -113,7 +113,7 @@ pub const EPSILON: f32 = f32::EPSILON;
 pub const MIN: f32 = f32::MIN;
 
 /// Smallest positive normal `f32` value.
-/// Use [`f32::MIN_POSITIVE`](../../std/primitive.f32.html#associatedconstant.MIN_POSITIVE) instead.
+/// Use [`f32::MIN_POSITIVE`] instead.
 ///
 /// # Examples
 ///
@@ -133,7 +133,7 @@ pub const MIN: f32 = f32::MIN;
 pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE;
 
 /// Largest finite `f32` value.
-/// Use [`f32::MAX`](../../std/primitive.f32.html#associatedconstant.MAX) instead.
+/// Use [`f32::MAX`] instead.
 ///
 /// # Examples
 ///
@@ -150,7 +150,7 @@ pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE;
 pub const MAX: f32 = f32::MAX;
 
 /// One greater than the minimum possible normal power of 2 exponent.
-/// Use [`f32::MIN_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_EXP) instead.
+/// Use [`f32::MIN_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -170,7 +170,7 @@ pub const MAX: f32 = f32::MAX;
 pub const MIN_EXP: i32 = f32::MIN_EXP;
 
 /// Maximum possible power of 2 exponent.
-/// Use [`f32::MAX_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_EXP) instead.
+/// Use [`f32::MAX_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -190,7 +190,7 @@ pub const MIN_EXP: i32 = f32::MIN_EXP;
 pub const MAX_EXP: i32 = f32::MAX_EXP;
 
 /// Minimum possible normal power of 10 exponent.
-/// Use [`f32::MIN_10_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_10_EXP) instead.
+/// Use [`f32::MIN_10_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -210,7 +210,7 @@ pub const MAX_EXP: i32 = f32::MAX_EXP;
 pub const MIN_10_EXP: i32 = f32::MIN_10_EXP;
 
 /// Maximum possible power of 10 exponent.
-/// Use [`f32::MAX_10_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_10_EXP) instead.
+/// Use [`f32::MAX_10_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -230,7 +230,7 @@ pub const MIN_10_EXP: i32 = f32::MIN_10_EXP;
 pub const MAX_10_EXP: i32 = f32::MAX_10_EXP;
 
 /// Not a Number (NaN).
-/// Use [`f32::NAN`](../../std/primitive.f32.html#associatedconstant.NAN) instead.
+/// Use [`f32::NAN`] instead.
 ///
 /// # Examples
 ///
@@ -247,7 +247,7 @@ pub const MAX_10_EXP: i32 = f32::MAX_10_EXP;
 pub const NAN: f32 = f32::NAN;
 
 /// Infinity (∞).
-/// Use [`f32::INFINITY`](../../std/primitive.f32.html#associatedconstant.INFINITY) instead.
+/// Use [`f32::INFINITY`] instead.
 ///
 /// # Examples
 ///
@@ -267,7 +267,7 @@ pub const NAN: f32 = f32::NAN;
 pub const INFINITY: f32 = f32::INFINITY;
 
 /// Negative infinity (−∞).
-/// Use [`f32::NEG_INFINITY`](../../std/primitive.f32.html#associatedconstant.NEG_INFINITY) instead.
+/// Use [`f32::NEG_INFINITY`] instead.
 ///
 /// # Examples
 ///
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index e365e1b21df..6d3737224c0 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1,6 +1,6 @@
 //! Constants specific to the `f64` double-precision floating point type.
 //!
-//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
+//! *[See also the `f64` primitive type][f64].*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
@@ -18,7 +18,7 @@ use crate::mem;
 use crate::num::FpCategory;
 
 /// The radix or base of the internal representation of `f64`.
-/// Use [`f64::RADIX`](../../std/primitive.f64.html#associatedconstant.RADIX) instead.
+/// Use [`f64::RADIX`] instead.
 ///
 /// # Examples
 ///
@@ -35,7 +35,7 @@ use crate::num::FpCategory;
 pub const RADIX: u32 = f64::RADIX;
 
 /// Number of significant digits in base 2.
-/// Use [`f64::MANTISSA_DIGITS`](../../std/primitive.f64.html#associatedconstant.MANTISSA_DIGITS) instead.
+/// Use [`f64::MANTISSA_DIGITS`] instead.
 ///
 /// # Examples
 ///
@@ -55,7 +55,7 @@ pub const RADIX: u32 = f64::RADIX;
 pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
 
 /// Approximate number of significant digits in base 10.
-/// Use [`f64::DIGITS`](../../std/primitive.f64.html#associatedconstant.DIGITS) instead.
+/// Use [`f64::DIGITS`] instead.
 ///
 /// # Examples
 ///
@@ -72,7 +72,7 @@ pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
 pub const DIGITS: u32 = f64::DIGITS;
 
 /// [Machine epsilon] value for `f64`.
-/// Use [`f64::EPSILON`](../../std/primitive.f64.html#associatedconstant.EPSILON) instead.
+/// Use [`f64::EPSILON`] instead.
 ///
 /// This is the difference between `1.0` and the next larger representable number.
 ///
@@ -96,7 +96,7 @@ pub const DIGITS: u32 = f64::DIGITS;
 pub const EPSILON: f64 = f64::EPSILON;
 
 /// Smallest finite `f64` value.
-/// Use [`f64::MIN`](../../std/primitive.f64.html#associatedconstant.MIN) instead.
+/// Use [`f64::MIN`] instead.
 ///
 /// # Examples
 ///
@@ -113,7 +113,7 @@ pub const EPSILON: f64 = f64::EPSILON;
 pub const MIN: f64 = f64::MIN;
 
 /// Smallest positive normal `f64` value.
-/// Use [`f64::MIN_POSITIVE`](../../std/primitive.f64.html#associatedconstant.MIN_POSITIVE) instead.
+/// Use [`f64::MIN_POSITIVE`] instead.
 ///
 /// # Examples
 ///
@@ -133,7 +133,7 @@ pub const MIN: f64 = f64::MIN;
 pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
 
 /// Largest finite `f64` value.
-/// Use [`f64::MAX`](../../std/primitive.f64.html#associatedconstant.MAX) instead.
+/// Use [`f64::MAX`] instead.
 ///
 /// # Examples
 ///
@@ -150,7 +150,7 @@ pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
 pub const MAX: f64 = f64::MAX;
 
 /// One greater than the minimum possible normal power of 2 exponent.
-/// Use [`f64::MIN_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_EXP) instead.
+/// Use [`f64::MIN_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -170,7 +170,7 @@ pub const MAX: f64 = f64::MAX;
 pub const MIN_EXP: i32 = f64::MIN_EXP;
 
 /// Maximum possible power of 2 exponent.
-/// Use [`f64::MAX_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_EXP) instead.
+/// Use [`f64::MAX_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -190,7 +190,7 @@ pub const MIN_EXP: i32 = f64::MIN_EXP;
 pub const MAX_EXP: i32 = f64::MAX_EXP;
 
 /// Minimum possible normal power of 10 exponent.
-/// Use [`f64::MIN_10_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_10_EXP) instead.
+/// Use [`f64::MIN_10_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -210,7 +210,7 @@ pub const MAX_EXP: i32 = f64::MAX_EXP;
 pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
 
 /// Maximum possible power of 10 exponent.
-/// Use [`f64::MAX_10_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_10_EXP) instead.
+/// Use [`f64::MAX_10_EXP`] instead.
 ///
 /// # Examples
 ///
@@ -230,7 +230,7 @@ pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
 pub const MAX_10_EXP: i32 = f64::MAX_10_EXP;
 
 /// Not a Number (NaN).
-/// Use [`f64::NAN`](../../std/primitive.f64.html#associatedconstant.NAN) instead.
+/// Use [`f64::NAN`] instead.
 ///
 /// # Examples
 ///
@@ -247,7 +247,7 @@ pub const MAX_10_EXP: i32 = f64::MAX_10_EXP;
 pub const NAN: f64 = f64::NAN;
 
 /// Infinity (∞).
-/// Use [`f64::INFINITY`](../../std/primitive.f64.html#associatedconstant.INFINITY) instead.
+/// Use [`f64::INFINITY`] instead.
 ///
 /// # Examples
 ///
@@ -267,7 +267,7 @@ pub const NAN: f64 = f64::NAN;
 pub const INFINITY: f64 = f64::INFINITY;
 
 /// Negative infinity (−∞).
-/// Use [`f64::NEG_INFINITY`](../../std/primitive.f64.html#associatedconstant.NEG_INFINITY) instead.
+/// Use [`f64::NEG_INFINITY`] instead.
 ///
 /// # Examples
 ///
diff --git a/library/core/src/num/shells/i128.rs b/library/core/src/num/shells/i128.rs
index 785e9a4e9cf..b37767cd5eb 100644
--- a/library/core/src/num/shells/i128.rs
+++ b/library/core/src/num/shells/i128.rs
@@ -1,6 +1,6 @@
 //! Constants for the 128-bit signed integer type.
 //!
-//! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
+//! *[See also the `i128` primitive type][i128].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/i16.rs b/library/core/src/num/shells/i16.rs
index 48ea2e3e964..3137e72ca00 100644
--- a/library/core/src/num/shells/i16.rs
+++ b/library/core/src/num/shells/i16.rs
@@ -1,6 +1,6 @@
 //! Constants for the 16-bit signed integer type.
 //!
-//! *[See also the `i16` primitive type](../../std/primitive.i16.html).*
+//! *[See also the `i16` primitive type][i16].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/i32.rs b/library/core/src/num/shells/i32.rs
index fce6980f456..bb70751d8ca 100644
--- a/library/core/src/num/shells/i32.rs
+++ b/library/core/src/num/shells/i32.rs
@@ -1,6 +1,6 @@
 //! Constants for the 32-bit signed integer type.
 //!
-//! *[See also the `i32` primitive type](../../std/primitive.i32.html).*
+//! *[See also the `i32` primitive type][i32].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/i64.rs b/library/core/src/num/shells/i64.rs
index 6aa8fcf452b..b08201c2555 100644
--- a/library/core/src/num/shells/i64.rs
+++ b/library/core/src/num/shells/i64.rs
@@ -1,6 +1,6 @@
 //! Constants for the 64-bit signed integer type.
 //!
-//! *[See also the `i64` primitive type](../../std/primitive.i64.html).*
+//! *[See also the `i64` primitive type][i64].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/i8.rs b/library/core/src/num/shells/i8.rs
index b4e0fef61bb..a7ad9bbbbce 100644
--- a/library/core/src/num/shells/i8.rs
+++ b/library/core/src/num/shells/i8.rs
@@ -1,6 +1,6 @@
 //! Constants for the 8-bit signed integer type.
 //!
-//! *[See also the `i8` primitive type](../../std/primitive.i8.html).*
+//! *[See also the `i8` primitive type][i8].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/int_macros.rs b/library/core/src/num/shells/int_macros.rs
index 78513d44b75..c6a5595d958 100644
--- a/library/core/src/num/shells/int_macros.rs
+++ b/library/core/src/num/shells/int_macros.rs
@@ -5,8 +5,7 @@ macro_rules! int_module {
     ($T:ident, #[$attr:meta]) => (
         #[doc = concat!(
             "The smallest value that can be represented by this integer type. Use ",
-            "[`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN)",
-            " instead.",
+            "[`", stringify!($T), "::MIN", "`] instead."
         )]
         ///
         /// # Examples
@@ -25,8 +24,7 @@ macro_rules! int_module {
 
         #[doc = concat!(
             "The largest value that can be represented by this integer type. Use ",
-            "[`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX)",
-            " instead.",
+            "[`", stringify!($T), "::MAX", "`] instead."
         )]
         ///
         /// # Examples
diff --git a/library/core/src/num/shells/isize.rs b/library/core/src/num/shells/isize.rs
index 5dc128d58ae..d719936c0b2 100644
--- a/library/core/src/num/shells/isize.rs
+++ b/library/core/src/num/shells/isize.rs
@@ -1,6 +1,6 @@
 //! Constants for the pointer-sized signed integer type.
 //!
-//! *[See also the `isize` primitive type](../../std/primitive.isize.html).*
+//! *[See also the `isize` primitive type][isize].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/u128.rs b/library/core/src/num/shells/u128.rs
index 6012584ae86..49f56c67c37 100644
--- a/library/core/src/num/shells/u128.rs
+++ b/library/core/src/num/shells/u128.rs
@@ -1,6 +1,6 @@
 //! Constants for the 128-bit unsigned integer type.
 //!
-//! *[See also the `u128` primitive type](../../std/primitive.u128.html).*
+//! *[See also the `u128` primitive type][u128].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs
index 36641196403..b1d58ad4b9d 100644
--- a/library/core/src/num/shells/u16.rs
+++ b/library/core/src/num/shells/u16.rs
@@ -1,6 +1,6 @@
 //! Constants for the 16-bit unsigned integer type.
 //!
-//! *[See also the `u16` primitive type](../../std/primitive.u16.html).*
+//! *[See also the `u16` primitive type][u16].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/u32.rs b/library/core/src/num/shells/u32.rs
index f58f71423db..b6acf950035 100644
--- a/library/core/src/num/shells/u32.rs
+++ b/library/core/src/num/shells/u32.rs
@@ -1,6 +1,6 @@
 //! Constants for the 32-bit unsigned integer type.
 //!
-//! *[See also the `u32` primitive type](../../std/primitive.u32.html).*
+//! *[See also the `u32` primitive type][u32].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/u64.rs b/library/core/src/num/shells/u64.rs
index 2b221f66da6..d43726f84fa 100644
--- a/library/core/src/num/shells/u64.rs
+++ b/library/core/src/num/shells/u64.rs
@@ -1,6 +1,6 @@
 //! Constants for the 64-bit unsigned integer type.
 //!
-//! *[See also the `u64` primitive type](../../std/primitive.u64.html).*
+//! *[See also the `u64` primitive type][u64].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/u8.rs b/library/core/src/num/shells/u8.rs
index 83ec60dcbd8..0eadf85ec6d 100644
--- a/library/core/src/num/shells/u8.rs
+++ b/library/core/src/num/shells/u8.rs
@@ -1,6 +1,6 @@
 //! Constants for the 8-bit unsigned integer type.
 //!
-//! *[See also the `u8` primitive type](../../std/primitive.u8.html).*
+//! *[See also the `u8` primitive type][u8].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/num/shells/usize.rs b/library/core/src/num/shells/usize.rs
index c38d521f3da..deeed67d496 100644
--- a/library/core/src/num/shells/usize.rs
+++ b/library/core/src/num/shells/usize.rs
@@ -1,6 +1,6 @@
 //! Constants for the pointer-sized unsigned integer type.
 //!
-//! *[See also the `usize` primitive type](../../std/primitive.usize.html).*
+//! *[See also the `usize` primitive type][usize].*
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index bfdec43f7d8..e5c4798afcb 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -28,7 +28,7 @@
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [function pointers]: ../../std/primitive.fn.html
+/// [function pointers]: fn
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
 /// # Examples
@@ -97,7 +97,7 @@ pub trait Fn<Args>: FnMut<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [function pointers]: ../../std/primitive.fn.html
+/// [function pointers]: fn
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
 /// # Examples
@@ -176,7 +176,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
 /// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
 ///
 /// [book]: ../../book/ch13-01-closures.html
-/// [function pointers]: ../../std/primitive.fn.html
+/// [function pointers]: fn
 /// [nomicon]: ../../nomicon/hrtb.html
 ///
 /// # Examples
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index ddff0ff67de..cfc1bfd54be 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1011,8 +1011,6 @@ impl<T> *const [T] {
     /// See also [`slice::from_raw_parts`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [`NonNull::dangling()`]: NonNull::dangling
-    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 481d5d772b4..5026c48bdf4 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1,6 +1,6 @@
 //! Manually manage memory through raw pointers.
 //!
-//! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
+//! *[See also the pointer primitive types](pointer).*
 //!
 //! # Safety
 //!
@@ -60,7 +60,7 @@
 //! [ub]: ../../reference/behavior-considered-undefined.html
 //! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts
 //! [atomic operations]: crate::sync::atomic
-//! [`offset`]: ../../std/primitive.pointer.html#method.offset
+//! [`offset`]: pointer::offset
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 4e3e88b946c..06bacc86351 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1273,8 +1273,6 @@ impl<T> *mut [T] {
     /// See also [`slice::from_raw_parts`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [`NonNull::dangling()`]: NonNull::dangling
-    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
@@ -1325,8 +1323,6 @@ impl<T> *mut [T] {
     /// See also [`slice::from_raw_parts_mut`][].
     ///
     /// [valid]: crate::ptr#safety
-    /// [`NonNull::dangling()`]: NonNull::dangling
-    /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 709c247f296..8d533cd6be1 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -425,7 +425,6 @@ impl<T> NonNull<[T]> {
     /// See also [`slice::from_raw_parts`].
     ///
     /// [valid]: crate::ptr#safety
-    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit<T>] {
@@ -470,7 +469,6 @@ impl<T> NonNull<[T]> {
     /// See also [`slice::from_raw_parts_mut`].
     ///
     /// [valid]: crate::ptr#safety
-    /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
     ///
     /// # Examples
     ///
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index c7121c7ee59..7c48b8e41c6 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1285,11 +1285,10 @@ impl<T> Result<T, T> {
     /// `Err`.
     ///
     /// This can be useful in conjunction with APIs such as
-    /// [`Atomic*::compare_exchange`], or [`slice::binary_search`][binary_search], but only in
+    /// [`Atomic*::compare_exchange`], or [`slice::binary_search`], but only in
     /// cases where you don't care if the result was `Ok` or not.
     ///
     /// [`Atomic*::compare_exchange`]: crate::sync::atomic::AtomicBool::compare_exchange
-    /// [binary_search]: ../../std/primitive.slice.html#method.binary_search
     ///
     /// # Examples
     ///
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index d20986bb724..c92b37b14be 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -464,8 +464,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 ///
 /// [`Range`]: ops::Range
 /// [`RangeTo`]: ops::RangeTo
-/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
-/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+/// [`slice::get_unchecked`]: slice::get_unchecked
+/// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
 ///
 /// # Panics
 ///
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 50664267a67..8e651091cab 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -60,8 +60,8 @@ fn size_from_ptr<T>(_: *const T) -> usize {
 /// }
 /// ```
 ///
-/// [`iter`]: ../../std/primitive.slice.html#method.iter
-/// [slices]: ../../std/primitive.slice.html
+/// [`iter`]: slice::iter
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     ptr: NonNull<T>,
@@ -179,8 +179,8 @@ impl<T> AsRef<[T]> for Iter<'_, T> {
 /// println!("{:?}", slice);
 /// ```
 ///
-/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`iter_mut`]: slice::iter_mut
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     ptr: NonNull<T>,
@@ -328,8 +328,8 @@ pub(super) trait SplitIter: DoubleEndedIterator {
 /// let mut iter = slice.split(|num| num % 3 == 0);
 /// ```
 ///
-/// [`split`]: ../../std/primitive.slice.html#method.split
-/// [slices]: ../../std/primitive.slice.html
+/// [`split`]: slice::split
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, T: 'a, P>
 where
@@ -450,8 +450,8 @@ impl<T, P> FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {}
 /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
 /// ```
 ///
-/// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive
-/// [slices]: ../../std/primitive.slice.html
+/// [`split_inclusive`]: slice::split_inclusive
+/// [slices]: slice
 #[stable(feature = "split_inclusive", since = "1.51.0")]
 pub struct SplitInclusive<'a, T: 'a, P>
 where
@@ -562,8 +562,8 @@ impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool
 /// let iter = v.split_mut(|num| *num % 3 == 0);
 /// ```
 ///
-/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`split_mut`]: slice::split_mut
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitMut<'a, T: 'a, P>
 where
@@ -691,8 +691,8 @@ impl<T, P> FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
 /// let iter = v.split_inclusive_mut(|num| *num % 3 == 0);
 /// ```
 ///
-/// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`split_inclusive_mut`]: slice::split_inclusive_mut
+/// [slices]: slice
 #[stable(feature = "split_inclusive", since = "1.51.0")]
 pub struct SplitInclusiveMut<'a, T: 'a, P>
 where
@@ -812,8 +812,8 @@ impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b
 /// let iter = slice.rsplit(|num| *num == 0);
 /// ```
 ///
-/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
-/// [slices]: ../../std/primitive.slice.html
+/// [`rsplit`]: slice::rsplit
+/// [slices]: slice
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
 #[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
 pub struct RSplit<'a, T: 'a, P>
@@ -898,8 +898,8 @@ impl<T, P> FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {}
 /// let iter = slice.rsplit_mut(|num| *num == 0);
 /// ```
 ///
-/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`rsplit_mut`]: slice::rsplit_mut
+/// [slices]: slice
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
 pub struct RSplitMut<'a, T: 'a, P>
 where
@@ -1017,8 +1017,8 @@ impl<T, I: SplitIter<Item = T>> Iterator for GenericSplitN<I> {
 /// let iter = slice.splitn(2, |num| *num % 3 == 0);
 /// ```
 ///
-/// [`splitn`]: ../../std/primitive.slice.html#method.splitn
-/// [slices]: ../../std/primitive.slice.html
+/// [`splitn`]: slice::splitn
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitN<'a, T: 'a, P>
 where
@@ -1057,8 +1057,8 @@ where
 /// let iter = slice.rsplitn(2, |num| *num % 3 == 0);
 /// ```
 ///
-/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn
-/// [slices]: ../../std/primitive.slice.html
+/// [`rsplitn`]: slice::rsplitn
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, T: 'a, P>
 where
@@ -1096,8 +1096,8 @@ where
 /// let iter = slice.splitn_mut(2, |num| *num % 3 == 0);
 /// ```
 ///
-/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`splitn_mut`]: slice::splitn_mut
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitNMut<'a, T: 'a, P>
 where
@@ -1136,8 +1136,8 @@ where
 /// let iter = slice.rsplitn_mut(2, |num| *num % 3 == 0);
 /// ```
 ///
-/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`rsplitn_mut`]: slice::rsplitn_mut
+/// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitNMut<'a, T: 'a, P>
 where
@@ -1179,8 +1179,8 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
 /// let iter = slice.windows(2);
 /// ```
 ///
-/// [`windows`]: ../../std/primitive.slice.html#method.windows
-/// [slices]: ../../std/primitive.slice.html
+/// [`windows`]: slice::windows
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Windows<'a, T: 'a> {
@@ -1325,8 +1325,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
 /// let iter = slice.chunks(2);
 /// ```
 ///
-/// [`chunks`]: ../../std/primitive.slice.html#method.chunks
-/// [slices]: ../../std/primitive.slice.html
+/// [`chunks`]: slice::chunks
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chunks<'a, T: 'a> {
@@ -1493,8 +1493,8 @@ unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
 /// let iter = slice.chunks_mut(2);
 /// ```
 ///
-/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`chunks_mut`]: slice::chunks_mut
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ChunksMut<'a, T: 'a> {
@@ -1659,9 +1659,9 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
 /// let iter = slice.chunks_exact(2);
 /// ```
 ///
-/// [`chunks_exact`]: ../../std/primitive.slice.html#method.chunks_exact
+/// [`chunks_exact`]: slice::chunks_exact
 /// [`remainder`]: ChunksExact::remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "chunks_exact", since = "1.31.0")]
 pub struct ChunksExact<'a, T: 'a> {
@@ -1815,9 +1815,9 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
 /// let iter = slice.chunks_exact_mut(2);
 /// ```
 ///
-/// [`chunks_exact_mut`]: ../../std/primitive.slice.html#method.chunks_exact_mut
+/// [`chunks_exact_mut`]: slice::chunks_exact_mut
 /// [`into_remainder`]: ChunksExactMut::into_remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "chunks_exact", since = "1.31.0")]
 pub struct ChunksExactMut<'a, T: 'a> {
@@ -1966,8 +1966,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
 /// let iter = slice.array_windows::<2>();
 /// ```
 ///
-/// [`array_windows`]: ../../std/primitive.slice.html#method.array_windows
-/// [slices]: ../../std/primitive.slice.html
+/// [`array_windows`]: slice::array_windows
+/// [slices]: slice
 #[derive(Debug, Clone, Copy)]
 #[unstable(feature = "array_windows", issue = "75027")]
 pub struct ArrayWindows<'a, T: 'a, const N: usize> {
@@ -2087,9 +2087,9 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
 /// let iter = slice.array_chunks::<2>();
 /// ```
 ///
-/// [`array_chunks`]: ../../std/primitive.slice.html#method.array_chunks
+/// [`array_chunks`]: slice::array_chunks
 /// [`remainder`]: ArrayChunks::remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub struct ArrayChunks<'a, T: 'a, const N: usize> {
@@ -2209,9 +2209,9 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N>
 /// let iter = slice.array_chunks_mut::<2>();
 /// ```
 ///
-/// [`array_chunks_mut`]: ../../std/primitive.slice.html#method.array_chunks_mut
+/// [`array_chunks_mut`]: slice::array_chunks_mut
 /// [`into_remainder`]: ../../std/slice/struct.ArrayChunksMut.html#method.into_remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub struct ArrayChunksMut<'a, T: 'a, const N: usize> {
@@ -2320,8 +2320,8 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunksMut<'a, T,
 /// let iter = slice.rchunks(2);
 /// ```
 ///
-/// [`rchunks`]: ../../std/primitive.slice.html#method.rchunks
-/// [slices]: ../../std/primitive.slice.html
+/// [`rchunks`]: slice::rchunks
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunks<'a, T: 'a> {
@@ -2484,8 +2484,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
 /// let iter = slice.rchunks_mut(2);
 /// ```
 ///
-/// [`rchunks_mut`]: ../../std/primitive.slice.html#method.rchunks_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`rchunks_mut`]: slice::rchunks_mut
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksMut<'a, T: 'a> {
@@ -2648,9 +2648,9 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
 /// let iter = slice.rchunks_exact(2);
 /// ```
 ///
-/// [`rchunks_exact`]: ../../std/primitive.slice.html#method.rchunks_exact
+/// [`rchunks_exact`]: slice::rchunks_exact
 /// [`remainder`]: ChunksExact::remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksExact<'a, T: 'a> {
@@ -2808,9 +2808,9 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
 /// let iter = slice.rchunks_exact_mut(2);
 /// ```
 ///
-/// [`rchunks_exact_mut`]: ../../std/primitive.slice.html#method.rchunks_exact_mut
+/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
 /// [`into_remainder`]: ChunksExactMut::into_remainder
-/// [slices]: ../../std/primitive.slice.html
+/// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
 pub struct RChunksExactMut<'a, T: 'a> {
@@ -2969,8 +2969,8 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
 ///
 /// This struct is created by the [`group_by`] method on [slices].
 ///
-/// [`group_by`]: ../../std/primitive.slice.html#method.group_by
-/// [slices]: ../../std/primitive.slice.html
+/// [`group_by`]: slice::group_by
+/// [slices]: slice
 #[unstable(feature = "slice_group_by", issue = "80552")]
 pub struct GroupBy<'a, T: 'a, P> {
     slice: &'a [T],
@@ -3055,8 +3055,8 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> {
 ///
 /// This struct is created by the [`group_by_mut`] method on [slices].
 ///
-/// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut
-/// [slices]: ../../std/primitive.slice.html
+/// [`group_by_mut`]: slice::group_by_mut
+/// [slices]: slice
 #[unstable(feature = "slice_group_by", issue = "80552")]
 pub struct GroupByMut<'a, T: 'a, P> {
     slice: &'a mut [T],
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 117db6e3e3b..eda50dc287f 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -83,7 +83,6 @@ use crate::ptr;
 ///
 /// [valid]: ptr#safety
 /// [`NonNull::dangling()`]: ptr::NonNull::dangling
-/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
@@ -125,7 +124,6 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
 ///
 /// [valid]: ptr#safety
 /// [`NonNull::dangling()`]: ptr::NonNull::dangling
-/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 73316433e09..05ff7bb120d 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -14,7 +14,7 @@ use super::Utf8Error;
 /// UTF-8, and then does the conversion.
 ///
 /// [`&str`]: str
-/// [byteslice]: ../../std/primitive.slice.html
+/// [byteslice]: slice
 ///
 /// If you are sure that the byte slice is valid UTF-8, and you don't want to
 /// incur the overhead of the validity check, there is an unsafe version of
@@ -31,7 +31,7 @@ use super::Utf8Error;
 /// stack-allocated string. There is an example of this in the
 /// examples section below.
 ///
-/// [byteslice]: ../../std/primitive.slice.html
+/// [byteslice]: slice
 ///
 /// # Errors
 ///
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 1906fa27bf4..0a2743b1c31 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -540,9 +540,7 @@ pub trait FromStr: Sized {
     ///
     /// # Examples
     ///
-    /// Basic usage with [`i32`][ithirtytwo], a type that implements `FromStr`:
-    ///
-    /// [ithirtytwo]: ../../std/primitive.i32.html
+    /// Basic usage with [`i32`], a type that implements `FromStr`:
     ///
     /// ```
     /// use std::str::FromStr;
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 81c9e1d1c10..ca39224602e 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1307,7 +1307,7 @@ macro_rules! atomic_int {
      $stable_nand:meta,
      $const_stable:meta,
      $stable_init_const:meta,
-     $s_int_type:literal, $int_ref:expr,
+     $s_int_type:literal,
      $extra_feature:expr,
      $min_fn:ident, $max_fn:ident,
      $align:expr,
@@ -1318,18 +1318,14 @@ macro_rules! atomic_int {
         /// This type has the same in-memory representation as the underlying
         /// integer type, [`
         #[doc = $s_int_type]
-        /// `](
-        #[doc = $int_ref]
-        /// ). For more about the differences between atomic types and
+        /// `]. For more about the differences between atomic types and
         /// non-atomic types as well as information about the portability of
         /// this type, please see the [module-level documentation].
         ///
         /// **Note:** This type is only available on platforms that support
         /// atomic loads and stores of [`
         #[doc = $s_int_type]
-        /// `](
-        #[doc = $int_ref]
-        /// ).
+        /// `].
         ///
         /// [module-level documentation]: crate::sync::atomic
         #[$stable]
@@ -1525,7 +1521,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1557,7 +1553,7 @@ macro_rules! atomic_int {
             /// happens, and using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Migrating to `compare_exchange` and `compare_exchange_weak`
             ///
@@ -1626,7 +1622,7 @@ macro_rules! atomic_int {
             /// and must be equivalent to or weaker than the success ordering.
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1678,7 +1674,7 @@ macro_rules! atomic_int {
             /// and must be equivalent to or weaker than the success ordering.
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1720,7 +1716,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1749,7 +1745,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1781,7 +1777,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1813,7 +1809,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1845,7 +1841,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1877,7 +1873,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1916,7 +1912,7 @@ macro_rules! atomic_int {
             /// and must be equivalent to or weaker than the success ordering.
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -1960,7 +1956,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -2003,7 +1999,7 @@ macro_rules! atomic_int {
             /// using [`Release`] makes the load part [`Relaxed`].
             ///
             /// **Note**: This method is only available on platforms that support atomic operations on
-            #[doc = concat!("[`", $s_int_type, "`](", $int_ref, ").")]
+            #[doc = concat!("[`", $s_int_type, "`].")]
             ///
             /// # Examples
             ///
@@ -2088,7 +2084,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "i8", "../../../std/primitive.i8.html",
+    "i8",
     "",
     atomic_min, atomic_max,
     1,
@@ -2107,7 +2103,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "u8", "../../../std/primitive.u8.html",
+    "u8",
     "",
     atomic_umin, atomic_umax,
     1,
@@ -2126,7 +2122,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "i16", "../../../std/primitive.i16.html",
+    "i16",
     "",
     atomic_min, atomic_max,
     2,
@@ -2145,7 +2141,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "u16", "../../../std/primitive.u16.html",
+    "u16",
     "",
     atomic_umin, atomic_umax,
     2,
@@ -2164,7 +2160,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "i32", "../../../std/primitive.i32.html",
+    "i32",
     "",
     atomic_min, atomic_max,
     4,
@@ -2183,7 +2179,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "u32", "../../../std/primitive.u32.html",
+    "u32",
     "",
     atomic_umin, atomic_umax,
     4,
@@ -2202,7 +2198,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "i64", "../../../std/primitive.i64.html",
+    "i64",
     "",
     atomic_min, atomic_max,
     8,
@@ -2221,7 +2217,7 @@ atomic_int! {
     stable(feature = "integer_atomics_stable", since = "1.34.0"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "u64", "../../../std/primitive.u64.html",
+    "u64",
     "",
     atomic_umin, atomic_umax,
     8,
@@ -2240,7 +2236,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "i128", "../../../std/primitive.i128.html",
+    "i128",
     "#![feature(integer_atomics)]\n\n",
     atomic_min, atomic_max,
     16,
@@ -2259,7 +2255,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
     unstable(feature = "integer_atomics", issue = "32976"),
-    "u128", "../../../std/primitive.u128.html",
+    "u128",
     "#![feature(integer_atomics)]\n\n",
     atomic_umin, atomic_umax,
     16,
@@ -2282,7 +2278,7 @@ macro_rules! atomic_int_ptr_sized {
             stable(feature = "atomic_nand", since = "1.27.0"),
             rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
             stable(feature = "rust1", since = "1.0.0"),
-            "isize", "../../../std/primitive.isize.html",
+            "isize",
             "",
             atomic_min, atomic_max,
             $align,
@@ -2302,7 +2298,7 @@ macro_rules! atomic_int_ptr_sized {
             stable(feature = "atomic_nand", since = "1.27.0"),
             rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
             stable(feature = "rust1", since = "1.0.0"),
-            "usize", "../../../std/primitive.usize.html",
+            "usize",
             "",
             atomic_umin, atomic_umax,
             $align,
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 230ef0b23db..945bfda1b78 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -62,20 +62,18 @@ use crate::sys;
 /// u8` argument which is not necessarily nul-terminated, plus another
 /// argument with the length of the string — like C's `strndup()`.
 /// You can of course get the slice's length with its
-/// [`len`][slice.len] method.
+/// [`len`][slice::len] method.
 ///
 /// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
 /// can use [`CString::as_bytes_with_nul`] instead.
 ///
 /// Once you have the kind of slice you need (with or without a nul
 /// terminator), you can call the slice's own
-/// [`as_ptr`][slice.as_ptr] method to get a read-only raw pointer to pass to
+/// [`as_ptr`][slice::as_ptr] method to get a read-only raw pointer to pass to
 /// extern functions. See the documentation for that function for a
 /// discussion on ensuring the lifetime of the raw pointer.
 ///
 /// [`&str`]: prim@str
-/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
-/// [slice.len]: ../primitive.slice.html#method.len
 /// [`Deref`]: ops::Deref
 /// [`&CStr`]: CStr
 ///
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index db3b0e2628f..22914987405 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -482,7 +482,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
 /// }
 /// ```
 ///
-/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
+/// Read from [`&str`] because [`&[u8]`][prim@slice] implements `Read`:
 ///
 /// ```no_run
 /// # use std::io;
@@ -504,7 +504,6 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
 /// [`&str`]: prim@str
 /// [`std::io`]: self
 /// [`File`]: crate::fs::File
-/// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
 pub trait Read {
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 6b06539a094..383eaf2e3a2 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -42,7 +42,7 @@
 /// [Reference]: ../reference/expressions/operator-expr.html#type-cast-expressions
 /// [`crate`]: keyword.crate.html
 /// [`use`]: keyword.use.html
-/// [const-cast]: primitive.pointer.html#method.cast
+/// [const-cast]: pointer::cast
 /// [mut-cast]: primitive.pointer.html#method.cast-1
 mod as_keyword {}
 
@@ -181,9 +181,8 @@ mod break_keyword {}
 /// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
 /// T` and `*mut T`. More about `const` as used in raw pointers can be read at the Rust docs for the [pointer primitive].
 ///
-/// [pointer primitive]: primitive.pointer.html
-/// [Rust Book]:
-/// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+/// [pointer primitive]: pointer
+/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
 /// [Reference]: ../reference/items/constant-items.html
 /// [const-eval]: ../reference/const_eval.html
 mod const_keyword {}
@@ -371,7 +370,6 @@ mod else_keyword {}
 /// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type
 /// [Rust Book]: ../book/ch06-01-defining-an-enum.html
 /// [Reference]: ../reference/items/enumerations.html
-/// [`!`]: primitive.never.html
 mod enum_keyword {}
 
 #[doc(keyword = "extern")]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 63b65d8b413..ba49dee38e6 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -61,14 +61,14 @@
 //!    type, but not the all-important methods.
 //!
 //! So for example there is a [page for the primitive type
-//! `i32`](primitive.i32.html) that lists all the methods that can be called on
+//! `i32`](primitive::i32) that lists all the methods that can be called on
 //! 32-bit integers (very useful), and there is a [page for the module
 //! `std::i32`] that documents the constant values [`MIN`] and [`MAX`] (rarely
 //! useful).
 //!
-//! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
+//! Note the documentation for the primitives [`str`] and [`[T]`][prim@slice] (also
 //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
-//! calls to methods on [`str`] and [`[T]`][slice] respectively, via [deref
+//! calls to methods on [`str`] and [`[T]`][prim@slice] respectively, via [deref
 //! coercions][deref-coercions].
 //!
 //! Third, the standard library defines [The Rust Prelude], a small collection
@@ -111,8 +111,8 @@
 //! regions of memory:
 //!
 //! * [`Vec<T>`] - A heap-allocated *vector* that is resizable at runtime.
-//! * [`[T; n]`][array] - An inline *array* with a fixed size at compile time.
-//! * [`[T]`][slice] - A dynamically sized *slice* into any other kind of contiguous
+//! * [`[T; N]`][prim@array] - An inline *array* with a fixed size at compile time.
+//! * [`[T]`][prim@slice] - A dynamically sized *slice* into any other kind of contiguous
 //!   storage, whether heap-allocated or not.
 //!
 //! Slices can only be handled through some kind of *pointer*, and as such come
@@ -275,7 +275,7 @@
 #![feature(int_error_matching)]
 #![feature(integer_atomics)]
 #![feature(into_future)]
-#![cfg_attr(not(bootstrap), feature(intra_doc_pointers))]
+#![feature(intra_doc_pointers)]
 #![feature(lang_items)]
 #![feature(link_args)]
 #![feature(linkage)]
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 876b2b8a3f6..d4bb2083d00 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -468,8 +468,8 @@ mod prim_unit {}
 ///
 /// [`null`]: ptr::null
 /// [`null_mut`]: ptr::null_mut
-/// [`is_null`]: ../std/primitive.pointer.html#method.is_null
-/// [`offset`]: ../std/primitive.pointer.html#method.offset
+/// [`is_null`]: pointer::is_null
+/// [`offset`]: pointer::offset
 /// [`into_raw`]: Box::into_raw
 /// [`drop`]: mem::drop
 /// [`write`]: ptr::write
@@ -564,7 +564,7 @@ mod prim_pointer {}
 /// move_away(roa);
 /// ```
 ///
-/// [slice]: primitive.slice.html
+/// [slice]: prim@slice
 /// [`Debug`]: fmt::Debug
 /// [`Hash`]: hash::Hash
 /// [`Borrow`]: borrow::Borrow
diff --git a/src/doc/book b/src/doc/book
-Subproject db5e8a5105aa22979490dce30e33b68d8645761
+Subproject 0f87daf683ae3de3cb725faecb11b7e7e89f0e5
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 4cf7981696a85c3e633076c6401611bd3f6346c
+Subproject a96d096cffe5fa2c84af1b4b61e1492f839bb2e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 361367c126290ac17cb4089f8d38fd8b2ac43f9
+Subproject 3b6fe80c205d2a2b5dc8a276192bbce9eeb9e9c
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 551cc4bc8394feccea6acd21f86d9a4e1d2271a
+Subproject 3e0d98790c9126517fa1c604dc3678f396e92a2
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 7adfab42bab045a848126895c2f1e09927c1331
+Subproject c431f8c29a41413dddcb3bfa0d71c9cabe36631
diff --git a/src/doc/rustdoc/src/linking-to-items-by-name.md b/src/doc/rustdoc/src/linking-to-items-by-name.md
index 76e04398530..6ca1d1153b4 100644
--- a/src/doc/rustdoc/src/linking-to-items-by-name.md
+++ b/src/doc/rustdoc/src/linking-to-items-by-name.md
@@ -1,7 +1,7 @@
 # Linking to items by name
 
 Rustdoc is capable of directly linking to other rustdoc pages using the path of
-the item as a link.
+the item as a link. This is referred to as an 'intra-doc link'.
 
 For example, in the following code all of the links will link to the rustdoc page for `Bar`:
 
@@ -24,11 +24,20 @@ pub struct Foo4;
 pub struct Bar;
 ```
 
+Unlike normal Markdown, `[bar][Bar]` syntax is also supported without needing a
+`[Bar]: ...` reference link.
+
 Backticks around the link will be stripped, so ``[`Option`]`` will correctly
 link to `Option`.
 
-You can refer to anything in scope, and use paths, including `Self`, `self`,
-`super`, and `crate`. You may also use `foo()` and `foo!()` to refer to methods/functions and macros, respectively.
+## Valid links
+
+You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and
+`crate`. Associated items (functions, types, and constants) are supported, but [not for blanket
+trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in
+[the standard library documentation](../std/index.html#primitives).
+
+[#79682]: https://github.com/rust-lang/rust/pull/79682
 
 You can also refer to items with generic parameters like `Vec<T>`. The link will
 resolve as if you had written ``[`Vec<T>`](Vec)``. Fully-qualified syntax (for example,
@@ -53,7 +62,7 @@ impl<T> AsyncReceiver<T> {
 }
 ```
 
-You can also link to sections using URL fragment specifiers:
+Rustdoc allows using URL fragment specifiers, just like a normal link:
 
 ```rust
 /// This is a special implementation of [positional parameters].
@@ -62,9 +71,11 @@ You can also link to sections using URL fragment specifiers:
 struct MySpecialFormatter;
 ```
 
-Paths in Rust have three namespaces: type, value, and macro. Item names must be
-unique within their namespace, but can overlap with items outside of their
-namespace. In case of ambiguity, rustdoc will warn about the ambiguity and ask you to disambiguate, which can be done by using a prefix like `struct@`, `enum@`, `type@`, `trait@`, `union@`, `const@`, `static@`, `value@`, `fn@`, `function@`, `mod@`, `module@`, `method@`, `prim@`, `primitive@`, `macro@`, or `derive@`:
+## Namespaces and Disambiguators
+
+Paths in Rust have three namespaces: type, value, and macro. Item names must be unique within
+their namespace, but can overlap with items in other namespaces. In case of ambiguity,
+rustdoc will warn about the ambiguity and suggest a disambiguator.
 
 ```rust
 /// See also: [`Foo`](struct@Foo)
@@ -76,19 +87,57 @@ struct Foo {}
 fn Foo() {}
 ```
 
+These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be
+rendered as `Foo`.
+
 You can also disambiguate for functions by adding `()` after the function name,
 or for macros by adding `!` after the macro name:
 
 ```rust
-/// See also: [`Foo`](struct@Foo)
-struct Bar;
+/// This is different from [`foo!`]
+fn foo() {}
 
-/// This is different from [`Foo()`]
-struct Foo {}
+/// This is different from [`foo()`]
+macro_rules! foo {
+  () => {}
+}
+```
 
-fn Foo() {}
+## Warnings, re-exports, and scoping
+
+Links are resolved in the scope of the module where the item is defined, even
+when the item is re-exported. If a link from another crate fails to resolve, no
+warning is given.
+
+```rust,edition2018
+mod inner {
+    /// Link to [f()]
+    pub struct S;
+    pub fn f() {}
+}
+pub use inner::S; // the link to `f` will still resolve correctly
 ```
 
-Note: Because of how `macro_rules!` macros are scoped in Rust, the intra-doc links of a `macro_rules!` macro will be resolved [relative to the crate root][#72243], as opposed to the module it is defined in.
+When re-exporting an item, rustdoc allows adding additional documentation to it.
+That additional documentation will be resolved in the scope of the re-export, not
+the original, allowing you to link to items in the new crate. The new links
+will still give a warning if they fail to resolve.
+
+```rust
+/// See also [foo()]
+pub use std::process::Command;
+
+pub fn foo() {}
+```
+
+This is especially useful for proc-macros, which must always be defined in their own dedicated crate.
+
+Note: Because of how `macro_rules!` macros are scoped in Rust, the intra-doc links of a
+`macro_rules!` macro will be resolved [relative to the crate root][#72243], as opposed to the
+module it is defined in.
+
+If links do not look 'sufficiently like' an intra-doc link, they will be ignored and no warning
+will be given, even if the link fails to resolve. For example, any link containing `/` or `[]`
+characters will be ignored.
 
 [#72243]: https://github.com/rust-lang/rust/issues/72243
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index c23c087be41..d0e058c7dda 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -46,7 +46,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             return None;
         }
 
-        let result = f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| {
+        let result = f.find_auto_trait_generics(ty, param_env, trait_def_id, |info| {
             let region_data = info.region_data;
 
             let names_map = tcx
@@ -61,7 +61,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 .collect();
             let lifetime_predicates = Self::handle_lifetimes(&region_data, &names_map);
             let new_generics = self.param_env_to_generics(
-                infcx.tcx,
                 item_def_id,
                 info.full_user_env,
                 lifetime_predicates,
@@ -313,12 +312,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         lifetime_predicates
     }
 
-    fn extract_for_generics(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        pred: ty::Predicate<'tcx>,
-    ) -> FxHashSet<GenericParamDef> {
+    fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet<GenericParamDef> {
         let bound_predicate = pred.kind();
+        let tcx = self.cx.tcx;
         let regions = match bound_predicate.skip_binder() {
             ty::PredicateKind::Trait(poly_trait_pred, _) => {
                 tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred))
@@ -443,7 +439,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     // * We explicitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type
     fn param_env_to_generics(
         &mut self,
-        tcx: TyCtxt<'tcx>,
         item_def_id: DefId,
         param_env: ty::ParamEnv<'tcx>,
         mut existing_predicates: Vec<WherePredicate>,
@@ -455,14 +450,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             item_def_id, param_env, existing_predicates
         );
 
+        let tcx = self.cx.tcx;
+
         // The `Sized` trait must be handled specially, since we only display it when
         // it is *not* required (i.e., '?Sized')
-        let sized_trait = self.cx.tcx.require_lang_item(LangItem::Sized, None);
+        let sized_trait = tcx.require_lang_item(LangItem::Sized, None);
 
         let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, tcx };
 
-        let orig_bounds: FxHashSet<_> =
-            self.cx.tcx.param_env(item_def_id).caller_bounds().iter().collect();
+        let orig_bounds: FxHashSet<_> = tcx.param_env(item_def_id).caller_bounds().iter().collect();
         let clean_where_predicates = param_env
             .caller_bounds()
             .iter()
@@ -512,7 +508,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                         continue;
                     }
 
-                    let mut for_generics = self.extract_for_generics(tcx, orig_p);
+                    let mut for_generics = self.extract_for_generics(orig_p);
 
                     assert!(bounds.len() == 1);
                     let mut b = bounds.pop().expect("bounds were empty");
@@ -541,7 +537,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                                 // that we don't end up with duplicate bounds (e.g., for<'b, 'b>)
                                 for_generics.extend(p.generic_params.clone());
                                 p.generic_params = for_generics.into_iter().collect();
-                                self.is_fn_ty(tcx, &p.trait_)
+                                self.is_fn_ty(&p.trait_)
                             }
                             _ => false,
                         };
@@ -576,7 +572,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                                 } => {
                                     let mut new_trait_path = trait_path.clone();
 
-                                    if self.is_fn_ty(tcx, trait_) && left_name == sym::Output {
+                                    if self.is_fn_ty(trait_) && left_name == sym::Output {
                                         ty_to_fn
                                             .entry(*ty.clone())
                                             .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
@@ -734,7 +730,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         vec.sort_by_cached_key(|x| format!("{:?}", x))
     }
 
-    fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool {
+    fn is_fn_ty(&self, ty: &Type) -> bool {
+        let tcx = self.cx.tcx;
         match ty {
             &Type::ResolvedPath { did, .. } => {
                 did == tcx.require_lang_item(LangItem::Fn, None)
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index c544d1f41ce..02adccef594 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -483,6 +483,7 @@ impl<'a> fmt::Display for Display<'a> {
                         "openbsd" => "OpenBSD",
                         "redox" => "Redox",
                         "solaris" => "Solaris",
+                        "wasi" => "WASI",
                         "windows" => "Windows",
                         _ => "",
                     },
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 3a78269f19a..34b9cbcb679 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -368,6 +368,10 @@ fn test_render_long_html() {
             "This is supported on <strong>macOS</strong> only."
         );
         assert_eq!(
+            name_value_cfg("target_os", "wasi").render_long_html(),
+            "This is supported on <strong>WASI</strong> only."
+        );
+        assert_eq!(
             name_value_cfg("target_pointer_width", "16").render_long_html(),
             "This is supported on <strong>16-bit</strong> only."
         );
diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs
index 51a58378299..89a61a289fd 100644
--- a/src/test/rustdoc/doc-cfg.rs
+++ b/src/test/rustdoc/doc-cfg.rs
@@ -5,6 +5,8 @@
 // @!has - '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' ''
 // @has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()'
 // @has - '//*[@class="stab portability"]' 'This is supported on Unix and ARM only.'
+// @has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()'
+// @has - '//*[@class="stab portability"]' 'This is supported on WASI and WebAssembly only.'
 pub struct Portable;
 
 // @has doc_cfg/unix_only/index.html \
@@ -37,6 +39,36 @@ pub mod unix_only {
     }
 }
 
+// @has doc_cfg/wasi_only/index.html \
+//  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
+//  'This is supported on WASI only.'
+// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
+// @count - '//*[@class="stab portability"]' 2
+#[doc(cfg(target_os = "wasi"))]
+pub mod wasi_only {
+    // @has doc_cfg/wasi_only/fn.wasi_only_function.html \
+    //  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
+    //  'This is supported on WASI only.'
+    // @count - '//*[@class="stab portability"]' 1
+    pub fn wasi_only_function() {
+        content::should::be::irrelevant();
+    }
+
+    // @has doc_cfg/wasi_only/trait.Wasm32Only.html \
+    //  '//*[@id="main"]/*[@class="item-info"]/*[@class="stab portability"]' \
+    //  'This is supported on WASI and WebAssembly only.'
+    // @count - '//*[@class="stab portability"]' 1
+    #[doc(cfg(target_arch = "wasm32"))]
+    pub trait Wasm32Only {
+        fn wasi_and_wasm32_only_function();
+    }
+
+    #[doc(cfg(target_arch = "wasm32"))]
+    impl Wasm32Only for super::Portable {
+        fn wasi_and_wasm32_only_function() {}
+    }
+}
+
 // tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
 // item as well
 
diff --git a/src/test/ui/assoc-inherent.rs b/src/test/ui/assoc-inherent.rs
index 05329a27142..c579c962ffc 100644
--- a/src/test/ui/assoc-inherent.rs
+++ b/src/test/ui/assoc-inherent.rs
@@ -1,9 +1,20 @@
-// Test associated types are, until #8995 is implemented, forbidden in inherent impls.
+// Test that inherent associated types work with
+// inherent_associated_types feature gate.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
 
 struct Foo;
 
 impl Foo {
-    type Bar = isize; //~ERROR associated types are not yet supported in inherent impls (see #8995)
+    type Bar = isize;
 }
 
-fn main() {}
+impl Foo {
+    type Baz; //~ ERROR associated type in `impl` without body
+}
+
+fn main() {
+    let x : Foo::Bar; //~ERROR ambiguous associated type
+    x = 0isize;
+}
diff --git a/src/test/ui/assoc-inherent.stderr b/src/test/ui/assoc-inherent.stderr
index f9ea3365cb8..b703453fa03 100644
--- a/src/test/ui/assoc-inherent.stderr
+++ b/src/test/ui/assoc-inherent.stderr
@@ -1,9 +1,17 @@
-error[E0202]: associated types are not yet supported in inherent impls (see #8995)
-  --> $DIR/assoc-inherent.rs:6:5
+error: associated type in `impl` without body
+  --> $DIR/assoc-inherent.rs:14:5
    |
-LL |     type Bar = isize;
-   |     ^^^^^^^^^^^^^^^^^
+LL |     type Baz;
+   |     ^^^^^^^^-
+   |             |
+   |             help: provide a definition for the type: `= <type>;`
 
-error: aborting due to previous error
+error[E0223]: ambiguous associated type
+  --> $DIR/assoc-inherent.rs:18:13
+   |
+LL |     let x : Foo::Bar;
+   |             ^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Bar`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0202`.
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/feature-gates/feature-gate-inherent_associated_types.rs b/src/test/ui/feature-gates/feature-gate-inherent_associated_types.rs
new file mode 100644
index 00000000000..fc7c6dbc02e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-inherent_associated_types.rs
@@ -0,0 +1,10 @@
+// Test that inherent associated types cannot be used when inherent_associated_types
+// feature gate is not used.
+
+struct Foo;
+
+impl Foo {
+    type Bar = isize; //~ERROR inherent associated types are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-inherent_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-inherent_associated_types.stderr
new file mode 100644
index 00000000000..76e65d239f8
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-inherent_associated_types.stderr
@@ -0,0 +1,12 @@
+error[E0658]: inherent associated types are unstable
+  --> $DIR/feature-gate-inherent_associated_types.rs:7:5
+   |
+LL |     type Bar = isize;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` 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/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
index fa9c7ababcf..1ccc9497d9d 100644
--- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
+++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs
@@ -8,16 +8,16 @@ struct X;
 impl X {
     type Y;
     //~^ ERROR associated type in `impl` without body
-    //~| ERROR associated types are not yet supported in inherent impls
+    //~| ERROR inherent associated types are unstable
     type Z: Ord;
     //~^ ERROR associated type in `impl` without body
     //~| ERROR bounds on `type`s in `impl`s have no effect
-    //~| ERROR associated types are not yet supported in inherent impls
+    //~| ERROR inherent associated types are unstable
     type W: Ord where Self: Eq;
     //~^ ERROR associated type in `impl` without body
     //~| ERROR bounds on `type`s in `impl`s have no effect
-    //~| ERROR associated types are not yet supported in inherent impls
+    //~| ERROR inherent associated types are unstable
     type W where Self: Eq;
     //~^ ERROR associated type in `impl` without body
-    //~| ERROR associated types are not yet supported in inherent impls
+    //~| ERROR inherent associated types are unstable
 }
diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
index 214467793bc..818d73c898d 100644
--- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
+++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr
@@ -51,30 +51,42 @@ LL | #![feature(generic_associated_types)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
 
-error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+error[E0658]: inherent associated types are unstable
   --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5
    |
 LL |     type Y;
    |     ^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
-error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+error[E0658]: inherent associated types are unstable
   --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5
    |
 LL |     type Z: Ord;
    |     ^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
-error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+error[E0658]: inherent associated types are unstable
   --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5
    |
 LL |     type W: Ord where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
-error[E0202]: associated types are not yet supported in inherent impls (see #8995)
+error[E0658]: inherent associated types are unstable
   --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5
    |
 LL |     type W where Self: Eq;
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
 error: aborting due to 10 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0202`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/return/issue-82612-return-mutable-reference.rs b/src/test/ui/return/issue-82612-return-mutable-reference.rs
new file mode 100644
index 00000000000..db0d08ddb91
--- /dev/null
+++ b/src/test/ui/return/issue-82612-return-mutable-reference.rs
@@ -0,0 +1,24 @@
+// Regression test for #82612.
+
+use std::marker::PhantomData;
+
+pub trait SparseSetIndex {
+    fn sparse_set_index(&self) -> usize;
+}
+pub struct SparseArray<I, V = I> {
+    values: Vec<Option<V>>,
+    marker: PhantomData<I>,
+}
+
+impl<I: SparseSetIndex, V> SparseArray<I, V> {
+    pub fn get_or_insert_with(&mut self, index: I, func: impl FnOnce() -> V) -> &mut V {
+        let index = index.sparse_set_index();
+        if index < self.values.len() {
+            let value = unsafe { self.values.get_unchecked_mut(index) };
+            value.get_or_insert_with(func) //~ ERROR mismatched types
+        }
+        unsafe { self.values.get_unchecked_mut(index).as_mut().unwrap() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/return/issue-82612-return-mutable-reference.stderr b/src/test/ui/return/issue-82612-return-mutable-reference.stderr
new file mode 100644
index 00000000000..a8045e043ad
--- /dev/null
+++ b/src/test/ui/return/issue-82612-return-mutable-reference.stderr
@@ -0,0 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-82612-return-mutable-reference.rs:18:13
+   |
+LL | /         if index < self.values.len() {
+LL | |             let value = unsafe { self.values.get_unchecked_mut(index) };
+LL | |             value.get_or_insert_with(func)
+   | |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&mut V`
+LL | |         }
+   | |_________- expected this to be `()`
+   |
+   = note:      expected unit type `()`
+           found mutable reference `&mut V`
+help: consider using a semicolon here
+   |
+LL |             value.get_or_insert_with(func);
+   |                                           ^
+help: consider using a semicolon here
+   |
+LL |         };
+   |          ^
+help: you might have meant to return this value
+   |
+LL |             return value.get_or_insert_with(func);
+   |             ^^^^^^                               ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-82566-1.rs b/src/test/ui/suggestions/issue-82566-1.rs
new file mode 100644
index 00000000000..95c31fbaa28
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-1.rs
@@ -0,0 +1,21 @@
+struct T1<const X1: usize>;
+struct T2<const X1: usize, const X2: usize>;
+struct T3<const X1: usize, const X2: usize, const X3: usize>;
+
+impl T1<1> {
+    const C: () = ();
+}
+
+impl T2<1, 2> {
+    const C: () = ();
+}
+
+impl T3<1, 2, 3> {
+    const C: () = ();
+}
+
+fn main() {
+    T1<1>::C; //~ ERROR: comparison operators cannot be chained
+    T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+    T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+}
diff --git a/src/test/ui/suggestions/issue-82566-1.stderr b/src/test/ui/suggestions/issue-82566-1.stderr
new file mode 100644
index 00000000000..5a9099a894c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-1.stderr
@@ -0,0 +1,35 @@
+error: comparison operators cannot be chained
+  --> $DIR/issue-82566-1.rs:18:7
+   |
+LL |     T1<1>::C;
+   |       ^ ^
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL |     T1::<1>::C;
+   |       ^^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+  --> $DIR/issue-82566-1.rs:19:9
+   |
+LL |     T2<1, 2>::C;
+   |         ^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL |     T2::<1, 2>::C;
+   |       ^^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+  --> $DIR/issue-82566-1.rs:20:9
+   |
+LL |     T3<1, 2, 3>::C;
+   |         ^ expected one of `.`, `;`, `?`, `}`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL |     T3::<1, 2, 3>::C;
+   |       ^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/suggestions/issue-82566-2.rs b/src/test/ui/suggestions/issue-82566-2.rs
new file mode 100644
index 00000000000..80c8034bd0a
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-2.rs
@@ -0,0 +1,31 @@
+struct Foo1<const N1: usize>;
+struct Foo2<const N1: usize, const N2: usize>;
+struct Foo3<const N1: usize, const N2: usize, const N3: usize>;
+
+impl<const N1: usize> Foo1<N1> {
+    const SUM: usize = N1;
+}
+
+impl<const N1: usize, const N2: usize> Foo2<N1, N2> {
+    const SUM: usize = N1 + N2;
+}
+
+impl<const N1: usize, const N2: usize, const N3: usize> Foo3<N1, N2, N3> {
+    const SUM: usize = N1 + N2 + N3;
+}
+
+fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained
+    todo!()
+}
+
+fn foo2() -> [(); Foo2<10, 20>::SUM] {
+    //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+    todo!()
+}
+
+fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+    //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,`
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-82566-2.stderr b/src/test/ui/suggestions/issue-82566-2.stderr
new file mode 100644
index 00000000000..ea391ee078c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-82566-2.stderr
@@ -0,0 +1,35 @@
+error: comparison operators cannot be chained
+  --> $DIR/issue-82566-2.rs:17:23
+   |
+LL | fn foo1() -> [(); Foo1<10>::SUM] {
+   |                       ^  ^
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo1() -> [(); Foo1::<10>::SUM] {
+   |                       ^^
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+  --> $DIR/issue-82566-2.rs:21:26
+   |
+LL | fn foo2() -> [(); Foo2<10, 20>::SUM] {
+   |                          ^ expected one of `.`, `?`, `]`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] {
+   |                       ^^
+
+error: expected one of `.`, `?`, `]`, or an operator, found `,`
+  --> $DIR/issue-82566-2.rs:26:26
+   |
+LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] {
+   |                          ^ expected one of `.`, `?`, `]`, or an operator
+   |
+help: use `::<...>` instead of `<...>` to specify type or const arguments
+   |
+LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] {
+   |                       ^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject 14de9e54a6d9ef070399b34a11634294a8cc3ca
+Subproject 5df3ee8274fdb7cdeb2b0871b4efea8cbf4724a