diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fe32b75d668ce..4f2991011bcea 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; use std::default::Default; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::lazy::SyncOnceCell as OnceCell; use std::path::PathBuf; use std::rc::Rc; @@ -904,7 +904,7 @@ impl + IntoIterator(&self, hasher: &mut H) { + self.doc_strings.hash(hasher); + for attr in &self.other_attrs { + attr.id.hash(hasher); + } + } +} + #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifier), @@ -1554,23 +1563,12 @@ impl Type { /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. /// - /// See [`Self::def_id_no_primitives`] for more. + /// See [`Self::def_id`] for more. /// /// [clean]: crate::clean crate fn def_id(&self, cache: &Cache) -> Option { self.inner_def_id(Some(cache)) } - - /// Use this method to get the [`DefId`] of a [`clean`] AST node. - /// This will return [`None`] when called on a primitive [`clean::Type`]. - /// Use [`Self::def_id`] if you want to include primitives. - /// - /// [`clean`]: crate::clean - /// [`clean::Type`]: crate::clean::Type - // FIXME: get rid of this function and always use `def_id` - crate fn def_id_no_primitives(&self) -> Option { - self.inner_def_id(None) - } } /// A primitive (aka, builtin) type. diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 631eacc961828..cf046e4e12967 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -261,7 +261,7 @@ crate fn get_real_types<'tcx>( tcx: TyCtxt<'_>, ty: Type, mut generics: Vec, - _cache: &Cache, + cache: &Cache, ) { let is_full_generic = ty.is_full_generic(); @@ -320,7 +320,7 @@ crate fn get_real_types<'tcx>( // We remove the name of the full generic because we have no use for it. index_ty.name = Some(String::new()); res.push(TypeWithKind::from((index_ty, ItemType::Generic))); - } else if let Some(kind) = ty.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) { + } else if let Some(kind) = ty.def_id(cache).map(|did| tcx.def_kind(did).into()) { res.push(TypeWithKind::from((index_ty, kind))); } else if ty.is_primitive() { // This is a primitive, let's store it as such. @@ -338,9 +338,7 @@ crate fn get_real_types<'tcx>( if let Type::Generic(arg_s) = *arg { // First we check if the bounds are in a `where` predicate... if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => { - ty.def_id_no_primitives() == arg.def_id_no_primitives() - } + WherePredicate::BoundPredicate { ty, .. } => ty.def_id(cache) == arg.def_id(cache), _ => false, }) { let mut ty_generics = Vec::new(); @@ -413,8 +411,7 @@ crate fn get_all_types<'tcx>( if !args.is_empty() { all_types.extend(args); } else { - if let Some(kind) = arg.type_.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) - { + if let Some(kind) = arg.type_.def_id(cache).map(|did| tcx.def_kind(did).into()) { all_types.push(TypeWithKind::from((get_index_type(&arg.type_, vec![]), kind))); } } @@ -425,9 +422,7 @@ crate fn get_all_types<'tcx>( FnRetTy::Return(ref return_type) => { get_real_types(generics, return_type, tcx, 0, &mut ret_types, cache); if ret_types.is_empty() { - if let Some(kind) = - return_type.def_id_no_primitives().map(|did| tcx.def_kind(did).into()) - { + if let Some(kind) = return_type.def_id(cache).map(|did| tcx.def_kind(did).into()) { ret_types.push(TypeWithKind::from((get_index_type(return_type, vec![]), kind))); } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 5884fdc715ab8..6cdf22a87bef7 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -6,6 +6,7 @@ use crate::clean::*; use crate::core::DocContext; use crate::visit::DocVisitor; +use crate::formats::cache::Cache; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefId; use rustc_middle::ty::DefIdTree; @@ -47,7 +48,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate inline::build_impl(cx, None, def_id, None, &mut new_items); // FIXME(eddyb) is this `doc(hidden)` check needed? - if !cx.tcx.is_doc_hidden(def_id) { + if !cx.tcx.get_attrs(def_id).lists(sym::doc).has_word(sym::hidden) { let impls = get_auto_trait_and_blanket_impls(cx, def_id); new_items.extend(impls.filter(|i| cx.inlined.insert(i.def_id))); } @@ -64,6 +65,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate map: &FxHashMap, cleaner: &mut BadImplStripper, type_did: DefId, + c: &Cache, ) { if let Some(target) = map.get(&type_did) { debug!("add_deref_target: type {:?}, target {:?}", type_did, target); @@ -76,7 +78,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate return; } cleaner.items.insert(target_did.into()); - add_deref_target(cx, map, cleaner, target_did); + add_deref_target(cx, map, cleaner, target_did, c); } } } @@ -85,7 +87,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate for it in &new_items { if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() - && cleaner.keep_impl(for_, true) + && cleaner.keep_impl(for_, true, &cx.cache) { let target = items .iter() @@ -100,13 +102,19 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate } else if let Some(did) = target.def_id(&cx.cache) { cleaner.items.insert(did.into()); } - if let Some(for_did) = for_.def_id_no_primitives() { + if let Some(for_did) = for_.def_id(&cx.cache) { if type_did_to_deref_target.insert(for_did, target).is_none() { // Since only the `DefId` portion of the `Type` instances is known to be same for both the // `Deref` target type and the impl for type positions, this map of types is keyed by // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. if cleaner.keep_impl_with_def_id(for_did.into()) { - add_deref_target(cx, &type_did_to_deref_target, &mut cleaner, for_did); + add_deref_target( + cx, + &type_did_to_deref_target, + &mut cleaner, + for_did, + &cx.cache, + ); } } } @@ -119,6 +127,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate cleaner.keep_impl( for_, trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(), + &cx.cache, ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) || kind.is_blanket() } else { @@ -176,7 +185,13 @@ impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> { fn visit_item(&mut self, i: &Item) { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? - if !self.cx.tcx.is_doc_hidden(i.def_id.expect_def_id()) { + if !self + .cx + .tcx + .get_attrs(i.def_id.expect_def_id()) + .lists(sym::doc) + .has_word(sym::hidden) + { self.impls .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id())); } @@ -211,13 +226,13 @@ struct BadImplStripper { } impl BadImplStripper { - fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool { + fn keep_impl(&self, ty: &Type, is_deref: bool, c: &Cache) -> bool { if let Generic(_) = ty { // keep impls made on generics true } else if let Some(prim) = ty.primitive_type() { self.prims.contains(&prim) - } else if let Some(did) = ty.def_id_no_primitives() { + } else if let Some(did) = ty.def_id(c) { is_deref || self.keep_impl_with_def_id(did.into()) } else { false diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index e63534659add7..e7a99ee7bfd84 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -15,7 +15,7 @@ crate const STRIP_HIDDEN: Pass = Pass { }; /// Strip items marked `#[doc(hidden)]` -crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate { +crate fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate { let mut retained = ItemIdSet::default(); // strip all #[doc(hidden)] items @@ -25,7 +25,7 @@ crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Cra }; // strip all impls referencing stripped items - let mut stripper = ImplStripper { retained: &retained }; + let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index c6b5bec4692dc..ef7e768a51149 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -29,6 +29,6 @@ crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clea } // strip all impls referencing private items - let mut stripper = ImplStripper { retained: &retained }; + let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 675443b48a206..f0fb21a9be2ca 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -5,6 +5,7 @@ use std::mem; use crate::clean::{self, Item, ItemIdSet}; use crate::fold::{strip_item, DocFolder}; +use crate::formats::cache::Cache; crate struct Stripper<'a> { crate retained: &'a mut ItemIdSet, @@ -119,6 +120,7 @@ impl<'a> DocFolder for Stripper<'a> { /// This stripper discards all impls which reference stripped items crate struct ImplStripper<'a> { crate retained: &'a ItemIdSet, + crate cache: &'a Cache, } impl<'a> DocFolder for ImplStripper<'a> { @@ -128,7 +130,7 @@ impl<'a> DocFolder for ImplStripper<'a> { if imp.trait_.is_none() && imp.items.is_empty() { return None; } - if let Some(did) = imp.for_.def_id_no_primitives() { + if let Some(did) = imp.for_.def_id(&self.cache) { if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into()) { debug!("ImplStripper: impl item for stripped type; removing"); @@ -143,7 +145,7 @@ impl<'a> DocFolder for ImplStripper<'a> { } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { - if let Some(did) = typaram.def_id_no_primitives() { + if let Some(did) = typaram.def_id(&self.cache) { if did.is_local() && !self.retained.contains(&did.into()) { debug!( "ImplStripper: stripped item in trait's generics; removing impl"