]> git.lizzy.rs Git - rust.git/commitdiff
Fix merge of attributes for reexports of local items
authorGuillaume Gomez <guillaume.gomez@huawei.com>
Wed, 2 Nov 2022 15:51:37 +0000 (16:51 +0100)
committerGuillaume Gomez <guillaume.gomez@huawei.com>
Wed, 2 Nov 2022 16:36:35 +0000 (17:36 +0100)
src/librustdoc/clean/mod.rs
src/librustdoc/visit_ast.rs

index 1ce0d1e4ffd02c3bcf104d68971a9bac83f32153..ad4ad4104e104e9d48562e13d4fe6b9bae150843 100644 (file)
@@ -74,12 +74,12 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     // This covers the case where somebody does an import which should pull in an item,
     // but there's already an item with the same namespace and same name. Rust gives
     // priority to the not-imported one, so we should, too.
-    items.extend(doc.items.iter().flat_map(|(item, renamed)| {
+    items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
         // First, lower everything other than imports.
         if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
             return Vec::new();
         }
-        let v = clean_maybe_renamed_item(cx, item, *renamed);
+        let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
         for item in &v {
             if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
                 inserted.insert((item.type_(), name));
@@ -87,7 +87,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
         }
         v
     }));
-    items.extend(doc.items.iter().flat_map(|(item, renamed)| {
+    items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
         // Now we actually lower the imports, skipping everything else.
         if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
             let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
@@ -1911,6 +1911,7 @@ fn clean_maybe_renamed_item<'tcx>(
     cx: &mut DocContext<'tcx>,
     item: &hir::Item<'tcx>,
     renamed: Option<Symbol>,
+    import_id: Option<hir::HirId>,
 ) -> Vec<Item> {
     use hir::ItemKind;
 
@@ -1987,8 +1988,23 @@ fn clean_maybe_renamed_item<'tcx>(
             }
             _ => unreachable!("not yet converted"),
         };
-
-        vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
+        if let Some(import_id) = import_id {
+            let (attrs, cfg) = inline::merge_attrs(
+                cx,
+                Some(cx.tcx.parent_module(import_id).to_def_id()),
+                inline::load_attrs(cx, def_id),
+                Some(inline::load_attrs(cx, cx.tcx.hir().local_def_id(import_id).to_def_id())),
+            );
+            vec![Item::from_def_id_and_attrs_and_parts(
+                def_id,
+                Some(name),
+                kind,
+                Box::new(attrs),
+                cfg,
+            )]
+        } else {
+            vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
+        }
     })
 }
 
index 7ee7eb25e0d90ca8165bf67354f3300e893dae61..c788b9f4093fea7721b838118443e16a71708ee1 100644 (file)
@@ -25,8 +25,8 @@ pub(crate) struct Module<'hir> {
     pub(crate) where_inner: Span,
     pub(crate) mods: Vec<Module<'hir>>,
     pub(crate) id: hir::HirId,
-    // (item, renamed)
-    pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
+    // (item, renamed, import_id)
+    pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<hir::HirId>)>,
     pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
 }
 
@@ -93,6 +93,7 @@ pub(crate) fn visit(mut self) -> Module<'tcx> {
             hir::CRATE_HIR_ID,
             self.cx.tcx.hir().root_module(),
             self.cx.tcx.crate_name(LOCAL_CRATE),
+            None,
         );
 
         // `#[macro_export] macro_rules!` items are reexported at the top level of the
@@ -113,7 +114,7 @@ pub(crate) fn visit(mut self) -> Module<'tcx> {
                     if self.cx.tcx.has_attr(def_id, sym::macro_export) {
                         if inserted.insert(def_id) {
                             let item = self.cx.tcx.hir().expect_item(local_def_id);
-                            top_level_module.items.push((item, None));
+                            top_level_module.items.push((item, None, None));
                         }
                     }
                 }
@@ -155,6 +156,7 @@ fn visit_mod_contents(
         id: hir::HirId,
         m: &'tcx hir::Mod<'tcx>,
         name: Symbol,
+        parent_id: Option<hir::HirId>,
     ) -> Module<'tcx> {
         let mut om = Module::new(name, id, m.spans.inner_span);
         let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
@@ -166,7 +168,7 @@ fn visit_mod_contents(
             if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
                 continue;
             }
-            self.visit_item(item, None, &mut om);
+            self.visit_item(item, None, &mut om, parent_id);
         }
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
@@ -174,7 +176,7 @@ fn visit_mod_contents(
             // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
             // imported items appear last, then they'll be the ones that get discarded.
             if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                self.visit_item(item, None, &mut om);
+                self.visit_item(item, None, &mut om, parent_id);
             }
         }
         self.inside_public_path = orig_inside_public_path;
@@ -247,14 +249,14 @@ fn maybe_inline_local(
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
                     let i = self.cx.tcx.hir().item(i);
-                    self.visit_item(i, None, om);
+                    self.visit_item(i, None, om, Some(id));
                 }
                 self.inlining = prev;
                 true
             }
             Node::Item(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_item(it, renamed, om);
+                self.visit_item(it, renamed, om, Some(id));
                 self.inlining = prev;
                 true
             }
@@ -275,6 +277,7 @@ fn visit_item(
         item: &'tcx hir::Item<'_>,
         renamed: Option<Symbol>,
         om: &mut Module<'tcx>,
+        parent_id: Option<hir::HirId>,
     ) {
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
@@ -330,7 +333,7 @@ fn visit_item(
                     }
                 }
 
-                om.items.push((item, renamed))
+                om.items.push((item, renamed, parent_id))
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
                 // `#[macro_export] macro_rules!` items are handled separately in `visit()`,
@@ -349,11 +352,11 @@ fn visit_item(
                 let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
 
                 if is_macro_2_0 || nonexported || self.inlining {
-                    om.items.push((item, renamed));
+                    om.items.push((item, renamed, None));
                 }
             }
             hir::ItemKind::Mod(ref m) => {
-                om.mods.push(self.visit_mod_contents(item.hir_id(), m, name));
+                om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
@@ -364,19 +367,19 @@ fn visit_item(
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Trait(..)
-            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
+            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
             hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
                 if name != kw::Underscore {
-                    om.items.push((item, renamed));
+                    om.items.push((item, renamed, parent_id));
                 }
             }
             hir::ItemKind::Impl(impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && impl_.of_trait.is_none() {
-                    om.items.push((item, None));
+                    om.items.push((item, None, None));
                 }
             }
         }