diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a4f754912aea6..38b12405ea821 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -249,7 +249,7 @@ pub(crate) fn clean_trait_ref_with_constraints<'tcx>( trait_ref: ty::PolyTraitRef<'tcx>, constraints: ThinVec, ) -> Path { - let kind = cx.tcx.def_kind(trait_ref.def_id()).into(); + let kind = ItemType::from_def_id(trait_ref.def_id(), cx.tcx); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {kind:?}"); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 6e4c65dc91273..7669a2b1a5799 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -522,8 +522,15 @@ impl Item { debug!(?id); if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) { debug!(?url); - if let Some(ref fragment) = *fragment { - fragment.render(&mut url, cx.tcx()) + match fragment { + Some(UrlFragment::Item(def_id)) => { + url.push_str(&crate::html::format::fragment(*def_id, cx.tcx())) + } + Some(UrlFragment::UserWritten(raw)) => { + url.push('#'); + url.push_str(raw); + } + None => {} } Some(RenderedLink { original_text: s.clone(), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 060abfd05e042..cb5cd6523afea 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -26,6 +26,7 @@ use crate::clean::{ }; use crate::core::DocContext; use crate::display::Joined as _; +use crate::formats::item_type::ItemType; #[cfg(test)] mod tests; @@ -496,7 +497,7 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { let (kind, did) = match res { Res::Def( - kind @ (AssocTy + AssocTy | AssocFn | AssocConst | Variant @@ -511,9 +512,9 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Const | Static { .. } | Macro(..) - | TraitAlias), + | TraitAlias, did, - ) => (kind.into(), did), + ) => (ItemType::from_def_id(did, cx.tcx), did), _ => panic!("register_res: unexpected {res:?}"), }; diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index ab40c01cb369d..d3923e3e31166 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -3,6 +3,8 @@ use std::fmt; use rustc_hir::def::{CtorOf, DefKind, MacroKinds}; +use rustc_hir::def_id::DefId; +use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::MacroKind; use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; @@ -147,17 +149,10 @@ impl<'a> From<&'a clean::Item> for ItemType { } } -impl From for ItemType { - fn from(other: DefKind) -> Self { - Self::from_def_kind(other, None) - } -} - impl ItemType { - /// Depending on the parent kind, some variants have a different translation (like a `Method` - /// becoming a `TyMethod`). - pub(crate) fn from_def_kind(kind: DefKind, parent_kind: Option) -> Self { - match kind { + pub(crate) fn from_def_id(def_id: DefId, tcx: TyCtxt<'_>) -> Self { + let def_kind = tcx.def_kind(def_id); + match def_kind { DefKind::Enum => Self::Enum, DefKind::Fn => Self::Function, DefKind::Mod => Self::Module, @@ -176,8 +171,13 @@ impl ItemType { DefKind::Variant => Self::Variant, DefKind::Field => Self::StructField, DefKind::AssocTy => Self::AssocType, - DefKind::AssocFn if let Some(DefKind::Trait) = parent_kind => Self::TyMethod, - DefKind::AssocFn => Self::Method, + DefKind::AssocFn => { + if tcx.associated_item(def_id).defaultness(tcx).has_value() { + Self::Method + } else { + Self::TyMethod + } + } DefKind::Ctor(CtorOf::Struct, _) => Self::Struct, DefKind::Ctor(CtorOf::Variant, _) => Self::Variant, DefKind::AssocConst => Self::AssocConst, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b7f6d84ea36c2..5892eecea35e9 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -431,7 +431,6 @@ fn generate_item_def_id_path( original_def_id: DefId, cx: &Context<'_>, root_path: Option<&str>, - original_def_kind: DefKind, ) -> Result { use rustc_middle::traits::ObligationCause; use rustc_trait_selection::infer::TyCtxtInferExt; @@ -457,15 +456,14 @@ fn generate_item_def_id_path( let relative = clean::inline::item_relative_path(tcx, def_id); let fqp: Vec = once(crate_name).chain(relative).collect(); - let def_kind = tcx.def_kind(def_id); - let shortty = def_kind.into(); + let shortty = ItemType::from_def_id(def_id, tcx); let module_fqp = to_module_fqp(shortty, &fqp); let mut is_remote = false; let url_parts = url_parts(cx.cache(), def_id, module_fqp, &cx.current, &mut is_remote)?; let mut url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote); if def_id != original_def_id { - let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind)); + let kind = ItemType::from_def_id(original_def_id, tcx); url_parts = format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)) }; Ok(HrefInfo { url: url_parts, kind: shortty, rust_path: fqp }) @@ -605,7 +603,7 @@ pub(crate) fn href_with_root_path( } else if did.is_local() { return Err(HrefError::Private); } else { - return generate_item_def_id_path(did, original_did, cx, root_path, def_kind); + return generate_item_def_id_path(did, original_did, cx, root_path); } } }; @@ -835,26 +833,35 @@ fn print_higher_ranked_params_with_space( }) } -pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display { - fmt::from_fn(move |f| { - if let Ok(HrefInfo { url, kind, rust_path }) = href(did, cx) { - let tcx = cx.tcx(); - let def_kind = tcx.def_kind(did); - let anchor = if matches!( - def_kind, - DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant - ) { - let parent_def_id = tcx.parent(did); - let item_type = - ItemType::from_def_kind(def_kind, Some(tcx.def_kind(parent_def_id))); - format!("#{}.{}", item_type.as_str(), tcx.item_name(did)) +pub(crate) fn fragment(did: DefId, tcx: TyCtxt<'_>) -> String { + let def_kind = tcx.def_kind(did); + match def_kind { + DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => { + let item_type = ItemType::from_def_id(did, tcx); + format!("#{}.{}", item_type.as_str(), tcx.item_name(did)) + } + DefKind::Field => { + let parent_def_id = tcx.parent(did); + let s; + let kind = if tcx.def_kind(parent_def_id) == DefKind::Variant { + s = format!("variant.{}.field", tcx.item_name(parent_def_id).as_str()); + &s } else { - String::new() + "structfield" }; + format!("#{kind}.{}", tcx.item_name(did)) + } + _ => String::new(), + } +} +pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display { + fmt::from_fn(move |f| { + if let Ok(HrefInfo { url, kind, rust_path }) = href(did, cx) { write!( f, r#"{text}"#, + anchor = fragment(did, cx.tcx()), path = join_path_syms(rust_path), text = EscapeBodyText(text.as_str()), ) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e29256bb5d1a5..4e4f21bf926fe 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -203,43 +203,6 @@ pub(crate) enum UrlFragment { UserWritten(String), } -impl UrlFragment { - /// Render the fragment, including the leading `#`. - pub(crate) fn render(&self, s: &mut String, tcx: TyCtxt<'_>) { - s.push('#'); - match self { - &UrlFragment::Item(def_id) => { - let kind = match tcx.def_kind(def_id) { - DefKind::AssocFn => { - if tcx.associated_item(def_id).defaultness(tcx).has_value() { - "method." - } else { - "tymethod." - } - } - DefKind::AssocConst => "associatedconstant.", - DefKind::AssocTy => "associatedtype.", - DefKind::Variant => "variant.", - DefKind::Field => { - let parent_id = tcx.parent(def_id); - if tcx.def_kind(parent_id) == DefKind::Variant { - s.push_str("variant."); - s.push_str(tcx.item_name(parent_id).as_str()); - ".field." - } else { - "structfield." - } - } - kind => bug!("unexpected associated item kind: {kind:?}"), - }; - s.push_str(kind); - s.push_str(tcx.item_name(def_id).as_str()); - } - UrlFragment::UserWritten(raw) => s.push_str(raw), - } - } -} - #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub(crate) struct ResolutionInfo { item_id: DefId,