diff --git a/Cargo.lock b/Cargo.lock
index 5c1736c692e48..897591646e41e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -294,7 +294,7 @@ dependencies = [
  "rand 0.8.3",
  "rustc-workspace-hack",
  "rustfix",
- "semver 1.0.1",
+ "semver 1.0.3",
  "serde",
  "serde_ignored",
  "serde_json",
@@ -4681,9 +4681,9 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.1"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d023dabf011d5dcb5ac64e3685d97d3b0ef412911077a2851455c6098524a723"
+checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe"
 dependencies = [
  "serde",
 ]
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 26706cd2b1b77..722ce6b636726 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -43,49 +43,9 @@ cfg_if! {
         use std::ops::Add;
         use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
 
-        /// This is a single threaded variant of AtomicCell provided by crossbeam.
-        /// Unlike `Atomic` this is intended for all `Copy` types,
-        /// but it lacks the explicit ordering arguments.
-        #[derive(Debug)]
-        pub struct AtomicCell<T: Copy>(Cell<T>);
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn new(v: T) -> Self {
-                AtomicCell(Cell::new(v))
-            }
-
-            #[inline]
-            pub fn get_mut(&mut self) -> &mut T {
-                self.0.get_mut()
-            }
-        }
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn into_inner(self) -> T {
-                self.0.into_inner()
-            }
-
-            #[inline]
-            pub fn load(&self) -> T {
-                self.0.get()
-            }
-
-            #[inline]
-            pub fn store(&self, val: T) {
-                self.0.set(val)
-            }
-
-            #[inline]
-            pub fn swap(&self, val: T) -> T {
-                self.0.replace(val)
-            }
-        }
-
         /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
-        /// It differs from `AtomicCell` in that it has explicit ordering arguments
-        /// and is only intended for use with the native atomic types.
+        /// It has explicit ordering arguments and is only intended for use with
+        /// the native atomic types.
         /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
         /// as it's not intended to be used separately.
         #[derive(Debug)]
@@ -159,22 +119,6 @@ cfg_if! {
             (oper_a(), oper_b())
         }
 
-        pub struct SerialScope;
-
-        impl SerialScope {
-            pub fn spawn<F>(&self, f: F)
-                where F: FnOnce(&SerialScope)
-            {
-                f(self)
-            }
-        }
-
-        pub fn scope<F, R>(f: F) -> R
-            where F: FnOnce(&SerialScope) -> R
-        {
-            f(&SerialScope)
-        }
-
         #[macro_export]
         macro_rules! parallel {
             ($($blocks:tt),*) => {
@@ -318,8 +262,6 @@ cfg_if! {
 
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
-        pub use crossbeam_utils::atomic::AtomicCell;
-
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 319adf42cf1ed..5d2256100ff67 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -909,11 +909,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         match *ty.kind() {
-            ty::Adt(def, _) if def.is_box() && matches!(self.mode, CItemKind::Definition) => {
-                FfiSafe
-            }
-
             ty::Adt(def, substs) => {
+                if def.is_box() && matches!(self.mode, CItemKind::Definition) {
+                    if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) {
+                        return FfiSafe;
+                    } else {
+                        return FfiUnsafe {
+                            ty,
+                            reason: format!("box cannot be represented as a single pointer"),
+                            help: None,
+                        };
+                    }
+                }
                 if def.is_phantom_data() {
                     return FfiPhantom(ty);
                 }
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index 87e740de08e91..6c8977351949d 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -103,12 +103,6 @@ pub fn options() -> TargetOptions {
         linker: Some("rust-lld".to_owned()),
         lld_flavor: LldFlavor::Wasm,
 
-        // No need for indirection here, simd types can always be passed by
-        // value as the whole module either has simd or not, which is different
-        // from x86 (for example) where programs can have functions that don't
-        // enable simd features.
-        simd_types_indirect: false,
-
         pre_link_args,
 
         crt_objects_fallback: Some(CrtObjectsFallback::Wasm),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index db396356d6711..19c3385dd4cbc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1878,6 +1878,10 @@ impl<'v> Visitor<'v> for FindTypeParam {
         hir::intravisit::NestedVisitorMap::None
     }
 
+    fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
+        // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
+    }
+
     fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
         // We collect the spans of all uses of the "bare" type param, like in `field: T` or
         // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 9cc435a0dec2e..33bc25accb319 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -17,6 +17,7 @@ use rustc_span::Span;
 use super::method::probe;
 
 use std::fmt;
+use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -573,12 +574,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest removing a `&`.
                 if sm.is_imported(expr.span) {
-                    if let Ok(src) = sm.span_to_snippet(sp) {
-                        if let Some(src) = src.strip_prefix('&') {
+                    // Go through the spans from which this span was expanded,
+                    // and find the one that's pointing inside `sp`.
+                    //
+                    // E.g. for `&format!("")`, where we want the span to the
+                    // `format!()` invocation instead of its expansion.
+                    if let Some(call_span) =
+                        iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s))
+                    {
+                        if let Ok(code) = sm.span_to_snippet(call_span) {
                             return Some((
                                 sp,
                                 "consider removing the borrow",
-                                src.to_string(),
+                                code,
                                 Applicability::MachineApplicable,
                             ));
                         }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 7bc9aa69be98e..a04e7c8a498da 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -59,7 +59,6 @@
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index a023edaca9e94..6c0b9c0331e30 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -51,7 +51,6 @@
 #![cfg(not(test))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 5dcd1e6af3659..d95ea6530c204 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -5,10 +5,7 @@
 
 #![no_std]
 #![unstable(feature = "panic_abort", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![panic_runtime]
 #![allow(unused_features)]
 #![feature(core_intrinsics)]
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 99a0c67fc11b9..d32a3f1f8322c 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -13,10 +13,7 @@
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(nll)]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 04a165e09f1e5..3990826ce42e0 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -12,7 +12,6 @@
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
 #![deny(missing_docs)]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 8e4c63762fd38..c4f21587457c1 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -190,7 +190,6 @@
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
diff --git a/library/term/src/lib.rs b/library/term/src/lib.rs
index 2116b433fce3f..943b276a220c8 100644
--- a/library/term/src/lib.rs
+++ b/library/term/src/lib.rs
@@ -30,11 +30,7 @@
 //! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    html_playground_url = "https://play.rust-lang.org/",
-    test(attr(deny(warnings)))
-)]
+#![doc(html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))]
 #![deny(missing_docs)]
 #![cfg_attr(windows, feature(libc))]
 
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index bda5ed888d7e1..3da4d434f48f2 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -19,7 +19,7 @@
 
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "50297")]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
+#![doc(test(attr(deny(warnings))))]
 #![cfg_attr(unix, feature(libc))]
 #![feature(rustc_private)]
 #![feature(nll)]
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index da298f7edb9f4..06f8bf89daecd 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -574,6 +574,18 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
+    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
+    pub fn doc_rust_lang_org_channel(&self) -> String {
+        let channel = match &*self.config.channel {
+            "stable" => &self.version,
+            "beta" => "beta",
+            "nightly" | "dev" => "nightly",
+            // custom build of rustdoc maybe? link to the latest stable docs just in case
+            _ => "stable",
+        };
+        "https://doc.rust-lang.org/".to_owned() + channel
+    }
+
     fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
         StepDescription::run(v, self, paths);
     }
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e5258d08956f6..c057910e4f95f 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -326,6 +326,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     if target.contains("riscv") {
         cargo.rustflag("-Cforce-unwind-tables=yes");
     }
+
+    let html_root =
+        format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
+    cargo.rustflag(&html_root);
+    cargo.rustdocflag(&html_root);
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2960dd3df6bf4..1ea29a829c270 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1366,7 +1366,7 @@ impl Build {
                 eprintln!(
                     "
 Couldn't find required command: ninja
-You should install ninja, or set ninja=false in config.toml
+You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
 "
                 );
                 std::process::exit(1);
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 7bd29c61b0cdb..cc7c143d47461 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1486,6 +1486,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             }
         }
         cmd.env("RUSTC_BOOTSTRAP", "1");
+        cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
         builder.add_rust_test_threads(&mut cmd);
 
         if builder.config.sanitizers_enabled(target) {
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 64e4be6863a62..9d75ad0918a79 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -263,6 +263,7 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
     cargo.env("CFG_VERSION", builder.rust_version());
     cargo.env("CFG_RELEASE_NUM", &builder.version);
+    cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
 
     let info = GitInfo::new(builder.config.ignore_git, &dir);
     if let Some(sha) = info.sha() {
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 2f7233685db52..8647db5a45dc8 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -135,6 +135,8 @@
     unichr = chr
 
 
+channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
+
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
 
@@ -270,6 +272,7 @@ def flatten(node):
 
 
 def normalize_xpath(path):
+    path = path.replace("{{channel}}", channel)
     if path.startswith('//'):
         return '.' + path  # avoid warnings
     elif path.startswith('.//'):
@@ -334,6 +337,7 @@ def get_dir(self, path):
 
 
 def check_string(data, pat, regexp):
+    pat = pat.replace("{{channel}}", channel)
     if not pat:
         return True  # special case a presence testing
     elif regexp:
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3ae516bd6df7c..9f2123f22bd38 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -499,7 +499,7 @@ impl Item {
                                     format!("{}/std/", s.trim_end_matches('/'))
                                 }
                                 Some(ExternalLocation::Unknown) | None => {
-                                    "https://doc.rust-lang.org/nightly/std/".to_string()
+                                    format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
                                 }
                             };
                             // This is a primitive so the url is done "by hand".
@@ -1767,37 +1767,6 @@ impl PrimitiveType {
         }
     }
 
-    crate fn as_str(&self) -> &'static str {
-        use self::PrimitiveType::*;
-        match *self {
-            Isize => "isize",
-            I8 => "i8",
-            I16 => "i16",
-            I32 => "i32",
-            I64 => "i64",
-            I128 => "i128",
-            Usize => "usize",
-            U8 => "u8",
-            U16 => "u16",
-            U32 => "u32",
-            U64 => "u64",
-            U128 => "u128",
-            F32 => "f32",
-            F64 => "f64",
-            Str => "str",
-            Bool => "bool",
-            Char => "char",
-            Array => "array",
-            Slice => "slice",
-            Tuple => "tuple",
-            Unit => "unit",
-            RawPointer => "pointer",
-            Reference => "reference",
-            Fn => "fn",
-            Never => "never",
-        }
-    }
-
     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
     }
@@ -1860,10 +1829,6 @@ impl PrimitiveType {
         })
     }
 
-    crate fn to_url_str(&self) -> &'static str {
-        self.as_str()
-    }
-
     crate fn as_sym(&self) -> Symbol {
         use PrimitiveType::*;
         match self {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 2c31a502565aa..350a387877142 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -2,7 +2,7 @@ use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
-    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -451,35 +451,48 @@ crate fn get_auto_trait_and_blanket_impls(
     auto_impls.into_iter().chain(blanket_impls)
 }
 
+/// If `res` has a documentation page associated, store it in the cache.
+///
+/// This is later used by [`href()`] to determine the HTML link for the item.
+///
+/// [`href()`]: crate::html::format::href
 crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
+    use DefKind::*;
     debug!("register_res({:?})", res);
 
     let (did, kind) = match res {
-        Res::Def(DefKind::Fn, i) => (i, ItemType::Function),
-        Res::Def(DefKind::TyAlias, i) => (i, ItemType::Typedef),
-        Res::Def(DefKind::Enum, i) => (i, ItemType::Enum),
-        Res::Def(DefKind::Trait, i) => (i, ItemType::Trait),
         Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => {
+            // associated items are documented, but on the page of their parent
             (cx.tcx.parent(i).unwrap(), ItemType::Trait)
         }
-        Res::Def(DefKind::Struct, i) => (i, ItemType::Struct),
-        Res::Def(DefKind::Union, i) => (i, ItemType::Union),
-        Res::Def(DefKind::Mod, i) => (i, ItemType::Module),
-        Res::Def(DefKind::ForeignTy, i) => (i, ItemType::ForeignType),
-        Res::Def(DefKind::Const, i) => (i, ItemType::Constant),
-        Res::Def(DefKind::Static, i) => (i, ItemType::Static),
         Res::Def(DefKind::Variant, i) => {
+            // variant items are documented, but on the page of their parent
             (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum)
         }
-        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
-            MacroKind::Bang => (i, ItemType::Macro),
-            MacroKind::Attr => (i, ItemType::ProcAttribute),
-            MacroKind::Derive => (i, ItemType::ProcDerive),
-        },
-        Res::Def(DefKind::TraitAlias, i) => (i, ItemType::TraitAlias),
-        Res::SelfTy(Some(def_id), _) => (def_id, ItemType::Trait),
-        Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id,
-        _ => return res.def_id(),
+        // Each of these have their own page.
+        Res::Def(
+            kind
+            @
+            (Fn | TyAlias | Enum | Trait | Struct | Union | Mod | ForeignTy | Const | Static
+            | Macro(..) | TraitAlias),
+            i,
+        ) => (i, kind.into()),
+        // This is part of a trait definition; document the trait.
+        Res::SelfTy(Some(trait_def_id), _) => (trait_def_id, ItemType::Trait),
+        // This is an inherent impl; it doesn't have its own page.
+        Res::SelfTy(None, Some((impl_def_id, _))) => return impl_def_id,
+        Res::SelfTy(None, None)
+        | Res::PrimTy(_)
+        | Res::ToolMod
+        | Res::SelfCtor(_)
+        | Res::Local(_)
+        | Res::NonMacroAttr(_)
+        | Res::Err => return res.def_id(),
+        Res::Def(
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
+            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            id,
+        ) => return id,
     };
     if did.is_local() {
         return did;
@@ -543,3 +556,8 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
             && attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag))
     })
 }
+
+/// A link to `doc.rust-lang.org` that includes the channel name.
+///
+/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
+crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 3c1d03a78f1cd..d5213fd77117a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -574,7 +574,7 @@ fn primitive_link(
                     f,
                     "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
                     "../".repeat(len),
-                    prim.to_url_str()
+                    prim.as_sym()
                 )?;
                 needs_termination = true;
             }
@@ -603,7 +603,7 @@ fn primitive_link(
                         f,
                         "<a class=\"primitive\" href=\"{}/primitive.{}.html\">",
                         loc.join("/"),
-                        prim.to_url_str()
+                        prim.as_sym()
                     )?;
                     needs_termination = true;
                 }
@@ -677,7 +677,7 @@ fn fmt_type<'cx>(
             fmt::Display::fmt(&tybounds(param_names, cx), f)
         }
         clean::Infer => write!(f, "_"),
-        clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cx),
+        clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
         clean::BareFunction(ref decl) => {
             if f.alternate() {
                 write!(
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index c6646ba9ae4d2..bee62915ea9b1 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -379,7 +379,7 @@ impl FromWithTcx<clean::Type> for Type {
                     .unwrap_or_default(),
             },
             Generic(s) => Type::Generic(s.to_string()),
-            Primitive(p) => Type::Primitive(p.as_str().to_string()),
+            Primitive(p) => Type::Primitive(p.as_sym().to_string()),
             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
             Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
             Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7c93a09480713..2d371b5383191 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -81,6 +81,8 @@ use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGro
 use rustc_session::getopts;
 use rustc_session::{early_error, early_warn};
 
+use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL;
+
 /// A macro to create a FxHashMap.
 ///
 /// Example:
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 81c90f4eaa75b..e6e6497902c26 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -91,10 +91,10 @@ impl Res {
         }
     }
 
-    fn name(self, tcx: TyCtxt<'_>) -> String {
+    fn name(self, tcx: TyCtxt<'_>) -> Symbol {
         match self {
-            Res::Def(_, id) => tcx.item_name(id).to_string(),
-            Res::Primitive(prim) => prim.as_str().to_string(),
+            Res::Def(_, id) => tcx.item_name(id),
+            Res::Primitive(prim) => prim.as_sym(),
         }
     }
 
@@ -388,7 +388,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ty::AssocKind::Const => "associatedconstant",
                         ty::AssocKind::Type => "associatedtype",
                     };
-                    let fragment = format!("{}#{}.{}", prim_ty.as_str(), out, item_name);
+                    let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
                     (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
                 })
         })
@@ -481,7 +481,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                             AnchorFailure::RustdocAnchorConflict(res),
                         ));
                     }
-                    return Ok((res, Some(ty.as_str().to_owned())));
+                    return Ok((res, Some(ty.as_sym().to_string())));
                 }
                 _ => return Ok((res, extra_fragment.clone())),
             }
@@ -1148,7 +1148,7 @@ impl LinkCollector<'_, '_> {
                         return None;
                     }
                     res = prim;
-                    fragment = Some(prim.name(self.cx.tcx));
+                    fragment = Some(prim.name(self.cx.tcx).to_string());
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
diff --git a/src/test/rustdoc-ui/check.rs b/src/test/rustdoc-ui/check.rs
index 65a56e03d9dfc..2b44ba24b4426 100644
--- a/src/test/rustdoc-ui/check.rs
+++ b/src/test/rustdoc-ui/check.rs
@@ -1,5 +1,6 @@
 // check-pass
 // compile-flags: -Z unstable-options --check
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 
 #![warn(missing_docs)]
 //~^ WARN
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
index 2e1fc1eca4d6e..8c9e70e57fe7b 100644
--- a/src/test/rustdoc-ui/check.stderr
+++ b/src/test/rustdoc-ui/check.stderr
@@ -1,5 +1,5 @@
 warning: missing documentation for the crate
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -10,13 +10,13 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:4:9
+  --> $DIR/check.rs:5:9
    |
 LL | #![warn(missing_docs)]
    |         ^^^^^^^^^^^^
 
 warning: missing documentation for a function
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^
@@ -24,16 +24,16 @@ LL | pub fn foo() {}
 warning: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -44,14 +44,14 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
index 417618c74582c..9465e8e7ab996 100644
--- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
+++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Email me at <hello@localhost>.
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
index f287f87408c48..1b07828fc6e55 100644
--- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
+++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
@@ -1,16 +1,16 @@
 error: unknown disambiguator `hello`
-  --> $DIR/email-address-localhost.rs:3:18
+  --> $DIR/email-address-localhost.rs:4:18
    |
 LL | //! Email me at <hello@localhost>.
    |                  ^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/email-address-localhost.rs:1:9
+  --> $DIR/email-address-localhost.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to previous error
 
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
index 925fc515a3e65..0aa1e5a415aa7 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Linking to [foo@banana] and [`bar@banana!()`].
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
index 94d6d4616518e..d280e6497e096 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -1,56 +1,56 @@
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:3:17
+  --> $DIR/unknown-disambiguator.rs:4:17
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                 ^^^
    |
 note: the lint level is defined here
-  --> $DIR/unknown-disambiguator.rs:1:9
+  --> $DIR/unknown-disambiguator.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `bar`
-  --> $DIR/unknown-disambiguator.rs:3:35
+  --> $DIR/unknown-disambiguator.rs:4:35
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                                   ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:34
+  --> $DIR/unknown-disambiguator.rs:10:34
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                  ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:48
+  --> $DIR/unknown-disambiguator.rs:10:48
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                                ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:31
+  --> $DIR/unknown-disambiguator.rs:7:31
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                               ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:57
+  --> $DIR/unknown-disambiguator.rs:7:57
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                                                         ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
index 3939ec6827ade..a186410acf483 100644
--- a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
@@ -1,4 +1,5 @@
 // error-pattern: no documentation found
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(rustdoc::missing_crate_level_docs)]
 //^~ NOTE defined here
 
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
index 55ead1a55cfcd..1a1f8085a1b46 100644
--- a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
@@ -1,12 +1,12 @@
 error: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/no-crate-level-doc-lint.rs:2:9
+  --> $DIR/no-crate-level-doc-lint.rs:3:9
    |
 LL | #![deny(rustdoc::missing_crate_level_docs)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 error: aborting due to previous error
 
diff --git a/src/test/rustdoc/intra-doc/associated-items.rs b/src/test/rustdoc/intra-doc/associated-items.rs
index 2757418bc64e5..d9fed2d69518a 100644
--- a/src/test/rustdoc/intra-doc/associated-items.rs
+++ b/src/test/rustdoc/intra-doc/associated-items.rs
@@ -3,9 +3,9 @@
 /// [`std::collections::BTreeMap::into_iter`]
 /// [`String::from`] is ambiguous as to which `From` impl
 /// [Vec::into_iter()] uses a disambiguator
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/struct.String.html#method.from"]' 'String::from'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
 pub fn foo() {}
 
 /// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
diff --git a/src/test/rustdoc/intra-doc/builtin-macros.rs b/src/test/rustdoc/intra-doc/builtin-macros.rs
index 74216a587e1da..bbdbe246bbce2 100644
--- a/src/test/rustdoc/intra-doc/builtin-macros.rs
+++ b/src/test/rustdoc/intra-doc/builtin-macros.rs
@@ -1,3 +1,3 @@
 // @has builtin_macros/index.html
-// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html'
+// @has - '//a/@href' '{{channel}}/core/macro.cfg.html'
 //! [cfg]
diff --git a/src/test/rustdoc/intra-doc/field.rs b/src/test/rustdoc/intra-doc/field.rs
new file mode 100644
index 0000000000000..c67c40a77edbe
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/field.rs
@@ -0,0 +1,4 @@
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/ops/range/struct.Range.html#structfield.start"]' 'start'
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
+//! [start][std::ops::Range::start]
+//! [not_found][std::io::ErrorKind::NotFound]
diff --git a/src/test/rustdoc/intra-doc/generic-params.rs b/src/test/rustdoc/intra-doc/generic-params.rs
index 1de6410f10c43..fbc9fc6a9bc21 100644
--- a/src/test/rustdoc/intra-doc/generic-params.rs
+++ b/src/test/rustdoc/intra-doc/generic-params.rs
@@ -5,40 +5,40 @@
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html"]' 'Vec<T>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html"]' 'Vec<T>'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
+// @has foo/index.html '//a[@href="{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
 
 //! And what about a link to [just `Option`](Option) and, [with the generic, `Option<T>`](Option<T>)?
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'just Option'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option<T>'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'just Option'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'with the generic, Option<T>'
 
 //! We should also try linking to [`Result<T, E>`]; it has *two* generics!
 //! And [`Result<T, !>`] and [`Result<!, E>`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, E>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, !>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<!, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, !>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<!, E>'
 
 //! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
 //! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
 //! And what about something even harder? That would be [`Vec::<Box<T>>::new()`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
 
 //! This is also pretty tricky: [`TypeId::of::<String>()`].
 //! And this too: [`Vec::<std::error::Error>::len`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
+// @has foo/index.html '//a[@href="{{channel}}/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
 
 //! We unofficially and implicitly support things that aren't valid in the actual Rust syntax, like
 //! [`Box::<T>new()`]. We may not support them in the future!
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
 
 //! These will be resolved as regular links:
 //! - [`this is <invalid syntax> first`](https://www.rust-lang.org)
diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs
index ee71537d15531..be4b44b314252 100644
--- a/src/test/rustdoc/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs
@@ -2,45 +2,45 @@
 #![feature(intra_doc_pointers)]
 #![deny(rustdoc::broken_intra_doc_links)]
 
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
+// @has foo/index.html '//a[@href="{{channel}}/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
 //! [slice::rotate_left]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map'
+// @has - '//a[@href="{{channel}}/std/primitive.array.html#method.map"]' 'array::map'
 //! [array::map]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'owned str'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str ref'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.len"]' '&str::len'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.len"]' '&str::len'
 //! [owned str][str]
 //! [str ref][&str]
 //! [str::is_empty]
 //! [&str::len]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
 //! [pointer::is_null]
 //! [*const::is_null]
 //! [*mut::is_null]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit'
+// @has - '//a[@href="{{channel}}/std/primitive.unit.html"]' 'unit'
 //! [unit]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.tuple.html"]' 'tuple'
+// @has - '//a[@href="{{channel}}/std/primitive.tuple.html"]' 'tuple'
 //! [tuple]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' 'reference'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&mut'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' 'reference'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&mut'
 //! [reference]
 //! [&]
 //! [&mut]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.fn.html"]' 'fn'
+// @has - '//a[@href="{{channel}}/std/primitive.fn.html"]' 'fn'
 //! [fn]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' 'never'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' '!'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' 'never'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' '!'
 //! [never]
 //! [!]
diff --git a/src/test/rustdoc/intra-doc/prim-assoc.rs b/src/test/rustdoc/intra-doc/prim-assoc.rs
index 4099ececfaf7c..c73140420ff1f 100644
--- a/src/test/rustdoc/intra-doc/prim-assoc.rs
+++ b/src/test/rustdoc/intra-doc/prim-assoc.rs
@@ -1,4 +1,4 @@
 #![deny(broken_intra_doc_links)]
 
 //! [i32::MAX]
-// @has prim_assoc/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
+// @has prim_assoc/index.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
diff --git a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
index 695a7fbfb5348..9347d7bb42819 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
@@ -9,8 +9,8 @@
 #![crate_type = "rlib"]
 
 // @has prim_methods_external_core/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
diff --git a/src/test/rustdoc/intra-doc/prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs
index f0b939a468c03..124faa9a636ff 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-local.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs
@@ -5,8 +5,8 @@
 
 
 // @has prim_methods_local/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
diff --git a/src/test/rustdoc/intra-doc/prim-methods.rs b/src/test/rustdoc/intra-doc/prim-methods.rs
index 6de15e76d15cf..076117359d264 100644
--- a/src/test/rustdoc/intra-doc/prim-methods.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods.rs
@@ -2,7 +2,7 @@
 
 
 // @has prim_methods/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
diff --git a/src/test/rustdoc/intra-doc/prim-precedence.rs b/src/test/rustdoc/intra-doc/prim-precedence.rs
index 478b40b0b516f..fcd86a99f1d6b 100644
--- a/src/test/rustdoc/intra-doc/prim-precedence.rs
+++ b/src/test/rustdoc/intra-doc/prim-precedence.rs
@@ -2,12 +2,12 @@
 
 pub mod char {
     /// [char]
-    // @has prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+    // @has prim_precedence/char/struct.Inner.html '//a/@href' '{{channel}}/std/primitive.char.html'
     pub struct Inner;
 }
 
 /// See [prim@char]
-// @has prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+// @has prim_precedence/struct.MyString.html '//a/@href' '{{channel}}/std/primitive.char.html'
 pub struct MyString;
 
 /// See also [crate::char] and [mod@char]
diff --git a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
index acdd07566c94d..9b3b698324096 100644
--- a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
+++ b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
@@ -1,4 +1,4 @@
 #![deny(broken_intra_doc_links)]
 // @has primitive_disambiguators/index.html
-// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim'
+// @has - '//a/@href' '{{channel}}/std/primitive.str.html#method.trim'
 //! [str::trim()]
diff --git a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
index cf83ead4db72c..f8a824bd08f42 100644
--- a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
+++ b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
@@ -3,29 +3,29 @@
 
 // @has primitive_non_default_impl/fn.str_methods.html
 /// [`str::trim`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.trim"]' 'str::trim'
 /// [`str::to_lowercase`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
 /// [`str::into_boxed_bytes`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
 /// [`str::replace`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.replace"]' 'str::replace'
 pub fn str_methods() {}
 
 // @has primitive_non_default_impl/fn.f32_methods.html
 /// [f32::powi]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.powi"]' 'f32::powi'
 /// [f32::sqrt]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
 /// [f32::mul_add]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
 pub fn f32_methods() {}
 
 // @has primitive_non_default_impl/fn.f64_methods.html
 /// [`f64::powi`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.powi"]' 'f64::powi'
 /// [`f64::sqrt`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
 /// [`f64::mul_add`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
 pub fn f64_methods() {}
diff --git a/src/test/rustdoc/intra-doc/pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs
index 579fa68cee8be..b4f2d6b0617fa 100644
--- a/src/test/rustdoc/intra-doc/pub-use.rs
+++ b/src/test/rustdoc/intra-doc/pub-use.rs
@@ -12,7 +12,7 @@ extern crate inner;
 // documenting the re-export.
 
 // @has outer/index.html
-// @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/fn.var.html"]' "std::env"
+// @ has - '//a[@href="{{channel}}/std/env/fn.var.html"]' "std::env"
 // @ has - '//a[@href="fn.f.html"]' "g"
 pub use f as g;
 
@@ -23,5 +23,5 @@ extern crate self as _;
 // Make sure the documentation is actually correct by documenting an inlined re-export
 /// [mod@std::env]
 // @has outer/fn.f.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/index.html"]' "std::env"
+// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env"
 pub use inner::f;
diff --git a/src/test/rustdoc/intra-doc/trait-item.rs b/src/test/rustdoc/intra-doc/trait-item.rs
index 7602aced56416..0be368d051ee6 100644
--- a/src/test/rustdoc/intra-doc/trait-item.rs
+++ b/src/test/rustdoc/intra-doc/trait-item.rs
@@ -3,7 +3,7 @@
 /// Link to [S::assoc_fn()]
 /// Link to [Default::default()]
 // @has trait_item/struct.S.html '//*[@href="struct.S.html#method.assoc_fn"]' 'S::assoc_fn()'
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
+// @has - '//*[@href="{{channel}}/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
 pub struct S;
 
 impl S {
diff --git a/src/test/rustdoc/intra-doc/true-false.rs b/src/test/rustdoc/intra-doc/true-false.rs
index db637ece36995..44aac68841373 100644
--- a/src/test/rustdoc/intra-doc/true-false.rs
+++ b/src/test/rustdoc/intra-doc/true-false.rs
@@ -3,7 +3,7 @@
 
 
 // @has foo/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'true'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'false'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'true'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'false'
 
 //! A `bool` is either [`true`] or [`false`].
diff --git a/src/test/rustdoc/intra-link-prim-self.rs b/src/test/rustdoc/intra-link-prim-self.rs
index 1189d266c536e..4744c84b6226d 100644
--- a/src/test/rustdoc/intra-link-prim-self.rs
+++ b/src/test/rustdoc/intra-link-prim-self.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![deny(broken_intra_doc_links)]
 #![feature(lang_items)]
 #![feature(no_core)]
@@ -8,8 +7,8 @@
 /// [Self::f]
 /// [Self::MAX]
 // @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
 impl usize {
     /// Some docs
     pub fn f() {}
@@ -18,7 +17,7 @@ impl usize {
     pub const MAX: usize = 10;
 
     // FIXME(#8995) uncomment this when associated types in inherent impls are supported
-    // @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
+    // @ has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
     // / [Self::ME]
     //pub type ME = usize;
 }
diff --git a/src/test/rustdoc/primitive-link.rs b/src/test/rustdoc/primitive-link.rs
index dd455e45bfc2a..125e0c849731a 100644
--- a/src/test/rustdoc/primitive-link.rs
+++ b/src/test/rustdoc/primitive-link.rs
@@ -1,12 +1,12 @@
 #![crate_name = "foo"]
 
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i64.html"]' 'i64'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html"]' 'std::primitive::i32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.str.html"]' 'std::primitive::str'
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
 
 /// It contains [`u32`] and [i64].
 /// It also links to [std::primitive::i32], [std::primitive::str],
diff --git a/src/test/rustdoc/primitive-reexport.rs b/src/test/rustdoc/primitive-reexport.rs
index de18360d4077c..10a8a47db5248 100644
--- a/src/test/rustdoc/primitive-reexport.rs
+++ b/src/test/rustdoc/primitive-reexport.rs
@@ -5,24 +5,24 @@
 
 // @has bar/p/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub mod p {
     pub use foo::bar::*;
 }
 
 // @has bar/baz/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub use foo::bar as baz;
 
 // @has bar/index.html
 // @has - '//code' 'pub use str;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str'
+// @has - '//code/a[@href="{{channel}}/std/primitive.str.html"]' 'str'
 // @has - '//code' 'pub use i32 as my_i32;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'i32'
+// @has - '//code/a[@href="{{channel}}/std/primitive.i32.html"]' 'i32'
 pub use str;
 pub use i32 as my_i32;
diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs
index e69d0dab49642..c18cb881032a6 100644
--- a/src/test/ui/lint/lint-ctypes-fn.rs
+++ b/src/test/ui/lint/lint-ctypes-fn.rs
@@ -8,6 +8,8 @@ extern crate libc;
 use std::default::Default;
 use std::marker::PhantomData;
 
+trait Trait {}
+
 trait Mirror { type It: ?Sized; }
 
 impl<T: ?Sized> Mirror for T { type It = Self; }
@@ -74,6 +76,15 @@ pub extern "C" fn box_type(p: Box<u32>) { }
 
 pub extern "C" fn opt_box_type(p: Option<Box<u32>>) { }
 
+pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+//~^ ERROR: uses type `Box<[u8]>`
+
+pub extern "C" fn boxed_string(p: Box<str>) { }
+//~^ ERROR: uses type `Box<str>`
+
+pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+//~^ ERROR: uses type `Box<dyn Trait>`
+
 pub extern "C" fn char_type(p: char) { }
 //~^ ERROR uses type `char`
 
diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr
index e6a0778ddb25d..d591d4ad292dd 100644
--- a/src/test/ui/lint/lint-ctypes-fn.stderr
+++ b/src/test/ui/lint/lint-ctypes-fn.stderr
@@ -1,5 +1,5 @@
 error: `extern` fn uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:67:33
+  --> $DIR/lint-ctypes-fn.rs:69:33
    |
 LL | pub extern "C" fn slice_type(p: &[u32]) { }
    |                                 ^^^^^^ not FFI-safe
@@ -13,7 +13,7 @@ LL | #![deny(improper_ctypes_definitions)]
    = note: slices have no C equivalent
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:70:31
+  --> $DIR/lint-ctypes-fn.rs:72:31
    |
 LL | pub extern "C" fn str_type(p: &str) { }
    |                               ^^^^ not FFI-safe
@@ -21,8 +21,32 @@ LL | pub extern "C" fn str_type(p: &str) { }
    = help: consider using `*const u8` and a length instead
    = note: string slices have no C equivalent
 
+error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:79:34
+   |
+LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+   |                                  ^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<str>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:82:35
+   |
+LL | pub extern "C" fn boxed_string(p: Box<str>) { }
+   |                                   ^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:85:34
+   |
+LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+   |                                  ^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
 error: `extern` fn uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:77:32
+  --> $DIR/lint-ctypes-fn.rs:88:32
    |
 LL | pub extern "C" fn char_type(p: char) { }
    |                                ^^^^ not FFI-safe
@@ -31,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { }
    = note: the `char` type has no C equivalent
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:80:32
+  --> $DIR/lint-ctypes-fn.rs:91:32
    |
 LL | pub extern "C" fn i128_type(p: i128) { }
    |                                ^^^^ not FFI-safe
@@ -39,7 +63,7 @@ LL | pub extern "C" fn i128_type(p: i128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:83:32
+  --> $DIR/lint-ctypes-fn.rs:94:32
    |
 LL | pub extern "C" fn u128_type(p: u128) { }
    |                                ^^^^ not FFI-safe
@@ -47,7 +71,7 @@ LL | pub extern "C" fn u128_type(p: u128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:86:33
+  --> $DIR/lint-ctypes-fn.rs:97:33
    |
 LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    |                                 ^^^^^^^^^^ not FFI-safe
@@ -56,7 +80,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:89:34
+  --> $DIR/lint-ctypes-fn.rs:100:34
    |
 LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    |                                  ^^^^^^^ not FFI-safe
@@ -65,7 +89,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:92:32
+  --> $DIR/lint-ctypes-fn.rs:103:32
    |
 LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    |                                ^^^^^^^^ not FFI-safe
@@ -73,26 +97,26 @@ LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:26:1
+  --> $DIR/lint-ctypes-fn.rs:28:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:95:40
+  --> $DIR/lint-ctypes-fn.rs:106:40
    |
 LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:61:1
+  --> $DIR/lint-ctypes-fn.rs:63:1
    |
 LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:98:51
+  --> $DIR/lint-ctypes-fn.rs:109:51
    |
 LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    |                                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -100,7 +124,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:103:30
+  --> $DIR/lint-ctypes-fn.rs:114:30
    |
 LL | pub extern "C" fn fn_type(p: RustFn) { }
    |                              ^^^^^^ not FFI-safe
@@ -109,7 +133,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:106:31
+  --> $DIR/lint-ctypes-fn.rs:117:31
    |
 LL | pub extern "C" fn fn_type2(p: fn()) { }
    |                               ^^^^ not FFI-safe
@@ -118,7 +142,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:111:39
+  --> $DIR/lint-ctypes-fn.rs:122:39
    |
 LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    |                                       ^^^^^^^^^^^^^^^ not FFI-safe
@@ -126,7 +150,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:114:38
+  --> $DIR/lint-ctypes-fn.rs:125:38
    |
 LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    |                                      ^^^^^^^^^^^^^^ not FFI-safe
@@ -135,7 +159,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    = note: string slices have no C equivalent
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:160:43
+  --> $DIR/lint-ctypes-fn.rs:171:43
    |
 LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    |                                           ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -143,7 +167,7 @@ LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:173:39
+  --> $DIR/lint-ctypes-fn.rs:184:39
    |
 LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    |                                       ^^^^^^ not FFI-safe
@@ -152,7 +176,7 @@ LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    = note: this struct has unspecified layout
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:176:41
+  --> $DIR/lint-ctypes-fn.rs:187:41
    |
 LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    |                                         ^^^^^^ not FFI-safe
@@ -160,5 +184,5 @@ LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 
-error: aborting due to 17 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/simd/wasm-simd-indirect.rs b/src/test/ui/simd/wasm-simd-indirect.rs
new file mode 100644
index 0000000000000..deac593df43f1
--- /dev/null
+++ b/src/test/ui/simd/wasm-simd-indirect.rs
@@ -0,0 +1,33 @@
+// build-pass
+
+#![cfg_attr(target_arch = "wasm32", feature(wasm_simd, wasm_target_feature))]
+
+#[cfg(target_arch = "wasm32")]
+fn main() {
+    unsafe {
+        a::api_with_simd_feature();
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod a {
+    use std::arch::wasm32::*;
+
+    #[target_feature(enable = "simd128")]
+    pub unsafe fn api_with_simd_feature() {
+        crate::b::api_takes_v128(u64x2(0, 1));
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod b {
+    use std::arch::wasm32::*;
+
+    #[inline(never)]
+    pub fn api_takes_v128(a: v128) -> v128 {
+        a
+    }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn main() {}
diff --git a/src/test/ui/suggestions/format-borrow.rs b/src/test/ui/suggestions/format-borrow.rs
index 63930e7f787fd..599a79fc08af4 100644
--- a/src/test/ui/suggestions/format-borrow.rs
+++ b/src/test/ui/suggestions/format-borrow.rs
@@ -3,4 +3,8 @@ fn main() {
     //~^ ERROR mismatched types
     let b: String = &format!("b");
     //~^ ERROR mismatched types
+    let c: String = &mut format!("c");
+    //~^ ERROR mismatched types
+    let d: String = &mut (format!("d"));
+    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr
index 05d8fcd3ed64b..0881b024712c5 100644
--- a/src/test/ui/suggestions/format-borrow.stderr
+++ b/src/test/ui/suggestions/format-borrow.stderr
@@ -18,6 +18,26 @@ LL |     let b: String = &format!("b");
    |            |        help: consider removing the borrow: `format!("b")`
    |            expected due to this
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:6:21
+   |
+LL |     let c: String = &mut format!("c");
+   |            ------   ^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("c")`
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:8:21
+   |
+LL |     let d: String = &mut (format!("d"));
+   |            ------   ^^^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("d")`
+   |            expected due to this
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
new file mode 100644
index 0000000000000..390d8bbdd5326
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
@@ -0,0 +1,9 @@
+// Regression test for #85943: should not emit suggestions for adding
+// indirection to type parameters in where-clauses when suggesting
+// adding `?Sized`.
+struct A<T>(T) where T: Send;
+struct B(A<[u8]>);
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
new file mode 100644
index 0000000000000..735aeb0e0e799
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          - required by this bound in `A`
+LL | struct B(A<[u8]>);
+   |          ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          ^  - ...if indirection were used here: `Box<T>`
+   |          |
+   |          this could be changed to `T: ?Sized`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.