about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2025-07-21 09:18:22 +0300
committerLaurențiu Nicola <lnicola@dend.ro>2025-07-21 09:18:22 +0300
commit2f14119240acfe803f210a896aa31db8981be03c (patch)
treef9bb31bc973696b881279c87bb28854ae181fc50 /src/librustdoc
parent750c1e9c39633de1242acf086ef1c053961219b2 (diff)
parente05ab47e6c418fb2b9faa2eae9a7e70c65c98eaa (diff)
Merge from rust-lang/rust
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/librustdoc/clean/types.rs86
-rw-r--r--src/librustdoc/clean/utils.rs17
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/librustdoc/doctest/rust.rs2
-rw-r--r--src/librustdoc/formats/cache.rs4
-rw-r--r--src/librustdoc/formats/renderer.rs4
-rw-r--r--src/librustdoc/html/format.rs35
-rw-r--r--src/librustdoc/html/highlight.rs4
-rw-r--r--src/librustdoc/html/layout.rs1
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/render/context.rs88
-rw-r--r--src/librustdoc/html/render/mod.rs56
-rw-r--r--src/librustdoc/html/render/ordered_json.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs92
-rw-r--r--src/librustdoc/html/render/search_index.rs16
-rw-r--r--src/librustdoc/html/render/sidebar.rs2
-rw-r--r--src/librustdoc/html/render/sorted_template.rs3
-rw-r--r--src/librustdoc/html/render/write_shared.rs4
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts7
-rw-r--r--src/librustdoc/html/static/js/search.js150
-rw-r--r--src/librustdoc/html/url_parts_builder.rs12
-rw-r--r--src/librustdoc/json/conversions.rs119
-rw-r--r--src/librustdoc/json/mod.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs25
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs16
-rw-r--r--src/librustdoc/passes/strip_aliased_non_local.rs10
27 files changed, 404 insertions, 370 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e7a1f4d8397..1265a39d27b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -390,7 +390,8 @@ pub(crate) fn clean_predicate<'tcx>(
         ty::ClauseKind::ConstEvaluatable(..)
         | ty::ClauseKind::WellFormed(..)
         | ty::ClauseKind::ConstArgHasType(..)
-        // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `[const]`.
+        | ty::ClauseKind::UnstableFeature(..)
+        // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `~const`.
         | ty::ClauseKind::HostEffect(_) => None,
     }
 }
@@ -2864,7 +2865,7 @@ fn clean_maybe_renamed_item<'tcx>(
             ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
                 clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
             }
-            ItemKind::Trait(_, _, _, generics, bounds, item_ids) => {
+            ItemKind::Trait(_, _, _, _, generics, bounds, item_ids) => {
                 let items = item_ids
                     .iter()
                     .map(|&ti| clean_trait_item(cx.tcx.hir_trait_item(ti), cx))
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3ecd41db2dd..5ac5da24299 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -648,7 +648,7 @@ impl Item {
             let sig = tcx.fn_sig(def_id).skip_binder();
             let constness = if tcx.is_const_fn(def_id) {
                 // rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent
-                // or that have a `#[const_trait]` parent. Do not display those as `const` in rustdoc because we
+                // or that have a `const trait` parent. Do not display those as `const` in rustdoc because we
                 // won't be printing correct syntax plus the syntax is unstable.
                 match tcx.opt_associated_item(def_id) {
                     Some(ty::AssocItem {
@@ -759,79 +759,48 @@ impl Item {
         Some(tcx.visibility(def_id))
     }
 
-    fn attributes_without_repr(&self, tcx: TyCtxt<'_>, is_json: bool) -> Vec<String> {
-        const ALLOWED_ATTRIBUTES: &[Symbol] =
-            &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
+    /// Get a list of attributes excluding `#[repr]` to display.
+    ///
+    /// Only used by the HTML output-format.
+    fn attributes_without_repr(&self) -> Vec<String> {
         self.attrs
             .other_attrs
             .iter()
-            .filter_map(|attr| {
-                if let hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) = attr {
+            .filter_map(|attr| match attr {
+                hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) => {
                     Some(format!("#[link_section = \"{name}\"]"))
                 }
-                // NoMangle is special cased, as it appears in HTML output, and we want to show it in source form, not HIR printing.
-                // It is also used by cargo-semver-checks.
-                else if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr {
+                hir::Attribute::Parsed(AttributeKind::NoMangle(..)) => {
                     Some("#[no_mangle]".to_string())
-                } else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr
-                {
+                }
+                hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) => {
                     Some(format!("#[export_name = \"{name}\"]"))
-                } else if let hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) = attr {
+                }
+                hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) => {
                     Some("#[non_exhaustive]".to_string())
-                } else if is_json {
-                    match attr {
-                        // rustdoc-json stores this in `Item::deprecation`, so we
-                        // don't want it it `Item::attrs`.
-                        hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => None,
-                        // We have separate pretty-printing logic for `#[repr(..)]` attributes.
-                        hir::Attribute::Parsed(AttributeKind::Repr { .. }) => None,
-                        // target_feature is special-cased because cargo-semver-checks uses it
-                        hir::Attribute::Parsed(AttributeKind::TargetFeature(features, _)) => {
-                            let mut output = String::new();
-                            for (i, (feature, _)) in features.iter().enumerate() {
-                                if i != 0 {
-                                    output.push_str(", ");
-                                }
-                                output.push_str(&format!("enable=\"{}\"", feature.as_str()));
-                            }
-                            Some(format!("#[target_feature({output})]"))
-                        }
-                        hir::Attribute::Parsed(AttributeKind::AutomaticallyDerived(..)) => {
-                            Some("#[automatically_derived]".to_string())
-                        }
-                        _ => Some({
-                            let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr);
-                            assert_eq!(s.pop(), Some('\n'));
-                            s
-                        }),
-                    }
-                } else {
-                    if !attr.has_any_name(ALLOWED_ATTRIBUTES) {
-                        return None;
-                    }
-                    Some(
-                        rustc_hir_pretty::attribute_to_string(&tcx, attr)
-                            .replace("\\\n", "")
-                            .replace('\n', "")
-                            .replace("  ", " "),
-                    )
                 }
+                _ => None,
             })
             .collect()
     }
 
-    pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
-        let mut attrs = self.attributes_without_repr(tcx, is_json);
+    /// Get a list of attributes to display on this item.
+    ///
+    /// Only used by the HTML output-format.
+    pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache) -> Vec<String> {
+        let mut attrs = self.attributes_without_repr();
 
-        if let Some(repr_attr) = self.repr(tcx, cache, is_json) {
+        if let Some(repr_attr) = self.repr(tcx, cache) {
             attrs.push(repr_attr);
         }
         attrs
     }
 
     /// Returns a stringified `#[repr(...)]` attribute.
-    pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Option<String> {
-        repr_attributes(tcx, cache, self.def_id()?, self.type_(), is_json)
+    ///
+    /// Only used by the HTML output-format.
+    pub(crate) fn repr(&self, tcx: TyCtxt<'_>, cache: &Cache) -> Option<String> {
+        repr_attributes(tcx, cache, self.def_id()?, self.type_())
     }
 
     pub fn is_doc_hidden(&self) -> bool {
@@ -843,12 +812,14 @@ impl Item {
     }
 }
 
+/// Return a string representing the `#[repr]` attribute if present.
+///
+/// Only used by the HTML output-format.
 pub(crate) fn repr_attributes(
     tcx: TyCtxt<'_>,
     cache: &Cache,
     def_id: DefId,
     item_type: ItemType,
-    is_json: bool,
 ) -> Option<String> {
     use rustc_abi::IntegerType;
 
@@ -865,7 +836,6 @@ pub(crate) fn repr_attributes(
         // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
         // field is public in case all fields are 1-ZST fields.
         let render_transparent = cache.document_private
-            || is_json
             || adt
                 .all_fields()
                 .find(|field| {
@@ -1707,7 +1677,7 @@ impl Type {
         }
     }
 
-    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
         match self {
             Type::Path { path, .. } => path.generics(),
             _ => None,
@@ -2257,7 +2227,7 @@ impl Path {
         self.segments.last().map(|seg| &seg.args)
     }
 
-    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
         self.segments.last().and_then(|seg| {
             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
                 Some(args.iter().filter_map(|arg| match arg {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index bf3f7607274..813fdee57e1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -3,6 +3,7 @@ use std::fmt::{self, Display, Write as _};
 use std::sync::LazyLock as Lazy;
 use std::{ascii, mem};
 
+use rustc_ast::join_path_idents;
 use rustc_ast::tokenstream::TokenTree;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
@@ -24,7 +25,7 @@ use crate::clean::{
     clean_middle_ty, inline,
 };
 use crate::core::DocContext;
-use crate::display::{Joined as _, MaybeDisplay as _};
+use crate::display::Joined as _;
 
 #[cfg(test)]
 mod tests;
@@ -251,13 +252,7 @@ pub(crate) fn qpath_to_string(p: &hir::QPath<'_>) -> String {
         hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
     };
 
-    fmt::from_fn(|f| {
-        segments
-            .iter()
-            .map(|seg| (seg.ident.name != kw::PathRoot).then_some(seg.ident).maybe_display())
-            .joined("::", f)
-    })
-    .to_string()
+    join_path_idents(segments.iter().map(|seg| seg.ident))
 }
 
 pub(crate) fn build_deref_target_impls(
@@ -348,13 +343,11 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
     match n.kind() {
         ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
-            let s = if let Some(def) = def.as_local() {
+            if let Some(def) = def.as_local() {
                 rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def)
             } else {
                 inline::print_inlined_const(cx.tcx, def)
-            };
-
-            s
+            }
         }
         // array lengths are obviously usize
         ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 9b4d2533954..38ba6b4503d 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -632,7 +632,7 @@ fn run_test(
         // the user to exploit nightly-only features on stable
         runner_compiler.env("RUSTC_BOOTSTRAP", "1");
         runner_compiler.args(compiler_args);
-        runner_compiler.args(&["--crate-type=bin", "-o"]).arg(&output_file);
+        runner_compiler.args(["--crate-type=bin", "-o"]).arg(&output_file);
         let mut extern_path = std::ffi::OsString::from(format!(
             "--extern=doctest_bundle_{edition}=",
             edition = doctest.edition
@@ -657,7 +657,7 @@ fn run_test(
         extern_path.push(&output_bundle_file);
         runner_compiler.arg(extern_path);
         runner_compiler.arg(&runner_input_file);
-        if std::fs::write(&runner_input_file, &merged_test_code).is_err() {
+        if std::fs::write(&runner_input_file, merged_test_code).is_err() {
             // If we cannot write this file for any reason, we leave. All combined tests will be
             // tested as standalone tests.
             return Err(TestFailure::CompileError);
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 96975105ac5..f5ec828187a 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -140,7 +140,7 @@ impl HirCollector<'_> {
                 .iter()
                 .filter(|a| a.has_name(sym::attr))
                 .flat_map(|a| a.meta_item_list().unwrap_or_default())
-                .map(|i| pprust::meta_list_item_to_string(i))
+                .map(pprust::meta_list_item_to_string)
             {
                 // Add the additional attributes to the global_crate_attrs vector
                 self.collector.global_crate_attrs.push(attr);
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 4989bd718c9..5191120ebdb 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -1,5 +1,6 @@
 use std::mem;
 
+use rustc_ast::join_path_syms;
 use rustc_attr_data_structures::StabilityLevel;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
@@ -13,7 +14,6 @@ use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::formats::Impl;
 use crate::formats::item_type::ItemType;
-use crate::html::format::join_with_double_colon;
 use crate::html::markdown::short_markdown_summary;
 use crate::html::render::IndexItem;
 use crate::html::render::search_index::get_function_type_for_search;
@@ -558,7 +558,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
         clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
         _ => item_def_id,
     };
-    let path = join_with_double_colon(parent_path);
+    let path = join_path_syms(parent_path);
     let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
         item_id.as_def_id()
     } else {
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 79ff1fa38c3..aa4be4db997 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -81,7 +81,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
         let _timer =
             prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
 
-        cx.mod_item_in(&item)?;
+        cx.mod_item_in(item)?;
         let (clean::StrippedItem(box clean::ModuleItem(ref module))
         | clean::ModuleItem(ref module)) = item.inner.kind
         else {
@@ -99,7 +99,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
     } else if let Some(item_name) = item.name
         && !item.is_extern_crate()
     {
-        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(&item))?;
+        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
     }
     Ok(())
 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index bcb3e57c844..be8a2d511e9 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -14,6 +14,7 @@ use std::slice;
 
 use itertools::{Either, Itertools};
 use rustc_abi::ExternAbi;
+use rustc_ast::join_path_syms;
 use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
@@ -25,7 +26,7 @@ use rustc_span::symbol::kw;
 use rustc_span::{Symbol, sym};
 use tracing::{debug, trace};
 
-use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
+use super::url_parts_builder::UrlPartsBuilder;
 use crate::clean::types::ExternalLocation;
 use crate::clean::utils::find_nearest_parent_module;
 use crate::clean::{self, ExternalCrate, PrimitiveType};
@@ -113,9 +114,9 @@ impl clean::Generics {
             let real_params =
                 fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f));
             if f.alternate() {
-                write!(f, "<{:#}>", real_params)
+                write!(f, "<{real_params:#}>")
             } else {
-                write!(f, "&lt;{}&gt;", real_params)
+                write!(f, "&lt;{real_params}&gt;")
             }
         })
     }
@@ -369,18 +370,6 @@ pub(crate) enum HrefError {
     NotInExternalCache,
 }
 
-// Panics if `syms` is empty.
-pub(crate) fn join_with_double_colon(syms: &[Symbol]) -> String {
-    let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len()));
-    // NOTE: using `Joined::joined` here causes a noticeable perf regression
-    s.push_str(syms[0].as_str());
-    for sym in &syms[1..] {
-        s.push_str("::");
-        s.push_str(sym.as_str());
-    }
-    s
-}
-
 /// This function is to get the external macro path because they are not in the cache used in
 /// `href_with_root_path`.
 fn generate_macro_def_id_path(
@@ -605,7 +594,7 @@ pub(crate) fn href_with_root_path(
             }
         }
     };
-    let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
+    let url_parts = make_href(root_path, shortty, url_parts, fqp, is_remote);
     Ok((url_parts, shortty, fqp.clone()))
 }
 
@@ -672,7 +661,7 @@ pub(crate) fn link_tooltip(
             write!(f, "{}", cx.tcx().item_name(id))?;
         } else if !fqp.is_empty() {
             write!(f, "{shortty} ")?;
-            fqp.iter().joined("::", f)?;
+            write!(f, "{}", join_path_syms(fqp))?;
         }
         Ok(())
     })
@@ -703,7 +692,7 @@ fn resolved_path(
                     write!(
                         f,
                         "{path}::{anchor}",
-                        path = join_with_double_colon(&fqp[..fqp.len() - 1]),
+                        path = join_path_syms(&fqp[..fqp.len() - 1]),
                         anchor = print_anchor(did, *fqp.last().unwrap(), cx)
                     )
                 } else {
@@ -835,7 +824,7 @@ pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl D
             write!(
                 f,
                 r#"<a class="{short_ty}" href="{url}" title="{short_ty} {path}">{text}</a>"#,
-                path = join_with_double_colon(&fqp),
+                path = join_path_syms(fqp),
                 text = EscapeBodyText(text.as_str()),
             )
         } else {
@@ -1095,7 +1084,7 @@ impl clean::QPathData {
                                     title=\"type {path}::{name}\">{name}</a>",
                         shortty = ItemType::AssocType,
                         name = assoc.name,
-                        path = join_with_double_colon(&path),
+                        path = join_path_syms(path),
                     )
                 } else {
                     write!(f, "{}", assoc.name)
@@ -1126,7 +1115,7 @@ impl clean::Impl {
                 {
                     let last = ty.last();
                     if f.alternate() {
-                        write!(f, "{}<", last)?;
+                        write!(f, "{last}<")?;
                         self.print_type(inner_type, f, use_absolute, cx)?;
                         write!(f, ">")?;
                     } else {
@@ -1230,7 +1219,7 @@ pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> imp
             .map(|param| {
                 fmt::from_fn(|f| {
                     if let Some(name) = param.name {
-                        write!(f, "{}: ", name)?;
+                        write!(f, "{name}: ")?;
                     }
                     param.type_.print(cx).fmt(f)
                 })
@@ -1352,7 +1341,7 @@ impl clean::FnDecl {
                     write!(f, "const ")?;
                 }
                 if let Some(name) = param.name {
-                    write!(f, "{}: ", name)?;
+                    write!(f, "{name}: ")?;
                 }
                 param.type_.print(cx).fmt(f)?;
             }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b2feee36c93..272180fb990 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -547,7 +547,7 @@ impl<'a> Iterator for TokenIter<'a> {
 fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> {
     let ignore: &[&str] =
         if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
-    if ignore.iter().any(|k| *k == text) {
+    if ignore.contains(&text) {
         return None;
     }
     Some(match text {
@@ -1159,7 +1159,7 @@ fn string_without_closing_tag<T: Display>(
         return Some("</a>");
     }
     if !open_tag {
-        write!(out, "{}", text_s).unwrap();
+        out.write_str(&text_s).unwrap();
         return None;
     }
     let klass_s = klass.as_html();
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 50320cb231d..1f92c521d46 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -132,6 +132,5 @@ pub(crate) fn redirect(url: &str) -> String {
     <script>location.replace("{url}" + location.search + location.hash);</script>
 </body>
 </html>"##,
-        url = url,
     )
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e41435de29c..4addf2c3c96 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -251,7 +251,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                     if !parse_result.rust {
                         let added_classes = parse_result.added_classes;
                         let lang_string = if let Some(lang) = parse_result.unknown.first() {
-                            format!("language-{}", lang)
+                            format!("language-{lang}")
                         } else {
                             String::new()
                         };
@@ -999,7 +999,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> {
 
         if let Some((_, c)) = self.inner.next() {
             if c != '=' {
-                self.emit_error(format!("expected `=`, found `{}`", c));
+                self.emit_error(format!("expected `=`, found `{c}`"));
                 return None;
             }
         } else {
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 3b4dae841ee..5ceb1fc988d 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
 use std::sync::mpsc::{Receiver, channel};
 
 use askama::Template;
+use rustc_ast::join_path_syms;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
 use rustc_middle::ty::TyCtxt;
@@ -27,7 +28,6 @@ use crate::formats::FormatRenderer;
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
-use crate::html::format::join_with_double_colon;
 use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
 use crate::html::render::write_shared::write_shared;
 use crate::html::url_parts_builder::UrlPartsBuilder;
@@ -193,14 +193,12 @@ impl<'tcx> Context<'tcx> {
         if it.is_stripped()
             && let Some(def_id) = it.def_id()
             && def_id.is_local()
+            && (self.info.is_inside_inlined_module
+                || self.shared.cache.inlined_items.contains(&def_id))
         {
-            if self.info.is_inside_inlined_module
-                || self.shared.cache.inlined_items.contains(&def_id)
-            {
-                // For now we're forced to generate a redirect page for stripped items until
-                // `record_extern_fqn` correctly points to external items.
-                render_redirect_pages = true;
-            }
+            // For now we're forced to generate a redirect page for stripped items until
+            // `record_extern_fqn` correctly points to external items.
+            render_redirect_pages = true;
         }
         let mut title = String::new();
         if !is_module {
@@ -211,7 +209,7 @@ impl<'tcx> Context<'tcx> {
                 title.push_str(" in ");
             }
             // No need to include the namespace for primitive types and keywords
-            title.push_str(&join_with_double_colon(&self.current));
+            title.push_str(&join_path_syms(&self.current));
         };
         title.push_str(" - Rust");
         let tyname = it.type_();
@@ -254,40 +252,36 @@ impl<'tcx> Context<'tcx> {
                 &self.shared.style_files,
             )
         } else {
-            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
-                if self.current.len() + 1 != names.len()
-                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
-                {
-                    // We checked that the redirection isn't pointing to the current file,
-                    // preventing an infinite redirection loop in the generated
-                    // documentation.
-
-                    let path = fmt::from_fn(|f| {
-                        for name in &names[..names.len() - 1] {
-                            write!(f, "{name}/")?;
-                        }
-                        write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
-                    });
-                    match self.shared.redirections {
-                        Some(ref redirections) => {
-                            let mut current_path = String::new();
-                            for name in &self.current {
-                                current_path.push_str(name.as_str());
-                                current_path.push('/');
-                            }
-                            let _ = write!(
-                                current_path,
-                                "{}",
-                                print_item_path(ty, names.last().unwrap().as_str())
-                            );
-                            redirections.borrow_mut().insert(current_path, path.to_string());
-                        }
-                        None => {
-                            return layout::redirect(&format!(
-                                "{root}{path}",
-                                root = self.root_path()
-                            ));
+            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id())
+                && (self.current.len() + 1 != names.len()
+                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b))
+            {
+                // We checked that the redirection isn't pointing to the current file,
+                // preventing an infinite redirection loop in the generated
+                // documentation.
+
+                let path = fmt::from_fn(|f| {
+                    for name in &names[..names.len() - 1] {
+                        write!(f, "{name}/")?;
+                    }
+                    write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
+                });
+                match self.shared.redirections {
+                    Some(ref redirections) => {
+                        let mut current_path = String::new();
+                        for name in &self.current {
+                            current_path.push_str(name.as_str());
+                            current_path.push('/');
                         }
+                        let _ = write!(
+                            current_path,
+                            "{}",
+                            print_item_path(ty, names.last().unwrap().as_str())
+                        );
+                        redirections.borrow_mut().insert(current_path, path.to_string());
+                    }
+                    None => {
+                        return layout::redirect(&format!("{root}{path}", root = self.root_path()));
                     }
                 }
             }
@@ -762,11 +756,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         // Flush pending errors.
         self.shared.fs.close();
         let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
-        if nb_errors > 0 {
-            Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
-        } else {
-            Ok(())
-        }
+        if nb_errors > 0 { Err(Error::new(io::Error::other("I/O error"), "")) } else { Ok(()) }
     }
 
     fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
@@ -842,7 +832,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             self.info.render_redirect_pages = item.is_stripped();
         }
 
-        let buf = self.render_item(&item, false);
+        let buf = self.render_item(item, false);
         // buf will be empty if the item is stripped and there is no redirect for it
         if !buf.is_empty() {
             let name = item.name.as_ref().unwrap();
@@ -853,7 +843,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             self.shared.fs.write(joint_dst, buf)?;
 
             if !self.info.render_redirect_pages {
-                self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
+                self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
             }
             // If the item is a macro, redirect from the old macro URL (with !)
             // to the new one (without).
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 70f3f54e4c0..872dbbcd19e 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -49,6 +49,7 @@ use std::{fs, str};
 
 use askama::Template;
 use itertools::Either;
+use rustc_ast::join_path_syms;
 use rustc_attr_data_structures::{
     ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
 };
@@ -74,9 +75,9 @@ use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
 use crate::html::format::{
-    Ending, HrefError, PrintWithSpace, href, join_with_double_colon, print_abi_with_space,
-    print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause,
-    visibility_print_with_space, write_str,
+    Ending, HrefError, PrintWithSpace, href, print_abi_with_space, print_constness_with_space,
+    print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
+    write_str,
 };
 use crate::html::markdown::{
     HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine,
@@ -1109,7 +1110,7 @@ fn since_to_string(since: &StableSince) -> Option<String> {
     match since {
         StableSince::Version(since) => Some(since.to_string()),
         StableSince::Current => Some(RustcVersion::CURRENT.to_string()),
-        StableSince::Err => None,
+        StableSince::Err(_) => None,
     }
 }
 
@@ -1191,7 +1192,7 @@ fn render_assoc_item(
 // a whitespace prefix and newline.
 fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
     fmt::from_fn(move |f| {
-        for a in it.attributes(cx.tcx(), cx.cache(), false) {
+        for a in it.attributes(cx.tcx(), cx.cache()) {
             writeln!(f, "{prefix}{a}")?;
         }
         Ok(())
@@ -1207,7 +1208,7 @@ fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
 // When an attribute is rendered inside a <code> tag, it is formatted using
 // a div to produce a newline after it.
 fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
-    for attr in it.attributes(cx.tcx(), cx.cache(), false) {
+    for attr in it.attributes(cx.tcx(), cx.cache()) {
         render_code_attribute(CodeAttribute(attr), w);
     }
 }
@@ -1219,7 +1220,7 @@ fn render_repr_attributes_in_code(
     def_id: DefId,
     item_type: ItemType,
 ) {
-    if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type, false) {
+    if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
         render_code_attribute(CodeAttribute(repr), w);
     }
 }
@@ -1482,10 +1483,10 @@ fn render_deref_methods(
             }
         }
         render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
-    } else if let Some(prim) = target.primitive_type() {
-        if let Some(&did) = cache.primitive_locations.get(&prim) {
-            render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
-        }
+    } else if let Some(prim) = target.primitive_type()
+        && let Some(&did) = cache.primitive_locations.get(&prim)
+    {
+        render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
     }
 }
 
@@ -2057,21 +2058,20 @@ fn render_impl(
         // default items which weren't overridden in the implementation block.
         // We don't emit documentation for default items if they appear in the
         // Implementations on Foreign Types or Implementors sections.
-        if rendering_params.show_default_items {
-            if let Some(t) = trait_
-                && !impl_.is_negative_trait_impl()
-            {
-                render_default_items(
-                    &mut default_impl_items,
-                    &mut impl_items,
-                    cx,
-                    t,
-                    impl_,
-                    &i.impl_item,
-                    render_mode,
-                    rendering_params,
-                )?;
-            }
+        if rendering_params.show_default_items
+            && let Some(t) = trait_
+            && !impl_.is_negative_trait_impl()
+        {
+            render_default_items(
+                &mut default_impl_items,
+                &mut impl_items,
+                cx,
+                t,
+                impl_,
+                &i.impl_item,
+                render_mode,
+                rendering_params,
+            )?;
         }
         if render_mode == RenderMode::Normal {
             let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
@@ -2555,7 +2555,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String>
         let fqp = cache.exact_paths.get(&did).or_else(get_extern);
 
         if let Some(path) = fqp {
-            out.push(join_with_double_colon(path));
+            out.push(join_path_syms(path));
         }
     };
 
@@ -2569,7 +2569,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String>
         match ty {
             clean::Type::Path { path } => process_path(path.def_id()),
             clean::Type::Tuple(tys) => {
-                work.extend(tys.into_iter());
+                work.extend(tys.iter());
             }
             clean::Type::Slice(ty) => {
                 work.push_back(ty);
diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs
index d1dddfebc83..be51dad1c2b 100644
--- a/src/librustdoc/html/render/ordered_json.rs
+++ b/src/librustdoc/html/render/ordered_json.rs
@@ -25,7 +25,7 @@ impl OrderedJson {
             .into_iter()
             .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow()))
             .format_with(",", |item, f| f(item.borrow()));
-        Self(format!("[{}]", items))
+        Self(format!("[{items}]"))
     }
 
     pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index e33bdc0db32..02ee34aaac6 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -4,6 +4,7 @@ use std::iter;
 
 use askama::Template;
 use rustc_abi::VariantIdx;
+use rustc_ast::join_path_syms;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -30,8 +31,8 @@ use crate::formats::Impl;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
 use crate::html::format::{
-    Ending, PrintWithSpace, join_with_double_colon, print_abi_with_space,
-    print_constness_with_space, print_where_clause, visibility_print_with_space,
+    Ending, PrintWithSpace, print_abi_with_space, print_constness_with_space, print_where_clause,
+    visibility_print_with_space,
 };
 use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
 use crate::html::render::{document_full, document_item_info};
@@ -1424,7 +1425,7 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) ->
                 iter::repeat_n("..", cx.current.len()).chain(iter::once("type.impl")).collect();
             js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
             js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
-            let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
+            let self_path = join_path_syms(self_fqp);
             write!(
                 w,
                 "<script src=\"{src}\" data-self-path=\"{self_path}\" async></script>",
@@ -1450,7 +1451,7 @@ item_template!(
 
 impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
     fn render_union(&self) -> impl Display {
-        render_union(self.it, Some(&self.generics), &self.fields, self.cx)
+        render_union(self.it, Some(self.generics), self.fields, self.cx)
     }
 
     fn document_field(&self, field: &'a clean::Item) -> impl Display {
@@ -1487,12 +1488,11 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
                     self.cx.cache(),
                     self.def_id,
                     ItemType::Union,
-                    false,
                 ) {
                     writeln!(f, "{repr}")?;
                 };
             } else {
-                for a in self.it.attributes(self.cx.tcx(), self.cx.cache(), false) {
+                for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) {
                     writeln!(f, "{a}")?;
                 }
             }
@@ -1982,16 +1982,14 @@ fn item_constant(
                 w.write_str(";")?;
             }
 
-            if !is_literal {
-                if let Some(value) = &value {
-                    let value_lowercase = value.to_lowercase();
-                    let expr_lowercase = expr.to_lowercase();
+            if !is_literal && let Some(value) = &value {
+                let value_lowercase = value.to_lowercase();
+                let expr_lowercase = expr.to_lowercase();
 
-                    if value_lowercase != expr_lowercase
-                        && value_lowercase.trim_end_matches("i32") != expr_lowercase
-                    {
-                        write!(w, " // {value}", value = Escape(value))?;
-                    }
+                if value_lowercase != expr_lowercase
+                    && value_lowercase.trim_end_matches("i32") != expr_lowercase
+                {
+                    write!(w, " // {value}", value = Escape(value))?;
                 }
             }
             Ok::<(), fmt::Error>(())
@@ -2071,41 +2069,39 @@ fn item_fields(
                 _ => None,
             })
             .peekable();
-        if let None | Some(CtorKind::Fn) = ctor_kind {
-            if fields.peek().is_some() {
-                let title = format!(
-                    "{}{}",
-                    if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
-                    document_non_exhaustive_header(it),
-                );
+        if let None | Some(CtorKind::Fn) = ctor_kind
+            && fields.peek().is_some()
+        {
+            let title = format!(
+                "{}{}",
+                if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
+                document_non_exhaustive_header(it),
+            );
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    &title,
+                    "fields",
+                    Some("fields"),
+                    document_non_exhaustive(it)
+                )
+            )?;
+            for (index, (field, ty)) in fields.enumerate() {
+                let field_name =
+                    field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
+                let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
                 write!(
                     w,
-                    "{}",
-                    write_section_heading(
-                        &title,
-                        "fields",
-                        Some("fields"),
-                        document_non_exhaustive(it)
-                    )
+                    "<span id=\"{id}\" class=\"{item_type} section-header\">\
+                        <a href=\"#{id}\" class=\"anchor field\">§</a>\
+                        <code>{field_name}: {ty}</code>\
+                    </span>\
+                    {doc}",
+                    item_type = ItemType::StructField,
+                    ty = ty.print(cx),
+                    doc = document(cx, field, Some(it), HeadingOffset::H3),
                 )?;
-                for (index, (field, ty)) in fields.enumerate() {
-                    let field_name = field
-                        .name
-                        .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
-                    let id =
-                        cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
-                    write!(
-                        w,
-                        "<span id=\"{id}\" class=\"{item_type} section-header\">\
-                            <a href=\"#{id}\" class=\"anchor field\">§</a>\
-                            <code>{field_name}: {ty}</code>\
-                        </span>\
-                        {doc}",
-                        item_type = ItemType::StructField,
-                        ty = ty.print(cx),
-                        doc = document(cx, field, Some(it), HeadingOffset::H3),
-                    )?;
-                }
             }
         }
         Ok(())
@@ -2257,7 +2253,7 @@ pub(crate) fn compare_names(left: &str, right: &str) -> Ordering {
 }
 
 pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
-    let mut s = join_with_double_colon(&cx.current);
+    let mut s = join_path_syms(&cx.current);
     s.push_str("::");
     s.push_str(item.name.unwrap().as_str());
     s
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index aff8684ee3a..3c9be29ccc3 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -4,6 +4,7 @@ use std::collections::hash_map::Entry;
 use std::collections::{BTreeMap, VecDeque};
 
 use encode::{bitmap_to_string, write_vlqhex_to_string};
+use rustc_ast::join_path_syms;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::DefId;
@@ -17,7 +18,6 @@ use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate};
 use crate::clean::{self, utils};
 use crate::formats::cache::{Cache, OrphanImplItem};
 use crate::formats::item_type::ItemType;
-use crate::html::format::join_with_double_colon;
 use crate::html::markdown::short_markdown_summary;
 use crate::html::render::ordered_json::OrderedJson;
 use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId};
@@ -78,7 +78,7 @@ pub(crate) fn build_index(
                 ty: item.type_(),
                 defid: item.item_id.as_def_id(),
                 name: item.name.unwrap(),
-                path: join_with_double_colon(&fqp[..fqp.len() - 1]),
+                path: join_path_syms(&fqp[..fqp.len() - 1]),
                 desc,
                 parent: Some(parent),
                 parent_idx: None,
@@ -116,7 +116,7 @@ pub(crate) fn build_index(
     // Set up alias indexes.
     for (i, item) in cache.search_index.iter().enumerate() {
         for alias in &item.aliases[..] {
-            aliases.entry(alias.as_str().to_lowercase()).or_default().push(i);
+            aliases.entry(alias.to_string()).or_default().push(i);
         }
     }
 
@@ -416,7 +416,7 @@ pub(crate) fn build_index(
                             if fqp.len() < 2 {
                                 return None;
                             }
-                            join_with_double_colon(&fqp[..fqp.len() - 1])
+                            join_path_syms(&fqp[..fqp.len() - 1])
                         };
                     if path == item.path {
                         return None;
@@ -427,10 +427,10 @@ pub(crate) fn build_index(
                 let i = <isize as TryInto<usize>>::try_into(parent_idx).unwrap();
                 item.path = {
                     let p = &crate_paths[i].1;
-                    join_with_double_colon(&p[..p.len() - 1])
+                    join_path_syms(&p[..p.len() - 1])
                 };
                 item.exact_path =
-                    crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1]));
+                    crate_paths[i].2.as_ref().map(|xp| join_path_syms(&xp[..xp.len() - 1]));
             }
 
             // Omit the parent path if it is same to that of the prior item.
@@ -549,11 +549,11 @@ pub(crate) fn build_index(
                     });
                     continue;
                 }
-                let full_path = join_with_double_colon(&path[..path.len() - 1]);
+                let full_path = join_path_syms(&path[..path.len() - 1]);
                 let full_exact_path = exact
                     .as_ref()
                     .filter(|exact| exact.last() == path.last() && exact.len() >= 2)
-                    .map(|exact| join_with_double_colon(&exact[..exact.len() - 1]));
+                    .map(|exact| join_path_syms(&exact[..exact.len() - 1]));
                 let exact_path = extra_paths.len() + self.items.len();
                 let exact_path = full_exact_path.as_ref().map(|full_exact_path| match extra_paths
                     .entry(full_exact_path.clone())
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 91540e06e33..b9f5ada417c 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -541,7 +541,7 @@ fn sidebar_deref_methods<'a>(
                 .iter()
                 .filter(|i| {
                     i.inner_impl().trait_.is_none()
-                        && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c)
+                        && real_target.is_doc_subtype_of(&i.inner_impl().for_, c)
                 })
                 .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
                 .collect::<Vec<_>>();
diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs
index a7b954ab70b..659c5e6093b 100644
--- a/src/librustdoc/html/render/sorted_template.rs
+++ b/src/librustdoc/html/render/sorted_template.rs
@@ -63,7 +63,8 @@ impl<F: FileFormat> fmt::Display for SortedTemplate<F> {
         for (p, fragment) in self.fragments.iter().with_position() {
             let mut f = DeltaWriter { inner: &mut f, delta: 0 };
             let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR };
-            write!(f, "{}{}", sep, fragment)?;
+            f.write_str(sep)?;
+            f.write_str(fragment)?;
             fragment_lengths.push(f.delta);
         }
         let offset = Offset { start: self.before.len(), fragment_lengths };
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 0078671fcc5..1f691392b17 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -26,6 +26,7 @@ use std::{fmt, fs};
 
 use indexmap::IndexMap;
 use regex::Regex;
+use rustc_ast::join_path_syms;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_middle::ty::TyCtxt;
@@ -43,7 +44,6 @@ use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::Impl;
 use crate::formats::item_type::ItemType;
-use crate::html::format::join_with_double_colon;
 use crate::html::layout;
 use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
 use crate::html::render::search_index::{SerializedSearchIndex, build_index};
@@ -608,7 +608,7 @@ impl TypeAliasPart {
                     for &(type_alias_fqp, type_alias_item) in type_aliases {
                         cx.id_map.borrow_mut().clear();
                         cx.deref_id_map.borrow_mut().clear();
-                        let type_alias_fqp = join_with_double_colon(&type_alias_fqp);
+                        let type_alias_fqp = join_path_syms(type_alias_fqp);
                         if let Some(ret) = &mut ret {
                             ret.aliases.push(type_alias_fqp);
                         } else {
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index ca2512e5ab6..a9589764547 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -219,6 +219,8 @@ declare namespace rustdoc {
         crate: string,
         descShard: SearchDescShard,
         id: number,
+        // This is the name of the item. For doc aliases, if you want the name of the aliased
+        // item, take a look at `Row.original.name`.
         name: string,
         normalizedName: string,
         word: string,
@@ -227,6 +229,11 @@ declare namespace rustdoc {
         path: string,
         ty: number,
         type: FunctionSearchType | null,
+        descIndex: number,
+        bitIndex: number,
+        implDisambiguator: String | null,
+        is_alias?: boolean,
+        original?: Row,
     }
 
     /**
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 15cad31f555..2caf214ff73 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -830,7 +830,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) {
  */
 function makePrimitiveElement(name, extra) {
     return Object.assign({
-        name: name,
+        name,
         id: null,
         fullPath: [name],
         pathWithoutLast: [],
@@ -1483,6 +1483,7 @@ class DocSearch {
          */
         this.assocTypeIdNameMap = new Map();
         this.ALIASES = new Map();
+        this.FOUND_ALIASES = new Set();
         this.rootPath = rootPath;
         this.searchState = searchState;
 
@@ -2030,6 +2031,8 @@ class DocSearch {
         // normalized names, type signature objects and fingerprints, and aliases.
         id = 0;
 
+        /** @type {Array<[string, { [key: string]: Array<number> },  number]>} */
+        const allAliases = [];
         for (const [crate, crateCorpus] of rawSearchIndex) {
             // a string representing the lengths of each description shard
             // a string representing the list of function types
@@ -2178,10 +2181,10 @@ class DocSearch {
                 paths[i] = { ty, name, path, exactPath, unboxFlag };
             }
 
-            // convert `item*` into an object form, and construct word indices.
+            // Convert `item*` into an object form, and construct word indices.
             //
-            // before any analysis is performed lets gather the search terms to
-            // search against apart from the rest of the data.  This is a quick
+            // Before any analysis is performed, let's gather the search terms to
+            // search against apart from the rest of the data. This is a quick
             // operation that is cached for the life of the page state so that
             // all other search operations have access to this cached data for
             // faster analysis operations
@@ -2269,29 +2272,58 @@ class DocSearch {
             }
 
             if (aliases) {
-                const currentCrateAliases = new Map();
-                this.ALIASES.set(crate, currentCrateAliases);
-                for (const alias_name in aliases) {
-                    if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
-                        continue;
-                    }
-
-                    /** @type{number[]} */
-                    let currentNameAliases;
-                    if (currentCrateAliases.has(alias_name)) {
-                        currentNameAliases = currentCrateAliases.get(alias_name);
-                    } else {
-                        currentNameAliases = [];
-                        currentCrateAliases.set(alias_name, currentNameAliases);
-                    }
-                    for (const local_alias of aliases[alias_name]) {
-                        currentNameAliases.push(local_alias + currentIndex);
-                    }
-                }
+                // We need to add the aliases in `searchIndex` after we finished filling it
+                // to not mess up indexes.
+                allAliases.push([crate, aliases, currentIndex]);
             }
             currentIndex += itemTypes.length;
             this.searchState.descShards.set(crate, descShardList);
         }
+
+        for (const [crate, aliases, index] of allAliases) {
+            for (const [alias_name, alias_refs] of Object.entries(aliases)) {
+                if (!this.ALIASES.has(crate)) {
+                    this.ALIASES.set(crate, new Map());
+                }
+                const word = alias_name.toLowerCase();
+                const crate_alias_map = this.ALIASES.get(crate);
+                if (!crate_alias_map.has(word)) {
+                    crate_alias_map.set(word, []);
+                }
+                const aliases_map = crate_alias_map.get(word);
+
+                const normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
+                for (const alias of alias_refs) {
+                    const originalIndex = alias + index;
+                    const original = searchIndex[originalIndex];
+                    /** @type {rustdoc.Row} */
+                    const row = {
+                        crate,
+                        name: alias_name,
+                        normalizedName,
+                        is_alias: true,
+                        ty: original.ty,
+                        type: original.type,
+                        paramNames: [],
+                        word,
+                        id,
+                        parent: undefined,
+                        original,
+                        path: "",
+                        implDisambiguator: original.implDisambiguator,
+                        // Needed to load the description of the original item.
+                        // @ts-ignore
+                        descShard: original.descShard,
+                        descIndex: original.descIndex,
+                        bitIndex: original.bitIndex,
+                    };
+                    aliases_map.push(row);
+                    this.nameTrie.insert(normalizedName, id, this.tailTable);
+                    id += 1;
+                    searchIndex.push(row);
+                }
+            }
+        }
         // Drop the (rather large) hash table used for reusing function items
         this.TYPES_POOL = new Map();
         return searchIndex;
@@ -2536,6 +2568,8 @@ class DocSearch {
             parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) +
             parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0);
         const maxEditDistance = Math.floor(queryLen / 3);
+        // We reinitialize the `FOUND_ALIASES` map.
+        this.FOUND_ALIASES.clear();
 
         /**
          * @type {Map<string, number>}
@@ -2695,6 +2729,10 @@ class DocSearch {
         const buildHrefAndPath = item => {
             let displayPath;
             let href;
+            if (item.is_alias) {
+                this.FOUND_ALIASES.add(item.word);
+                item = item.original;
+            }
             const type = itemTypes[item.ty];
             const name = item.name;
             let path = item.path;
@@ -3198,8 +3236,7 @@ class DocSearch {
                 result.item = this.searchIndex[result.id];
                 result.word = this.searchIndex[result.id].word;
                 if (isReturnTypeQuery) {
-                    // we are doing a return-type based search,
-                    // deprioritize "clone-like" results,
+                    // We are doing a return-type based search, deprioritize "clone-like" results,
                     // ie. functions that also take the queried type as an argument.
                     const resultItemType = result.item && result.item.type;
                     if (!resultItemType) {
@@ -4259,28 +4296,13 @@ class DocSearch {
             return false;
         }
 
-        // this does not yet have a type in `rustdoc.d.ts`.
-        // @ts-expect-error
-        function createAliasFromItem(item) {
-            return {
-                crate: item.crate,
-                name: item.name,
-                path: item.path,
-                descShard: item.descShard,
-                descIndex: item.descIndex,
-                exactPath: item.exactPath,
-                ty: item.ty,
-                parent: item.parent,
-                type: item.type,
-                is_alias: true,
-                bitIndex: item.bitIndex,
-                implDisambiguator: item.implDisambiguator,
-            };
-        }
-
         // @ts-expect-error
         const handleAliases = async(ret, query, filterCrates, currentCrate) => {
             const lowerQuery = query.toLowerCase();
+            if (this.FOUND_ALIASES.has(lowerQuery)) {
+                return;
+            }
+            this.FOUND_ALIASES.add(lowerQuery);
             // We separate aliases and crate aliases because we want to have current crate
             // aliases to be before the others in the displayed results.
             // @ts-expect-error
@@ -4292,7 +4314,7 @@ class DocSearch {
                     && this.ALIASES.get(filterCrates).has(lowerQuery)) {
                     const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery);
                     for (const alias of query_aliases) {
-                        aliases.push(createAliasFromItem(this.searchIndex[alias]));
+                        aliases.push(alias);
                     }
                 }
             } else {
@@ -4302,7 +4324,7 @@ class DocSearch {
                         const pushTo = crate === currentCrate ? crateAliases : aliases;
                         const query_aliases = crateAliasesIndex.get(lowerQuery);
                         for (const alias of query_aliases) {
-                            pushTo.push(createAliasFromItem(this.searchIndex[alias]));
+                            pushTo.push(alias);
                         }
                     }
                 }
@@ -4310,9 +4332,9 @@ class DocSearch {
 
             // @ts-expect-error
             const sortFunc = (aaa, bbb) => {
-                if (aaa.path < bbb.path) {
+                if (aaa.original.path < bbb.original.path) {
                     return 1;
-                } else if (aaa.path === bbb.path) {
+                } else if (aaa.original.path === bbb.original.path) {
                     return 0;
                 }
                 return -1;
@@ -4322,20 +4344,9 @@ class DocSearch {
             aliases.sort(sortFunc);
 
             // @ts-expect-error
-            const fetchDesc = alias => {
-                // @ts-expect-error
-                return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
-                    "" : this.searchState.loadDesc(alias);
-            };
-            const [crateDescs, descs] = await Promise.all([
-                // @ts-expect-error
-                Promise.all(crateAliases.map(fetchDesc)),
-                Promise.all(aliases.map(fetchDesc)),
-            ]);
-
-            // @ts-expect-error
             const pushFunc = alias => {
-                alias.alias = query;
+                // Cloning `alias` to prevent its fields to be updated.
+                alias = {...alias};
                 const res = buildHrefAndPath(alias);
                 alias.displayPath = pathSplitter(res[0]);
                 alias.fullPath = alias.displayPath + alias.name;
@@ -4347,16 +4358,8 @@ class DocSearch {
                 }
             };
 
-            aliases.forEach((alias, i) => {
-                // @ts-expect-error
-                alias.desc = descs[i];
-            });
             aliases.forEach(pushFunc);
             // @ts-expect-error
-            crateAliases.forEach((alias, i) => {
-                alias.desc = crateDescs[i];
-            });
-            // @ts-expect-error
             crateAliases.forEach(pushFunc);
         };
 
@@ -4802,7 +4805,7 @@ async function addTab(array, query, display) {
         output.className = "search-results " + extraClass;
 
         const lis = Promise.all(array.map(async item => {
-            const name = item.name;
+            const name = item.is_alias ? item.original.name : item.name;
             const type = itemTypes[item.ty];
             const longType = longItemTypes[item.ty];
             const typeName = longType.length !== 0 ? `${longType}` : "?";
@@ -4822,7 +4825,7 @@ async function addTab(array, query, display) {
             let alias = " ";
             if (item.is_alias) {
                 alias = ` <div class="alias">\
-<b>${item.alias}</b><i class="grey">&nbsp;- see&nbsp;</i>\
+<b>${item.name}</b><i class="grey">&nbsp;- see&nbsp;</i>\
 </div>`;
             }
             resultName.insertAdjacentHTML(
@@ -5201,6 +5204,7 @@ function registerSearchEvents() {
         if (searchState.input.value.length === 0) {
             searchState.hideResults();
         } else {
+            // @ts-ignore
             searchState.timeout = setTimeout(search, 500);
         }
     };
@@ -5842,8 +5846,8 @@ Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new In
 // be called ONLY when the whole file has been parsed and loaded.
 
 // @ts-expect-error
-function initSearch(searchIndx) {
-    rawSearchIndex = searchIndx;
+function initSearch(searchIndex) {
+    rawSearchIndex = searchIndex;
     if (typeof window !== "undefined") {
         // @ts-expect-error
         docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState);
diff --git a/src/librustdoc/html/url_parts_builder.rs b/src/librustdoc/html/url_parts_builder.rs
index 9a533827441..705fa498e8d 100644
--- a/src/librustdoc/html/url_parts_builder.rs
+++ b/src/librustdoc/html/url_parts_builder.rs
@@ -117,7 +117,7 @@ impl UrlPartsBuilder {
 
 /// This is just a guess at the average length of a URL part,
 /// used for [`String::with_capacity`] calls in the [`FromIterator`]
-/// and [`Extend`] impls, and for [estimating item path lengths].
+/// and [`Extend`] impls.
 ///
 /// The value `8` was chosen for two main reasons:
 ///
@@ -125,18 +125,8 @@ impl UrlPartsBuilder {
 /// * jemalloc's size classes are all multiples of eight,
 ///   which means that the amount of memory it allocates will often match
 ///   the amount requested, avoiding wasted bytes.
-///
-/// [estimating item path lengths]: estimate_item_path_byte_length
 const AVG_PART_LENGTH: usize = 8;
 
-/// Estimate the number of bytes in an item's path, based on how many segments it has.
-///
-/// **Note:** This is only to be used with, e.g., [`String::with_capacity()`];
-/// the return value is just a rough estimate.
-pub(crate) const fn estimate_item_path_byte_length(segment_count: usize) -> usize {
-    AVG_PART_LENGTH * segment_count
-}
-
 impl<'a> FromIterator<&'a str> for UrlPartsBuilder {
     fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
         let iter = iter.into_iter();
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index e7163bead92..08bc0bb1950 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -5,10 +5,12 @@
 use rustc_abi::ExternAbi;
 use rustc_ast::ast;
 use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
+use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{HeaderSafety, Safety};
 use rustc_metadata::rendered_const;
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::{bug, ty};
 use rustc_span::{Pos, kw, sym};
 use rustdoc_json_types::*;
@@ -39,11 +41,16 @@ impl JsonRenderer<'_> {
             })
             .collect();
         let docs = item.opt_doc_value();
-        let attrs = item.attributes(self.tcx, &self.cache, true);
+        let attrs = item
+            .attrs
+            .other_attrs
+            .iter()
+            .filter_map(|a| maybe_from_hir_attr(a, item.item_id, self.tcx))
+            .collect();
         let span = item.span(self.tcx);
         let visibility = item.visibility(self.tcx);
         let clean::ItemInner { name, item_id, .. } = *item.inner;
-        let id = self.id_from_item(&item);
+        let id = self.id_from_item(item);
         let inner = match item.kind {
             clean::KeywordItem => return None,
             clean::StrippedItem(ref inner) => {
@@ -79,14 +86,14 @@ impl JsonRenderer<'_> {
         items
             .iter()
             .filter(|i| !i.is_stripped() && !i.is_keyword())
-            .map(|i| self.id_from_item(&i))
+            .map(|i| self.id_from_item(i))
             .collect()
     }
 
     fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
         items
             .iter()
-            .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
+            .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i)))
             .collect()
     }
 }
@@ -351,12 +358,12 @@ impl FromClean<clean::Struct> for Struct {
         let clean::Struct { ctor_kind, generics, fields } = struct_;
 
         let kind = match ctor_kind {
-            Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+            Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)),
             Some(CtorKind::Const) => {
                 assert!(fields.is_empty());
                 StructKind::Unit
             }
-            None => StructKind::Plain { fields: renderer.ids(&fields), has_stripped_fields },
+            None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields },
         };
 
         Struct {
@@ -374,7 +381,7 @@ impl FromClean<clean::Union> for Union {
         Union {
             generics: generics.into_json(renderer),
             has_stripped_fields,
-            fields: renderer.ids(&fields),
+            fields: renderer.ids(fields),
             impls: Vec::new(), // Added in JsonRenderer::item
         }
     }
@@ -652,7 +659,7 @@ impl FromClean<clean::FnDecl> for FunctionSignature {
         let clean::FnDecl { inputs, output, c_variadic } = decl;
         FunctionSignature {
             inputs: inputs
-                .into_iter()
+                .iter()
                 .map(|param| {
                     // `_` is the most sensible name for missing param names.
                     let name = param.name.unwrap_or(kw::Underscore).to_string();
@@ -677,7 +684,7 @@ impl FromClean<clean::Trait> for Trait {
             is_auto,
             is_unsafe,
             is_dyn_compatible,
-            items: renderer.ids(&items),
+            items: renderer.ids(items),
             generics: generics.into_json(renderer),
             bounds: bounds.into_json(renderer),
             implementations: Vec::new(), // Added in JsonRenderer::item
@@ -720,7 +727,7 @@ impl FromClean<clean::Impl> for Impl {
                 .collect(),
             trait_: trait_.into_json(renderer),
             for_: for_.into_json(renderer),
-            items: renderer.ids(&items),
+            items: renderer.ids(items),
             is_negative,
             is_synthetic,
             blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
@@ -763,7 +770,7 @@ impl FromClean<clean::Variant> for Variant {
 
         let kind = match &variant.kind {
             CLike => VariantKind::Plain,
-            Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+            Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)),
             Struct(s) => VariantKind::Struct {
                 has_stripped_fields: s.has_stripped_entries(),
                 fields: renderer.ids(&s.fields),
@@ -886,3 +893,93 @@ impl FromClean<ItemType> for ItemKind {
         }
     }
 }
+
+/// Maybe convert a attribute from hir to json.
+///
+/// Returns `None` if the attribute shouldn't be in the output.
+fn maybe_from_hir_attr(
+    attr: &hir::Attribute,
+    item_id: ItemId,
+    tcx: TyCtxt<'_>,
+) -> Option<Attribute> {
+    use attrs::AttributeKind as AK;
+
+    let kind = match attr {
+        hir::Attribute::Parsed(kind) => kind,
+
+        hir::Attribute::Unparsed(_) => {
+            // FIXME: We should handle `#[doc(hidden)]`.
+            return Some(other_attr(tcx, attr));
+        }
+    };
+
+    Some(match kind {
+        AK::Deprecation { .. } => return None, // Handled separately into Item::deprecation.
+        AK::DocComment { .. } => unreachable!("doc comments stripped out earlier"),
+
+        AK::MustUse { reason, span: _ } => {
+            Attribute::MustUse { reason: reason.map(|s| s.to_string()) }
+        }
+        AK::Repr { .. } => repr_attr(
+            tcx,
+            item_id.as_def_id().expect("all items that could have #[repr] have a DefId"),
+        ),
+        AK::ExportName { name, span: _ } => Attribute::ExportName(name.to_string()),
+        AK::LinkSection { name, span: _ } => Attribute::LinkSection(name.to_string()),
+        AK::TargetFeature(features, _span) => Attribute::TargetFeature {
+            enable: features.iter().map(|(feat, _span)| feat.to_string()).collect(),
+        },
+
+        AK::NoMangle(_) => Attribute::NoMangle,
+        AK::NonExhaustive(_) => Attribute::NonExhaustive,
+        AK::AutomaticallyDerived(_) => Attribute::AutomaticallyDerived,
+
+        _ => other_attr(tcx, attr),
+    })
+}
+
+fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute {
+    let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr);
+    assert_eq!(s.pop(), Some('\n'));
+    Attribute::Other(s)
+}
+
+fn repr_attr(tcx: TyCtxt<'_>, def_id: DefId) -> Attribute {
+    let repr = tcx.adt_def(def_id).repr();
+
+    let kind = if repr.c() {
+        ReprKind::C
+    } else if repr.transparent() {
+        ReprKind::Transparent
+    } else if repr.simd() {
+        ReprKind::Simd
+    } else {
+        ReprKind::Rust
+    };
+
+    let align = repr.align.map(|a| a.bytes());
+    let packed = repr.pack.map(|p| p.bytes());
+    let int = repr.int.map(format_integer_type);
+
+    Attribute::Repr(AttributeRepr { kind, align, packed, int })
+}
+
+fn format_integer_type(it: rustc_abi::IntegerType) -> String {
+    use rustc_abi::Integer::*;
+    use rustc_abi::IntegerType::*;
+    match it {
+        Pointer(true) => "isize",
+        Pointer(false) => "usize",
+        Fixed(I8, true) => "i8",
+        Fixed(I8, false) => "u8",
+        Fixed(I16, true) => "i16",
+        Fixed(I16, false) => "u16",
+        Fixed(I32, true) => "i32",
+        Fixed(I32, false) => "u32",
+        Fixed(I64, true) => "i64",
+        Fixed(I64, false) => "u64",
+        Fixed(I128, true) => "i128",
+        Fixed(I128, false) => "u128",
+    }
+    .to_owned()
+}
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 600a4b429f3..760e48baffa 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -133,7 +133,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
     let feature_stability: FxHashMap<&str, Stability> = sess
         .target
         .rust_target_features()
-        .into_iter()
+        .iter()
         .copied()
         .map(|(name, stability, _)| (name, stability))
         .collect();
@@ -143,7 +143,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
         target_features: sess
             .target
             .rust_target_features()
-            .into_iter()
+            .iter()
             .copied()
             .filter(|(_, stability, _)| {
                 // Describe only target features which the user can toggle
@@ -157,7 +157,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
                         _ => None,
                     },
                     implies_features: implied_features
-                        .into_iter()
+                        .iter()
                         .copied()
                         .filter(|name| {
                             // Imply only target features which the user can toggle
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ca6f67eb6df..5a9aa2a94c8 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -274,7 +274,7 @@ impl From<DiagnosticInfo<'_>> for OwnedDiagnosticInfo {
 }
 
 impl OwnedDiagnosticInfo {
-    pub(crate) fn into_info(&self) -> DiagnosticInfo<'_> {
+    pub(crate) fn as_info(&self) -> DiagnosticInfo<'_> {
         DiagnosticInfo {
             item: &self.item,
             ori_link: &self.ori_link,
@@ -1177,7 +1177,7 @@ impl LinkCollector<'_, '_> {
                     // Primitive types are always valid.
                     Res::Primitive(_) => true,
                 });
-                let diag_info = info.diag_info.into_info();
+                let diag_info = info.diag_info.as_info();
                 match info.resolved.len() {
                     1 => {
                         let (res, fragment) = info.resolved.pop().unwrap();
@@ -1243,17 +1243,16 @@ impl LinkCollector<'_, '_> {
             disambiguator,
             None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive)
         ) && !matches!(res, Res::Primitive(_))
+            && let Some(prim) = resolve_primitive(path_str, TypeNS)
         {
-            if let Some(prim) = resolve_primitive(path_str, TypeNS) {
-                // `prim@char`
-                if matches!(disambiguator, Some(Disambiguator::Primitive)) {
-                    res = prim;
-                } else {
-                    // `[char]` when a `char` module is in scope
-                    let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
-                    ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
-                    return None;
-                }
+            // `prim@char`
+            if matches!(disambiguator, Some(Disambiguator::Primitive)) {
+                res = prim;
+            } else {
+                // `[char]` when a `char` module is in scope
+                let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
+                ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
+                return None;
             }
         }
 
@@ -2233,7 +2232,7 @@ fn ambiguity_error(
     // proc macro can exist in multiple namespaces at once, so we need to compare `DefIds`
     //  to remove the candidate in the fn namespace.
     let mut possible_proc_macro_id = None;
-    let is_proc_macro_crate = cx.tcx.crate_types() == &[CrateType::ProcMacro];
+    let is_proc_macro_crate = cx.tcx.crate_types() == [CrateType::ProcMacro];
     let mut kinds = candidates
         .iter()
         .map(|(res, def_id)| {
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 5757b6a9740..e69cf87f957 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -93,14 +93,14 @@ fn check_redundant_explicit_link<'md>(
         if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event {
             let link_data = collect_link_data(&mut offset_iter);
 
-            if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
-                if &link_data.display_link.replace('`', "") != resolvable_link {
-                    // Skips if display link does not match to actual
-                    // resolvable link, usually happens if display link
-                    // has several segments, e.g.
-                    // [this is just an `Option`](Option)
-                    continue;
-                }
+            if let Some(resolvable_link) = link_data.resolvable_link.as_ref()
+                && &link_data.display_link.replace('`', "") != resolvable_link
+            {
+                // Skips if display link does not match to actual
+                // resolvable link, usually happens if display link
+                // has several segments, e.g.
+                // [this is just an `Option`](Option)
+                continue;
             }
 
             let explicit_link = dest_url.to_string();
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index b53e3b4e3d7..bb13308e6c2 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -47,13 +47,11 @@ impl DocFolder for NonLocalStripper<'_> {
         // FIXME(#125009): Not-local should probably consider same Cargo workspace
         if let Some(def_id) = i.def_id()
             && !def_id.is_local()
-        {
-            if i.is_doc_hidden()
+            && (i.is_doc_hidden()
                 // Default to *not* stripping items with inherited visibility.
-                || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public)
-            {
-                return Some(strip_item(i));
-            }
+                || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public))
+        {
+            return Some(strip_item(i));
         }
 
         Some(self.fold_item_recur(i))