From 4029a03b345ae9fcc8e981ac181f00332b7711ed Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Mon, 3 May 2021 14:57:51 -0400 Subject: [PATCH] Make match in `register_res` easier to read - Don't duplicate DefKind -> ItemType handling; that's a good way to get bugs - Use exhaustive match - Add comments This found that register_res is very wrong in at least one way: if it registers a Res for `Variant`, it should also register one for `Field`. But I don't know whether the one for Variant should be removed or Field added. Maybe someone has ideas? --- src/librustdoc/clean/utils.rs | 53 ++++++++++++++++++----------- src/test/rustdoc/intra-doc/field.rs | 4 +++ 2 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 src/test/rustdoc/intra-doc/field.rs diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 7df8b442e5acc..c751356879a71 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; @@ -431,35 +431,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; 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]