@@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst;
66use rustc_middle:: ty:: util:: { needs_drop_components, AlwaysRequiresDrop } ;
77use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
88use rustc_session:: Limit ;
9- use rustc_span:: DUMMY_SP ;
9+ use rustc_span:: { sym , DUMMY_SP } ;
1010
1111type NeedsDropResult < T > = Result < T , AlwaysRequiresDrop > ;
1212
@@ -21,6 +21,19 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
2121 res
2222}
2323
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+
2437struct NeedsDropTypes < ' tcx , F > {
2538 tcx : TyCtxt < ' tcx > ,
2639 param_env : ty:: ParamEnv < ' tcx > ,
@@ -155,12 +168,20 @@ where
155168 }
156169}
157170
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 > {
159180 let adt_components = move |adt_def : & ty:: AdtDef | {
160181 if adt_def. is_manually_drop ( ) {
161182 debug ! ( "adt_drop_tys: `{:?}` is manually drop" , adt_def) ;
162183 return Ok ( Vec :: new ( ) . into_iter ( ) ) ;
163- } else if adt_def . destructor ( tcx ) . is_some ( ) {
184+ } else if adt_has_dtor ( adt_def ) {
164185 debug ! ( "adt_drop_tys: `{:?}` implements `Drop`" , adt_def) ;
165186 return Err ( AlwaysRequiresDrop ) ;
166187 } else if adt_def. is_union ( ) {
@@ -179,6 +200,30 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw
179200 res. map ( |components| tcx. intern_type_list ( & components) )
180201}
181202
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+
182221pub ( 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+ } ;
184229}
0 commit comments