about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume.gomez@huawei.com>2022-08-25 16:42:17 +0200
committerGuillaume Gomez <guillaume.gomez@huawei.com>2022-08-25 20:12:53 +0200
commit01d64f5e3eb309a41a40fbbaf5d6bd9d20f86bee (patch)
treec74b775a806ccdc56551e7b2763d5b668a4bde78 /src
parent4a24f08ba43166cfee86d868b3fe8612aec6faca (diff)
downloadrust-01d64f5e3eb309a41a40fbbaf5d6bd9d20f86bee.tar.gz
rust-01d64f5e3eb309a41a40fbbaf5d6bd9d20f86bee.zip
Fix missing cfg propagation for reexports
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/types.rs27
-rw-r--r--src/librustdoc/html/render/mod.rs9
-rw-r--r--src/librustdoc/html/render/print_item.rs2
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs39
5 files changed, 71 insertions, 8 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index a7048e788b6..f367edcbf5a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -300,7 +300,7 @@ pub(crate) fn build_impls(
 }
 
 /// `parent_module` refers to the parent of the re-export, not the original item
-fn merge_attrs(
+pub(crate) fn merge_attrs(
     cx: &mut DocContext<'_>,
     parent_module: Option<DefId>,
     old_attrs: Attrs<'_>,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 4c39021903c..909a47d07b1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -482,7 +482,7 @@ impl Item {
         cx: &mut DocContext<'_>,
         cfg: Option<Arc<Cfg>>,
     ) -> Item {
-        trace!("name={:?}, def_id={:?}", name, def_id);
+        trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
 
         // Primitives and Keywords are written in the source code as private modules.
         // The modules need to be private so that nobody actually uses them, but the
@@ -801,6 +801,31 @@ impl ItemKind {
             | KeywordItem => [].iter(),
         }
     }
+
+    /// Returns `true` if this item does not appear inside an impl block.
+    pub(crate) fn is_non_assoc(&self) -> bool {
+        matches!(
+            self,
+            StructItem(_)
+                | UnionItem(_)
+                | EnumItem(_)
+                | TraitItem(_)
+                | ModuleItem(_)
+                | ExternCrateItem { .. }
+                | FunctionItem(_)
+                | TypedefItem(_)
+                | OpaqueTyItem(_)
+                | StaticItem(_)
+                | ConstantItem(_)
+                | TraitAliasItem(_)
+                | ForeignFunctionItem(_)
+                | ForeignStaticItem(_)
+                | ForeignTypeItem
+                | MacroItem(_)
+                | ProcMacroItem(_)
+                | PrimitiveItem(_)
+        )
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index f9d6b4619cc..020f6a74d69 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -522,7 +522,14 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
         (cfg, _) => cfg.as_deref().cloned(),
     };
 
-    debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.and_then(|p| p.cfg.as_ref()), cfg);
+    debug!(
+        "Portability {:?} {:?} (parent: {:?}) - {:?} = {:?}",
+        item.name,
+        item.cfg,
+        parent,
+        parent.and_then(|p| p.cfg.as_ref()),
+        cfg
+    );
 
     Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html()))
 }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 6d0a825fec8..a313b896e84 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -477,7 +477,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
         (cfg, _) => cfg.as_deref().cloned(),
     };
 
-    debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.cfg, cfg);
+    debug!("Portability name={:?} {:?} - {:?} = {:?}", item.name, item.cfg, parent.cfg, cfg);
     if let Some(ref cfg) = cfg {
         tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
     }
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 0c5d8365518..21d295bb1f8 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -2,29 +2,53 @@
 use std::sync::Arc;
 
 use crate::clean::cfg::Cfg;
+use crate::clean::inline::{load_attrs, merge_attrs};
 use crate::clean::{Crate, Item};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::Pass;
 
+use rustc_hir::def_id::LocalDefId;
+
 pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass {
     name: "propagate-doc-cfg",
     run: propagate_doc_cfg,
     description: "propagates `#[doc(cfg(...))]` to child items",
 };
 
-pub(crate) fn propagate_doc_cfg(cr: Crate, _: &mut DocContext<'_>) -> Crate {
-    CfgPropagator { parent_cfg: None }.fold_crate(cr)
+pub(crate) fn propagate_doc_cfg(cr: Crate, cx: &mut DocContext<'_>) -> Crate {
+    CfgPropagator { parent_cfg: None, parent: None, cx }.fold_crate(cr)
 }
 
-struct CfgPropagator {
+struct CfgPropagator<'a, 'tcx> {
     parent_cfg: Option<Arc<Cfg>>,
+    parent: Option<LocalDefId>,
+    cx: &'a mut DocContext<'tcx>,
 }
 
-impl DocFolder for CfgPropagator {
+impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
     fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let old_parent_cfg = self.parent_cfg.clone();
 
+        if item.kind.is_non_assoc() &&
+            let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
+            let hir = self.cx.tcx.hir();
+            let hir_id = hir.local_def_id_to_hir_id(def_id);
+            let expected_parent = hir.get_parent_item(hir_id);
+
+            // If parents are different, it means that `item` is a reexport and we need to compute
+            // the actual `cfg` by iterating through its "real" parents.
+            if self.parent != Some(expected_parent) {
+                let mut attrs = Vec::new();
+                for (parent_hir_id, _) in hir.parent_iter(hir_id) {
+                    let def_id = hir.local_def_id(parent_hir_id).to_def_id();
+                    attrs.extend_from_slice(load_attrs(self.cx, def_id));
+                }
+                let (_, cfg) =
+                    merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
+                item.cfg = cfg;
+            }
+        }
         let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
             (None, None) => None,
             (Some(rc), None) | (None, Some(rc)) => Some(rc),
@@ -37,8 +61,15 @@ impl DocFolder for CfgPropagator {
         self.parent_cfg = new_cfg.clone();
         item.cfg = new_cfg;
 
+        let old_parent =
+            if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
+                self.parent.replace(def_id)
+            } else {
+                self.parent.take()
+            };
         let result = self.fold_item_recur(item);
         self.parent_cfg = old_parent_cfg;
+        self.parent = old_parent;
 
         Some(result)
     }