@@ -65,15 +65,18 @@ impl Module<'hir> {
6565
6666 pub ( crate ) fn push_item ( & mut self , ctx : & DocContext < ' _ > , new_item : Item < ' hir > ) {
6767 let new_item_ns = ctx. tcx . def_kind ( new_item. hir_item . def_id ) . ns ( ) ;
68+ let mut to_remove = None ;
6869 if !new_item. name ( ) . is_empty ( ) && new_item_ns. is_some ( ) {
69- if let Some ( existing_item) = self . items . iter_mut ( ) . find ( |item| {
70- item. name ( ) == new_item. name ( )
71- && ctx. tcx . def_kind ( item. hir_item . def_id ) . ns ( ) == new_item_ns
72- } ) {
70+ if let Some ( ( index, existing_item) ) =
71+ self . items . iter_mut ( ) . enumerate ( ) . find ( |( _, item) | {
72+ item. name ( ) == new_item. name ( )
73+ && ctx. tcx . def_kind ( item. hir_item . def_id ) . ns ( ) == new_item_ns
74+ } )
75+ {
7376 match ( existing_item. from_glob , new_item. from_glob ) {
74- ( true , _ ) => {
75- // `existing_item` is from glob, no matter whether `new_item` is from glob ,
76- // `new_item` should always shadow `existing_item`
77+ ( true , false ) => {
78+ // `existing_item` is from glob, `new_item` is not ,
79+ // `new_item` should shadow `existing_item`
7780 debug ! ( "push_item: {:?} shadowed by {:?}" , existing_item, new_item) ;
7881 * existing_item = new_item;
7982 return ;
@@ -83,27 +86,56 @@ impl Module<'hir> {
8386 // just keep `existing_item` and return at once
8487 return ;
8588 }
89+ ( true , true ) => {
90+ // both `existing_item` and `new_item` are from glob
91+ if existing_item. hir_item . def_id == new_item. hir_item . def_id {
92+ // they actually point to same object, it is ok to just keep one of them
93+ return ;
94+ } else {
95+ // a "glob import vs glob import in the same module" will raise when actually use these item
96+ // we should accept neither of these two items
97+ to_remove = Some ( index) ;
98+ }
99+ }
86100 ( false , false ) => {
87101 // should report "defined multiple time" error before reach this
88102 unreachable ! ( )
89103 }
90104 }
91105 }
92106 }
107+ if let Some ( index) = to_remove {
108+ self . items . swap_remove ( index) ;
109+ return ;
110+ }
93111 // no item with same name and namespace exists, just collect `new_item`
94112 self . items . push ( new_item) ;
95113 }
96114
97115 pub ( crate ) fn push_mod ( & mut self , new_mod : Module < ' hir > ) {
98- if let Some ( existing_mod) = self . mods . iter_mut ( ) . find ( |mod_| mod_. name == new_mod. name ) {
116+ let mut to_remove = None ;
117+ if let Some ( ( index, existing_mod) ) =
118+ self . mods . iter_mut ( ) . enumerate ( ) . find ( |( _, mod_) | mod_. name == new_mod. name )
119+ {
99120 match ( existing_mod. from_glob , new_mod. from_glob ) {
100- ( true , _ ) => {
121+ ( true , false ) => {
101122 // `existing_mod` is from glob, no matter whether `new_mod` is from glob,
102123 // `new_mod` should always shadow `existing_mod`
103124 debug ! ( "push_mod: {:?} shadowed by {:?}" , existing_mod. name, new_mod. name) ;
104125 * existing_mod = new_mod;
105126 return ;
106127 }
128+ ( true , true ) => {
129+ // both `existing_item` and `new_item` are from glob
130+ if existing_mod. id == new_mod. id {
131+ // they actually point to same object, it is ok to just keep one of them
132+ return ;
133+ } else {
134+ // a "glob import vs glob import in the same module" will raise when actually use these item
135+ // we should accept neither of these two items
136+ to_remove = Some ( index) ;
137+ }
138+ }
107139 ( false , true ) => {
108140 // `existing_mod` is not from glob but `new_mod` is,
109141 // just keep `existing_mod` and return at once
@@ -115,6 +147,10 @@ impl Module<'hir> {
115147 }
116148 }
117149 }
150+ if let Some ( index) = to_remove {
151+ self . mods . swap_remove ( index) ;
152+ return ;
153+ }
118154 // no mod with same name exists, just collect `new_mod`
119155 self . mods . push ( new_mod) ;
120156 }
0 commit comments