add new attribute rustc_insignificant_dtor and a query to check if a type has a significant drop
This commit is contained in:
parent
1025db84a6
commit
a7e1cec621
11 changed files with 333 additions and 13 deletions
|
@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst;
|
|||
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{sym, DUMMY_SP};
|
||||
|
||||
type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
|
||||
|
||||
|
@ -21,6 +21,19 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
|
|||
res
|
||||
}
|
||||
|
||||
fn has_significant_drop_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> bool {
|
||||
let significant_drop_fields =
|
||||
move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter());
|
||||
let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
|
||||
.next()
|
||||
.is_some();
|
||||
debug!("has_significant_drop_raw({:?}) = {:?}", query, res);
|
||||
res
|
||||
}
|
||||
|
||||
struct NeedsDropTypes<'tcx, F> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -155,12 +168,20 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
|
||||
// Depending on the implentation of `adt_has_dtor`, it is used to check if the
|
||||
// ADT has a destructor or if the ADT only has a significant destructor. For
|
||||
// understanding significant destructor look at `adt_significant_drop_tys`.
|
||||
fn adt_drop_tys_helper(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
adt_has_dtor: impl Fn(&ty::AdtDef) -> bool,
|
||||
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_components = move |adt_def: &ty::AdtDef| {
|
||||
if adt_def.is_manually_drop() {
|
||||
debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
|
||||
return Ok(Vec::new().into_iter());
|
||||
} else if adt_def.destructor(tcx).is_some() {
|
||||
} else if adt_has_dtor(adt_def) {
|
||||
debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
|
||||
return Err(AlwaysRequiresDrop);
|
||||
} else if adt_def.is_union() {
|
||||
|
@ -179,6 +200,30 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw
|
|||
res.map(|components| tcx.intern_type_list(&components))
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers { needs_drop_raw, adt_drop_tys, ..*providers };
|
||||
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).is_some();
|
||||
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
|
||||
}
|
||||
|
||||
fn adt_significant_drop_tys(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
|
||||
let adt_has_dtor = |adt_def: &ty::AdtDef| {
|
||||
adt_def
|
||||
.destructor(tcx)
|
||||
.map(|dtor| !tcx.has_attr(dtor.did, sym::rustc_insignificant_dtor))
|
||||
.unwrap_or(false)
|
||||
};
|
||||
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
*providers = ty::query::Providers {
|
||||
needs_drop_raw,
|
||||
has_significant_drop_raw,
|
||||
adt_drop_tys,
|
||||
adt_significant_drop_tys,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue