Skip to content

Commit 9158fc2

Browse files
committed
Fixes incorrect handling of ADT's drop requirements
See rust-lang#90024 (comment)
1 parent 0119879 commit 9158fc2

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

compiler/rustc_ty_utils/src/needs_drop.rs

+54-41
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ use rustc_span::{sym, DUMMY_SP};
1212
type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
1313

1414
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
15-
let adt_components =
16-
move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
17-
1815
// If we don't know a type doesn't need drop, for example if it's a type
1916
// parameter without a `Copy` bound, then we conservatively return that it
2017
// needs drop.
21-
let res =
22-
NeedsDropTypes::new(tcx, query.param_env, query.value, adt_components).next().is_some();
18+
let adt_has_dtor =
19+
|adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
20+
let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor).next().is_some();
2321

2422
debug!("needs_drop_raw({:?}) = {:?}", query, res);
2523
res
@@ -29,12 +27,10 @@ fn has_significant_drop_raw<'tcx>(
2927
tcx: TyCtxt<'tcx>,
3028
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
3129
) -> bool {
32-
let significant_drop_fields = move |adt_def: &ty::AdtDef, _| {
33-
tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter())
34-
};
35-
let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
36-
.next()
37-
.is_some();
30+
let res =
31+
drop_tys_helper(tcx, query.value, query.param_env, adt_consider_insignificant_dtor(tcx))
32+
.next()
33+
.is_some();
3834
debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
3935
res
4036
}
@@ -140,15 +136,14 @@ where
140136
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
141137
// impl then check whether the field types need `Drop`.
142138
ty::Adt(adt_def, substs) => {
139+
debug!("Got value {:?} with substs {:?}", adt_def, substs);
143140
let tys = match (self.adt_components)(adt_def, substs) {
144141
Err(e) => return Some(Err(e)),
145142
Ok(tys) => tys,
146143
};
147144
for required_ty in tys {
148-
let subst_ty = tcx.normalize_erasing_regions(
149-
self.param_env,
150-
required_ty.subst(tcx, substs),
151-
);
145+
let subst_ty =
146+
tcx.normalize_erasing_regions(self.param_env, required_ty);
152147
queue_type(self, subst_ty);
153148
}
154149
}
@@ -187,11 +182,12 @@ enum DtorType {
187182
// Depending on the implentation of `adt_has_dtor`, it is used to check if the
188183
// ADT has a destructor or if the ADT only has a significant destructor. For
189184
// understanding significant destructor look at `adt_significant_drop_tys`.
190-
fn adt_drop_tys_helper<'tcx>(
185+
fn drop_tys_helper<'tcx>(
191186
tcx: TyCtxt<'tcx>,
192-
def_id: DefId,
187+
ty: Ty<'tcx>,
188+
param_env: rustc_middle::ty::ParamEnv<'tcx>,
193189
adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
194-
) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
190+
) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> {
195191
let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
196192
if adt_def.is_manually_drop() {
197193
debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
@@ -215,31 +211,25 @@ fn adt_drop_tys_helper<'tcx>(
215211
debug!("adt_drop_tys: `{:?}` is a union", adt_def);
216212
return Ok(Vec::new().into_iter());
217213
}
218-
Ok(adt_def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>().into_iter())
214+
debug!("Path");
215+
Ok(adt_def
216+
.all_fields()
217+
.map(|field| {
218+
let r = tcx.type_of(field.did).subst(tcx, substs);
219+
debug!("Subst into {:?} with {:?} gettng {:?}", field, substs, r);
220+
r
221+
})
222+
.collect::<Vec<_>>()
223+
.into_iter())
219224
};
220225

221-
let adt_ty = tcx.type_of(def_id);
222-
let param_env = tcx.param_env(def_id);
223-
let res: Result<Vec<_>, _> =
224-
NeedsDropTypes::new(tcx, param_env, adt_ty, adt_components).collect();
225-
226-
debug!("adt_drop_tys(`{}`) = `{:?}`", tcx.def_path_str(def_id), res);
227-
res.map(|components| tcx.intern_type_list(&components))
226+
NeedsDropTypes::new(tcx, param_env, ty, adt_components)
228227
}
229228

230-
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
231-
// This is for the "needs_drop" query, that considers all `Drop` impls, therefore all dtors are
232-
// significant.
233-
let adt_has_dtor =
234-
|adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
235-
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
236-
}
237-
238-
fn adt_significant_drop_tys(
239-
tcx: TyCtxt<'_>,
240-
def_id: DefId,
241-
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
242-
let adt_has_dtor = |adt_def: &ty::AdtDef| {
229+
fn adt_consider_insignificant_dtor<'tcx>(
230+
tcx: TyCtxt<'tcx>,
231+
) -> impl Fn(&ty::AdtDef) -> Option<DtorType> + 'tcx {
232+
move |adt_def: &ty::AdtDef| {
243233
let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor);
244234
if is_marked_insig {
245235
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
@@ -256,8 +246,31 @@ fn adt_significant_drop_tys(
256246
// treat this as the simple case of Drop impl for type.
257247
None
258248
}
259-
};
260-
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
249+
}
250+
}
251+
252+
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
253+
// This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are
254+
// significant.
255+
let adt_has_dtor =
256+
|adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
257+
drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor)
258+
.collect::<Result<Vec<_>, _>>()
259+
.map(|components| tcx.intern_type_list(&components))
260+
}
261+
262+
fn adt_significant_drop_tys(
263+
tcx: TyCtxt<'_>,
264+
def_id: DefId,
265+
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
266+
drop_tys_helper(
267+
tcx,
268+
tcx.type_of(def_id),
269+
tcx.param_env(def_id),
270+
adt_consider_insignificant_dtor(tcx),
271+
)
272+
.collect::<Result<Vec<_>, _>>()
273+
.map(|components| tcx.intern_type_list(&components))
261274
}
262275

263276
pub(crate) fn provide(providers: &mut ty::query::Providers) {

0 commit comments

Comments
 (0)