From 3d11e96569861f2df3254af65bd8065dc70474bf Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Mon, 23 Nov 2020 15:51:01 +0100 Subject: [PATCH 1/2] Fix order of diff when rustdoc tests fail --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4ca0b2aba0ad1..57926fedfd471 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2436,7 +2436,7 @@ impl<'test> TestCx<'test> { }) }; let mut diff = Command::new("diff"); - diff.args(&["-u", "-r"]).args(&[out_dir, &compare_dir]); + diff.args(&["-u", "-r"]).args(&[&compare_dir, out_dir]); let output = if let Some(pager) = pager { let diff_pid = diff.stdout(Stdio::piped()).spawn().expect("failed to run `diff`"); From d93f1d6c04fab017a24d868dd766a290321e636c Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Mon, 23 Nov 2020 13:22:56 +0100 Subject: [PATCH 2/2] Apply `doc(cfg)` from parent items while collecting trait impls 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. --- src/librustdoc/clean/inline.rs | 10 ++--- src/librustdoc/passes/collect_trait_impls.rs | 28 ++++++++++++- src/test/rustdoc/doc-cfg.rs | 3 +- src/test/rustdoc/issue-79201.rs | 41 ++++++++++++++++++++ 4 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/test/rustdoc/issue-79201.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cc3e8707e5276..17963e44a01fe 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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); @@ -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 { @@ -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) -> clean::Module { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 2946db1f46206..62eb7d4d11f3e 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -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 { @@ -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, + ); }); } } diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index d7041ee2f1af8..471dd3a9d1821 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -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() {} } diff --git a/src/test/rustdoc/issue-79201.rs b/src/test/rustdoc/issue-79201.rs new file mode 100644 index 0000000000000..f95d79cd493ea --- /dev/null +++ b/src/test/rustdoc/issue-79201.rs @@ -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 {} + } +}