Don't require Drop for [PhantomData<T>; N] where N and T are generic, if T requires Drop

This commit is contained in:
Oli Scherer 2023-09-04 08:54:27 +00:00
parent 61efe9d298
commit 320bb8116f
2 changed files with 39 additions and 2 deletions

View File

@ -19,13 +19,32 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
// needs drop.
let adt_has_dtor =
|adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
let res =
drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some();
let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false)
.filter(filter_array_elements(tcx, query.param_env))
.next()
.is_some();
debug!("needs_drop_raw({:?}) = {:?}", query, res);
res
}
/// HACK: in order to not mistakenly assume that `[PhantomData<T>; N]` requires drop glue
/// we check the element type for drop glue. The correct fix would be looking at the
/// entirety of the code around `needs_drop_components` and this file and come up with
/// logic that is easier to follow while not repeating any checks that may thus diverge.
fn filter_array_elements<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> impl Fn(&Result<Ty<'tcx>, AlwaysRequiresDrop>) -> bool {
move |ty| match ty {
Ok(ty) => match *ty.kind() {
ty::Array(elem, _) => tcx.needs_drop_raw(param_env.and(elem)),
_ => true,
},
Err(AlwaysRequiresDrop) => true,
}
}
fn has_significant_drop_raw<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
@ -37,6 +56,7 @@ fn has_significant_drop_raw<'tcx>(
adt_consider_insignificant_dtor(tcx),
true,
)
.filter(filter_array_elements(tcx, query.param_env))
.next()
.is_some();
debug!("has_significant_drop_raw({:?}) = {:?}", query, res);

View File

@ -0,0 +1,17 @@
// build-pass
pub const fn f<T, const N: usize>(_: [std::mem::MaybeUninit<T>; N]) {}
pub struct Blubb<T>(*const T);
pub const fn g<T, const N: usize>(_: [Blubb<T>; N]) {}
pub struct Blorb<const N: usize>([String; N]);
pub const fn h(_: Blorb<0>) {}
pub struct Wrap(Blorb<0>);
pub const fn i(_: Wrap) {}
fn main() {}