@@ -65,15 +65,18 @@ impl Module<'hir> {
65
65
66
66
pub ( crate ) fn push_item ( & mut self , ctx : & DocContext < ' _ > , new_item : Item < ' hir > ) {
67
67
let new_item_ns = ctx. tcx . def_kind ( new_item. hir_item . def_id ) . ns ( ) ;
68
+ let mut to_remove = None ;
68
69
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
+ {
73
76
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`
77
80
debug ! ( "push_item: {:?} shadowed by {:?}" , existing_item, new_item) ;
78
81
* existing_item = new_item;
79
82
return ;
@@ -83,27 +86,56 @@ impl Module<'hir> {
83
86
// just keep `existing_item` and return at once
84
87
return ;
85
88
}
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
+ }
86
100
( false , false ) => {
87
101
// should report "defined multiple time" error before reach this
88
102
unreachable ! ( )
89
103
}
90
104
}
91
105
}
92
106
}
107
+ if let Some ( index) = to_remove {
108
+ self . items . swap_remove ( index) ;
109
+ return ;
110
+ }
93
111
// no item with same name and namespace exists, just collect `new_item`
94
112
self . items . push ( new_item) ;
95
113
}
96
114
97
115
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
+ {
99
120
match ( existing_mod. from_glob , new_mod. from_glob ) {
100
- ( true , _ ) => {
121
+ ( true , false ) => {
101
122
// `existing_mod` is from glob, no matter whether `new_mod` is from glob,
102
123
// `new_mod` should always shadow `existing_mod`
103
124
debug ! ( "push_mod: {:?} shadowed by {:?}" , existing_mod. name, new_mod. name) ;
104
125
* existing_mod = new_mod;
105
126
return ;
106
127
}
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
+ }
107
139
( false , true ) => {
108
140
// `existing_mod` is not from glob but `new_mod` is,
109
141
// just keep `existing_mod` and return at once
@@ -115,6 +147,10 @@ impl Module<'hir> {
115
147
}
116
148
}
117
149
}
150
+ if let Some ( index) = to_remove {
151
+ self . mods . swap_remove ( index) ;
152
+ return ;
153
+ }
118
154
// no mod with same name exists, just collect `new_mod`
119
155
self . mods . push ( new_mod) ;
120
156
}
0 commit comments