@@ -103,16 +103,18 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> {
103
103
// we will proceed with `succ`
104
104
let dropped_local_there = match self . visited . entry ( succ) {
105
105
hash_map:: Entry :: Occupied ( occupied_entry) => {
106
- if !occupied_entry. get ( ) . borrow_mut ( ) . union ( & * dropped_local_here. borrow ( ) ) {
106
+ if succ == block
107
+ || !occupied_entry. get ( ) . borrow_mut ( ) . union ( & * dropped_local_here. borrow ( ) )
108
+ {
107
109
// `succ` has been visited but no new drops observed so far,
108
110
// so we can bail on `succ` until new drop information arrives
109
111
continue ;
110
112
}
111
113
occupied_entry. get ( ) . clone ( )
112
114
}
113
- hash_map:: Entry :: Vacant ( vacant_entry) => {
114
- vacant_entry . insert ( dropped_local_here. clone ( ) ) . clone ( )
115
- }
115
+ hash_map:: Entry :: Vacant ( vacant_entry) => vacant_entry
116
+ . insert ( Rc :: new ( RefCell :: new ( dropped_local_here. borrow ( ) . clone ( ) ) ) )
117
+ . clone ( ) ,
116
118
} ;
117
119
if let Some ( terminator) = & target. terminator
118
120
&& let TerminatorKind :: Drop {
@@ -141,6 +143,61 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> {
141
143
}
142
144
}
143
145
146
+ fn true_significant_drop_ty < ' tcx > (
147
+ tcx : TyCtxt < ' tcx > ,
148
+ ty : Ty < ' tcx > ,
149
+ ) -> Option < SmallVec < [ Ty < ' tcx > ; 2 ] > > {
150
+ if let ty:: Adt ( def, args) = ty. kind ( ) {
151
+ let mut did = def. did ( ) ;
152
+ let mut name_rev = vec ! [ ] ;
153
+ loop {
154
+ let key = tcx. def_key ( did) ;
155
+
156
+ match key. disambiguated_data . data {
157
+ rustc_hir:: definitions:: DefPathData :: CrateRoot => {
158
+ name_rev. push ( tcx. crate_name ( did. krate ) )
159
+ }
160
+ rustc_hir:: definitions:: DefPathData :: TypeNs ( symbol) => name_rev. push ( symbol) ,
161
+ _ => return None ,
162
+ }
163
+ if let Some ( parent) = key. parent {
164
+ did = DefId { krate : did. krate , index : parent } ;
165
+ } else {
166
+ break ;
167
+ }
168
+ }
169
+ let name_str: Vec < _ > = name_rev. iter ( ) . rev ( ) . map ( |x| x. as_str ( ) ) . collect ( ) ;
170
+ debug ! ( ?name_str) ;
171
+ match name_str[ ..] {
172
+ // These are the types from Rust core ecosystem
173
+ [ "sym" | "proc_macro2" , ..] | [ "core" | "std" , "task" , "RawWaker" ] => Some ( smallvec ! [ ] ) ,
174
+ // These are important types from Rust ecosystem
175
+ [ "tracing" , "instrument" , "Instrumented" ] | [ "bytes" , "Bytes" ] => Some ( smallvec ! [ ] ) ,
176
+ [ "hashbrown" , "raw" , "RawTable" | "RawIntoIter" ] => {
177
+ if let [ ty, ..] = & * * * args
178
+ && let Some ( ty) = ty. as_type ( )
179
+ {
180
+ Some ( smallvec ! [ ty] )
181
+ } else {
182
+ None
183
+ }
184
+ }
185
+ [ "hashbrown" , "raw" , "RawDrain" ] => {
186
+ if let [ _, ty, ..] = & * * * args
187
+ && let Some ( ty) = ty. as_type ( )
188
+ {
189
+ Some ( smallvec ! [ ty] )
190
+ } else {
191
+ None
192
+ }
193
+ }
194
+ _ => None ,
195
+ }
196
+ } else {
197
+ None
198
+ }
199
+ }
200
+
144
201
#[ instrument( level = "debug" , skip( tcx, param_env) ) ]
145
202
fn extract_component_raw < ' tcx > (
146
203
tcx : TyCtxt < ' tcx > ,
@@ -154,7 +211,14 @@ fn extract_component_raw<'tcx>(
154
211
debug ! ( ?ty, "components" ) ;
155
212
let mut out_tys = smallvec ! [ ] ;
156
213
for ty in tys {
157
- out_tys. push ( ty) ;
214
+ if let Some ( tys) = true_significant_drop_ty ( tcx, ty) {
215
+ // Some types can be further opened up because the drop is simply delegated
216
+ for ty in tys {
217
+ out_tys. extend ( extract_component_raw ( tcx, param_env, ty) ) ;
218
+ }
219
+ } else {
220
+ out_tys. push ( ty) ;
221
+ }
158
222
}
159
223
out_tys
160
224
}
0 commit comments