Skip to content

Commit

Permalink
Apply doc(cfg) from parent items while collecting trait impls
Browse files Browse the repository at this point in the history
Because trait impls bypass the standard `clean` hierarchy they do not
participate in the `propagate_doc_cfg` pass, so instead we need to
pre-collect all possible `doc(cfg)` attributes that will apply to them
when cleaning.
  • Loading branch information
Nemo157 committed Nov 23, 2020
1 parent 3d11e96 commit d93f1d6
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 7 deletions.
10 changes: 5 additions & 5 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,6 @@ crate fn build_impl(
return;
}

let attrs = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
debug!("merged_attrs={:?}", attrs);

let tcx = cx.tcx;
let associated_trait = tcx.impl_trait_ref(did);

Expand Down Expand Up @@ -435,7 +432,7 @@ crate fn build_impl(

debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());

ret.push(clean::Item::from_def_id_and_parts(
let mut item = clean::Item::from_def_id_and_parts(
did,
None,
clean::ImplItem(clean::Impl {
Expand All @@ -450,7 +447,10 @@ crate fn build_impl(
blanket_impl: None,
}),
cx,
));
);
item.attrs = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
debug!("merged_attrs={:?}", item.attrs);
ret.push(item);
}

fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>) -> clean::Module {
Expand Down
28 changes: 27 additions & 1 deletion src/librustdoc/passes/collect_trait_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::fold::DocFolder;

use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::DefIdTree;
use rustc_span::symbol::sym;

crate const COLLECT_TRAIT_IMPLS: Pass = Pass {
Expand Down Expand Up @@ -90,7 +91,32 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
let impl_did = cx.tcx.hir().local_def_id(impl_node);
cx.tcx.sess.time("build_local_trait_impl", || {
inline::build_impl(cx, None, impl_did.to_def_id(), None, &mut new_items);
let mut extra_attrs = Vec::new();
let mut parent = cx.tcx.parent(impl_did.to_def_id());
while let Some(did) = parent {
extra_attrs.extend(
cx.tcx
.get_attrs(did)
.iter()
.filter(|attr| attr.has_name(sym::doc))
.filter(|attr| {
if let Some([attr]) = attr.meta_item_list().as_deref() {
attr.has_name(sym::cfg)
} else {
false
}
})
.cloned(),
);
parent = cx.tcx.parent(did);
}
inline::build_impl(
cx,
None,
impl_did.to_def_id(),
Some(&extra_attrs),
&mut new_items,
);
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/rustdoc/doc-cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ pub mod unix_only {
// @has doc_cfg/unix_only/trait.ArmOnly.html \
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
// 'This is supported on Unix and ARM only.'
// @count - '//*[@class="stab portability"]' 2
// @count - '//*[@class="stab portability"]' 1
#[doc(cfg(target_arch = "arm"))]
pub trait ArmOnly {
fn unix_and_arm_only_function();
}

#[doc(cfg(target_arch = "arm"))]
impl ArmOnly for super::Portable {
fn unix_and_arm_only_function() {}
}
Expand Down
41 changes: 41 additions & 0 deletions src/test/rustdoc/issue-79201.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![feature(doc_cfg)]

// @has 'issue_79201/trait.Foo.html'
// @count - '//*[@class="stab portability"]' 6
// @matches - '//*[@class="stab portability"]' 'crate feature foo-root'
// @matches - '//*[@class="stab portability"]' 'crate feature foo-public-mod'
// @matches - '//*[@class="stab portability"]' 'crate feature foo-private-mod'
// @matches - '//*[@class="stab portability"]' 'crate feature foo-fn'
// @matches - '//*[@class="stab portability"]' 'crate feature foo-method'

pub trait Foo {}

#[doc(cfg(feature = "foo-root"))]
impl crate::Foo for usize {}

#[doc(cfg(feature = "foo-public-mod"))]
pub mod public {
impl crate::Foo for u8 {}
}

#[doc(cfg(feature = "foo-private-mod"))]
mod private {
impl crate::Foo for u16 {}
}

#[doc(cfg(feature = "foo-const"))]
const _: () = {
impl crate::Foo for u32 {}
};

#[doc(cfg(feature = "foo-fn"))]
fn __() {
impl crate::Foo for u64 {}
}

#[doc(cfg(feature = "foo-method"))]
impl dyn Foo {
fn __() {
impl crate::Foo for u128 {}
}
}

0 comments on commit d93f1d6

Please sign in to comment.