@@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst;
6
6
use rustc_middle:: ty:: util:: { needs_drop_components, AlwaysRequiresDrop } ;
7
7
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
8
8
use rustc_session:: Limit ;
9
- use rustc_span:: DUMMY_SP ;
9
+ use rustc_span:: { sym , DUMMY_SP } ;
10
10
11
11
type NeedsDropResult < T > = Result < T , AlwaysRequiresDrop > ;
12
12
@@ -21,6 +21,19 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
21
21
res
22
22
}
23
23
24
+ fn has_significant_drop_raw < ' tcx > (
25
+ tcx : TyCtxt < ' tcx > ,
26
+ query : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
27
+ ) -> bool {
28
+ let significant_drop_fields =
29
+ move |adt_def : & ty:: AdtDef | tcx. adt_significant_drop_tys ( adt_def. did ) . map ( |tys| tys. iter ( ) ) ;
30
+ let res = NeedsDropTypes :: new ( tcx, query. param_env , query. value , significant_drop_fields)
31
+ . next ( )
32
+ . is_some ( ) ;
33
+ debug ! ( "has_significant_drop_raw({:?}) = {:?}" , query, res) ;
34
+ res
35
+ }
36
+
24
37
struct NeedsDropTypes < ' tcx , F > {
25
38
tcx : TyCtxt < ' tcx > ,
26
39
param_env : ty:: ParamEnv < ' tcx > ,
@@ -155,12 +168,20 @@ where
155
168
}
156
169
}
157
170
158
- fn adt_drop_tys ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Result < & ty:: List < Ty < ' _ > > , AlwaysRequiresDrop > {
171
+ // This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
172
+ // Depending on the implentation of `adt_has_dtor`, it is used to check if the
173
+ // ADT has a destructor or if the ADT only has a significant destructor. For
174
+ // understanding significant destructor look at `adt_significant_drop_tys`.
175
+ fn adt_drop_tys_helper (
176
+ tcx : TyCtxt < ' _ > ,
177
+ def_id : DefId ,
178
+ adt_has_dtor : impl Fn ( & ty:: AdtDef ) -> bool ,
179
+ ) -> Result < & ty:: List < Ty < ' _ > > , AlwaysRequiresDrop > {
159
180
let adt_components = move |adt_def : & ty:: AdtDef | {
160
181
if adt_def. is_manually_drop ( ) {
161
182
debug ! ( "adt_drop_tys: `{:?}` is manually drop" , adt_def) ;
162
183
return Ok ( Vec :: new ( ) . into_iter ( ) ) ;
163
- } else if adt_def . destructor ( tcx ) . is_some ( ) {
184
+ } else if adt_has_dtor ( adt_def ) {
164
185
debug ! ( "adt_drop_tys: `{:?}` implements `Drop`" , adt_def) ;
165
186
return Err ( AlwaysRequiresDrop ) ;
166
187
} else if adt_def. is_union ( ) {
@@ -179,6 +200,30 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw
179
200
res. map ( |components| tcx. intern_type_list ( & components) )
180
201
}
181
202
203
+ fn adt_drop_tys ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Result < & ty:: List < Ty < ' _ > > , AlwaysRequiresDrop > {
204
+ let adt_has_dtor = |adt_def : & ty:: AdtDef | adt_def. destructor ( tcx) . is_some ( ) ;
205
+ adt_drop_tys_helper ( tcx, def_id, adt_has_dtor)
206
+ }
207
+
208
+ fn adt_significant_drop_tys (
209
+ tcx : TyCtxt < ' _ > ,
210
+ def_id : DefId ,
211
+ ) -> Result < & ty:: List < Ty < ' _ > > , AlwaysRequiresDrop > {
212
+ let adt_has_dtor = |adt_def : & ty:: AdtDef | {
213
+ adt_def
214
+ . destructor ( tcx)
215
+ . map ( |dtor| !tcx. has_attr ( dtor. did , sym:: rustc_insignificant_dtor) )
216
+ . unwrap_or ( false )
217
+ } ;
218
+ adt_drop_tys_helper ( tcx, def_id, adt_has_dtor)
219
+ }
220
+
182
221
pub ( crate ) fn provide ( providers : & mut ty:: query:: Providers ) {
183
- * providers = ty:: query:: Providers { needs_drop_raw, adt_drop_tys, ..* providers } ;
222
+ * providers = ty:: query:: Providers {
223
+ needs_drop_raw,
224
+ has_significant_drop_raw,
225
+ adt_drop_tys,
226
+ adt_significant_drop_tys,
227
+ ..* providers
228
+ } ;
184
229
}
0 commit comments