@@ -32,11 +32,29 @@ pub(crate) struct Module<'hir> {
3232    pub ( crate )  def_id :  LocalDefId , 
3333    pub ( crate )  renamed :  Option < Symbol > , 
3434    pub ( crate )  import_id :  Option < LocalDefId > , 
35-     /// The key is the item `ItemId` and the value is: (item, renamed, import_id). 
35+     /// The key is the item `ItemId` and the value is: (item, renamed, Vec< import_id> ). 
3636     /// We use `FxIndexMap` to keep the insert order. 
37+      /// 
38+      /// `import_id` needs to be a `Vec` because we live in a dark world where you can have code 
39+      /// like: 
40+      /// 
41+      /// ``` 
42+      /// mod raw { 
43+      ///     pub fn foo() {} 
44+      /// } 
45+      /// 
46+      /// /// Foobar 
47+      /// pub use raw::foo; 
48+      /// 
49+      /// pub use raw::*; 
50+      /// ``` 
51+      /// 
52+      /// So in this case, we don't want to have two items but just one with attributes from all 
53+      /// non-glob imports to be merged. Glob imports attributes are always ignored, whether they're 
54+      /// shadowed or not. 
3755     pub ( crate )  items :  FxIndexMap < 
3856        ( LocalDefId ,  Option < Symbol > ) , 
39-         ( & ' hir  hir:: Item < ' hir > ,  Option < Symbol > ,  Option < LocalDefId > ) , 
57+         ( & ' hir  hir:: Item < ' hir > ,  Option < Symbol > ,  Vec < LocalDefId > ) , 
4058    > , 
4159
4260    /// (def_id, renamed) -> (res, local_import_id) 
@@ -154,7 +172,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
154172            { 
155173                let  item = self . cx . tcx . hir_expect_item ( local_def_id) ; 
156174                let  ( ident,  _,  _)  = item. expect_macro ( ) ; 
157-                 top_level_module. items . insert ( ( local_def_id,  Some ( ident. name ) ) ,  ( item,  None ,  None ) ) ; 
175+                 top_level_module
176+                     . items 
177+                     . insert ( ( local_def_id,  Some ( ident. name ) ) ,  ( item,  None ,  Vec :: new ( ) ) ) ; 
158178            } 
159179        } 
160180
@@ -236,7 +256,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
236256    )  -> bool  { 
237257        debug ! ( "maybe_inline_local (renamed: {renamed:?}) res: {res:?}" ) ; 
238258
239-         let  glob = renamed. is_none ( ) ; 
240259        if  renamed == Some ( kw:: Underscore )  { 
241260            // We never inline `_` reexports. 
242261            return  false ; 
@@ -261,14 +280,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
261280            return  false ; 
262281        } 
263282
283+         let  is_glob = renamed. is_none ( ) ; 
264284        let  is_hidden = !document_hidden && tcx. is_doc_hidden ( ori_res_did) ; 
265285        let  Some ( res_did)  = ori_res_did. as_local ( )  else  { 
266286            // For cross-crate impl inlining we need to know whether items are 
267287            // reachable in documentation -- a previously unreachable item can be 
268288            // made reachable by cross-crate inlining which we're checking here. 
269289            // (this is done here because we need to know this upfront). 
270290            crate :: visit_lib:: lib_embargo_visit_item ( self . cx ,  ori_res_did) ; 
271-             if  is_hidden || glob  { 
291+             if  is_hidden || is_glob  { 
272292                return  false ; 
273293            } 
274294            // We store inlined foreign items otherwise, it'd mean that the `use` item would be kept 
@@ -316,10 +336,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
316336            // Bang macros are handled a bit on their because of how they are handled by the 
317337            // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have 
318338            // `#[doc(inline)]`, then we don't inline it. 
319-             Node :: Item ( _)  if  is_bang_macro && !please_inline && renamed . is_some ( )  && is_hidden => { 
339+             Node :: Item ( _)  if  is_bang_macro && !please_inline && !is_glob  && is_hidden => { 
320340                return  false ; 
321341            } 
322-             Node :: Item ( & hir:: Item  {  kind :  hir:: ItemKind :: Mod ( _,  m) ,  .. } )  if  glob  => { 
342+             Node :: Item ( & hir:: Item  {  kind :  hir:: ItemKind :: Mod ( _,  m) ,  .. } )  if  is_glob  => { 
323343                let  prev = mem:: replace ( & mut  self . inlining ,  true ) ; 
324344                for  & i in  m. item_ids  { 
325345                    let  i = tcx. hir_item ( i) ; 
@@ -328,13 +348,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
328348                self . inlining  = prev; 
329349                true 
330350            } 
331-             Node :: Item ( it)  if  !glob  => { 
351+             Node :: Item ( it)  if  !is_glob  => { 
332352                let  prev = mem:: replace ( & mut  self . inlining ,  true ) ; 
333353                self . visit_item_inner ( it,  renamed,  Some ( def_id) ) ; 
334354                self . inlining  = prev; 
335355                true 
336356            } 
337-             Node :: ForeignItem ( it)  if  !glob  => { 
357+             Node :: ForeignItem ( it)  if  !is_glob  => { 
338358                let  prev = mem:: replace ( & mut  self . inlining ,  true ) ; 
339359                self . visit_foreign_item_inner ( it,  renamed,  Some ( def_id) ) ; 
340360                self . inlining  = prev; 
@@ -378,8 +398,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
378398    fn  add_to_current_mod ( 
379399        & mut  self , 
380400        item :  & ' tcx  hir:: Item < ' _ > , 
381-         renamed :  Option < Symbol > , 
382-         parent_id :  Option < LocalDefId > , 
401+         mut   renamed :  Option < Symbol > , 
402+         import_id :  Option < LocalDefId > , 
383403    )  { 
384404        if  self . is_importable_from_parent 
385405            // If we're inside an item, only impl blocks and `macro_rules!` with the `macro_export` 
@@ -392,11 +412,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
392412                _ => false , 
393413            } 
394414        { 
395-             self . modules 
396-                 . last_mut ( ) 
397-                 . unwrap ( ) 
398-                 . items 
399-                 . insert ( ( item. owner_id . def_id ,  renamed) ,  ( item,  renamed,  parent_id) ) ; 
415+             if  renamed == item. kind . ident ( ) . map ( |ident| ident. name )  { 
416+                 renamed = None ; 
417+             } 
418+             let  key = ( item. owner_id . def_id ,  renamed) ; 
419+             if  let  Some ( import_id)  = import_id { 
420+                 self . modules 
421+                     . last_mut ( ) 
422+                     . unwrap ( ) 
423+                     . items 
424+                     . entry ( key) 
425+                     . and_modify ( |v| v. 2 . push ( import_id) ) 
426+                     . or_insert_with ( || ( item,  renamed,  vec ! [ import_id] ) ) ; 
427+             }  else  { 
428+                 self . modules . last_mut ( ) . unwrap ( ) . items . insert ( key,  ( item,  renamed,  Vec :: new ( ) ) ) ; 
429+             } 
400430        } 
401431    } 
402432
@@ -468,7 +498,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
468498                            _ => false , 
469499                        } ) ; 
470500                        let  ident = match  kind { 
471-                             hir:: UseKind :: Single ( ident)  => Some ( renamed . unwrap_or ( ident. name ) ) , 
501+                             hir:: UseKind :: Single ( ident)  => Some ( ident. name ) , 
472502                            hir:: UseKind :: Glob  => None , 
473503                            hir:: UseKind :: ListStem  => unreachable ! ( ) , 
474504                        } ; 
0 commit comments