Skip to content

Commit 8f8a5d2

Browse files
authored
Rollup merge of #101279 - GuillaumeGomez:doc_auto_cfg_nested_impl, r=notriddle
Fix doc_auto_cfg for impl blocks in different modules with different `cfg` Fixes #101129. Just like reexports, impl blocks don't necessarily share the same "space" as the item they implement so we need to merge attributes from its parents as well. r? `@notriddle`
2 parents e9df5dd + 68d0094 commit 8f8a5d2

File tree

2 files changed

+64
-20
lines changed

2 files changed

+64
-20
lines changed

src/librustdoc/passes/propagate_doc_cfg.rs

+40-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33

44
use crate::clean::cfg::Cfg;
55
use crate::clean::inline::{load_attrs, merge_attrs};
6-
use crate::clean::{Crate, Item};
6+
use crate::clean::{Crate, Item, ItemKind};
77
use crate::core::DocContext;
88
use crate::fold::DocFolder;
99
use crate::passes::Pass;
@@ -26,30 +26,50 @@ struct CfgPropagator<'a, 'tcx> {
2626
cx: &'a mut DocContext<'tcx>,
2727
}
2828

29-
impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
30-
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
31-
let old_parent_cfg = self.parent_cfg.clone();
29+
impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
30+
// Some items need to merge their attributes with their parents' otherwise a few of them
31+
// (mostly `cfg` ones) will be missing.
32+
fn merge_with_parent_attributes(&mut self, item: &mut Item) {
33+
let check_parent = match &*item.kind {
34+
// impl blocks can be in different modules with different cfg and we need to get them
35+
// as well.
36+
ItemKind::ImplItem(_) => false,
37+
kind if kind.is_non_assoc() => true,
38+
_ => return,
39+
};
3240

33-
if item.kind.is_non_assoc() &&
34-
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
35-
let hir = self.cx.tcx.hir();
36-
let hir_id = hir.local_def_id_to_hir_id(def_id);
41+
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local())
42+
else { return };
43+
44+
let hir = self.cx.tcx.hir();
45+
let hir_id = hir.local_def_id_to_hir_id(def_id);
46+
47+
if check_parent {
3748
let expected_parent = hir.get_parent_item(hir_id);
49+
// If parents are different, it means that `item` is a reexport and we need
50+
// to compute the actual `cfg` by iterating through its "real" parents.
51+
if self.parent == Some(expected_parent) {
52+
return;
53+
}
54+
}
3855

39-
// If parents are different, it means that `item` is a reexport and we need to compute
40-
// the actual `cfg` by iterating through its "real" parents.
41-
if self.parent != Some(expected_parent) {
42-
let mut attrs = Vec::new();
43-
for (parent_hir_id, _) in hir.parent_iter(hir_id) {
44-
if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
45-
attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
46-
}
47-
}
48-
let (_, cfg) =
49-
merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
50-
item.cfg = cfg;
56+
let mut attrs = Vec::new();
57+
for (parent_hir_id, _) in hir.parent_iter(hir_id) {
58+
if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
59+
attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
5160
}
5261
}
62+
let (_, cfg) = merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
63+
item.cfg = cfg;
64+
}
65+
}
66+
67+
impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
68+
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
69+
let old_parent_cfg = self.parent_cfg.clone();
70+
71+
self.merge_with_parent_attributes(&mut item);
72+
5373
let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
5474
(None, None) => None,
5575
(Some(rc), None) | (None, Some(rc)) => Some(rc),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/101129>.
2+
3+
#![feature(doc_auto_cfg)]
4+
#![crate_type = "lib"]
5+
#![crate_name = "foo"]
6+
7+
pub struct S;
8+
pub trait MyTrait1 {}
9+
pub trait MyTrait2 {}
10+
11+
// @has foo/struct.S.html
12+
// @has - '//*[@id="impl-MyTrait1-for-S"]//*[@class="stab portability"]' \
13+
// 'Available on non-crate feature coolstuff only.'
14+
#[cfg(not(feature = "coolstuff"))]
15+
impl MyTrait1 for S {}
16+
17+
#[cfg(not(feature = "coolstuff"))]
18+
mod submod {
19+
use crate::{S, MyTrait2};
20+
// This impl should also have the `not(feature = "coolstuff")`.
21+
// @has - '//*[@id="impl-MyTrait2-for-S"]//*[@class="stab portability"]' \
22+
// 'Available on non-crate feature coolstuff only.'
23+
impl MyTrait2 for S {}
24+
}

0 commit comments

Comments
 (0)