Start implementing needs_async_drop and related
This commit is contained in:
parent
e0904cd6a9
commit
a47173c4f7
@ -112,6 +112,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
wfcheck::provide(providers);
|
||||
*providers = Providers {
|
||||
adt_destructor,
|
||||
adt_async_destructor,
|
||||
region_scope_tree,
|
||||
collect_return_position_impl_trait_in_trait_tys,
|
||||
compare_impl_const: compare_impl_item::compare_impl_const_raw,
|
||||
@ -124,6 +125,10 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor>
|
||||
tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
|
||||
tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl)
|
||||
}
|
||||
|
||||
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
||||
/// expressions.
|
||||
fn get_owner_return_paths(
|
||||
|
@ -287,6 +287,10 @@ fn into_args(self) -> (DefId, SimplifiedType) {
|
||||
let _ = cdata;
|
||||
tcx.calculate_dtor(def_id, |_,_| Ok(()))
|
||||
}
|
||||
adt_async_destructor => {
|
||||
let _ = cdata;
|
||||
tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
|
||||
}
|
||||
associated_item_def_ids => {
|
||||
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
|
||||
}
|
||||
|
@ -238,6 +238,7 @@ impl EraseType for $ty {
|
||||
Option<rustc_hir::CoroutineKind>,
|
||||
Option<rustc_hir::HirId>,
|
||||
Option<rustc_middle::middle::stability::DeprecationEntry>,
|
||||
Option<rustc_middle::ty::AsyncDestructor>,
|
||||
Option<rustc_middle::ty::Destructor>,
|
||||
Option<rustc_middle::ty::ImplTraitInTraitData>,
|
||||
Option<rustc_middle::ty::ScalarInt>,
|
||||
@ -295,6 +296,7 @@ impl EraseType for $ty {
|
||||
rustc_middle::ty::AssocItem,
|
||||
rustc_middle::ty::AssocItemContainer,
|
||||
rustc_middle::ty::Asyncness,
|
||||
rustc_middle::ty::AsyncDestructor,
|
||||
rustc_middle::ty::BoundVariableKind,
|
||||
rustc_middle::ty::DeducedParamAttrs,
|
||||
rustc_middle::ty::Destructor,
|
||||
|
@ -703,6 +703,11 @@
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
query adt_async_destructor(key: DefId) -> Option<ty::AsyncDestructor> {
|
||||
desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
|
||||
@ -1343,18 +1348,14 @@
|
||||
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` is `Unpin`", env.value }
|
||||
}
|
||||
/// Query backing `Ty::has_surface_async_drop`.
|
||||
query has_surface_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` has `AsyncDrop` implementation", env.value }
|
||||
}
|
||||
/// Query backing `Ty::has_surface_drop`.
|
||||
query has_surface_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` has `Drop` implementation", env.value }
|
||||
}
|
||||
/// Query backing `Ty::needs_drop`.
|
||||
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` needs drop", env.value }
|
||||
}
|
||||
/// Query backing `Ty::needs_async_drop`.
|
||||
query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` needs async drop", env.value }
|
||||
}
|
||||
/// Query backing `Ty::has_significant_drop_raw`.
|
||||
query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` has a significant drop", env.value }
|
||||
|
@ -24,7 +24,9 @@
|
||||
use std::ops::Range;
|
||||
use std::str;
|
||||
|
||||
use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr};
|
||||
use super::{
|
||||
AsyncDestructor, Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct AdtFlags(u16);
|
||||
@ -577,6 +579,12 @@ pub fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
|
||||
tcx.adt_destructor(self.did())
|
||||
}
|
||||
|
||||
// FIXME(zetanumbers): consider supporting this method in same places where
|
||||
// `destructor` is referenced
|
||||
pub fn async_destructor(self, tcx: TyCtxt<'tcx>) -> Option<AsyncDestructor> {
|
||||
tcx.adt_async_destructor(self.did())
|
||||
}
|
||||
|
||||
/// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
|
||||
/// or `None` if the type is always sized.
|
||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
||||
|
@ -1172,6 +1172,15 @@ pub struct Destructor {
|
||||
pub constness: hir::Constness,
|
||||
}
|
||||
|
||||
// FIXME: consider combining this definition with regular `Destructor`
|
||||
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
|
||||
pub struct AsyncDestructor {
|
||||
/// The `DefId` of the async destructor future constructor
|
||||
pub ctor: DefId,
|
||||
/// The `DefId` of the async destructor future type
|
||||
pub future: DefId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct VariantFlags(u8);
|
||||
bitflags::bitflags! {
|
||||
|
@ -1991,7 +1991,7 @@ pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -
|
||||
ty::Adt(adt_def, _) => {
|
||||
assert!(adt_def.is_union());
|
||||
|
||||
let surface_drop = self.surface_async_dropper_ty(tcx, param_env).unwrap();
|
||||
let surface_drop = self.surface_async_dropper_ty(tcx).unwrap();
|
||||
|
||||
Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
|
||||
.instantiate(tcx, &[surface_drop.into()])
|
||||
@ -2041,7 +2041,7 @@ fn adt_async_destructor_ty<I>(
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx, param_env) {
|
||||
let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx) {
|
||||
Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain)
|
||||
.instantiate(tcx, &[dropper_ty.into(), variants_dtor.into()])
|
||||
} else {
|
||||
@ -2052,21 +2052,13 @@ fn adt_async_destructor_ty<I>(
|
||||
.instantiate(tcx, &[dtor.into()])
|
||||
}
|
||||
|
||||
fn surface_async_dropper_ty(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
if self.has_surface_async_drop(tcx, param_env) {
|
||||
Some(LangItem::SurfaceAsyncDropInPlace)
|
||||
} else if self.has_surface_drop(tcx, param_env) {
|
||||
Some(LangItem::AsyncDropSurfaceDropInPlace)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.map(|dropper| {
|
||||
Ty::async_destructor_combinator(tcx, dropper).instantiate(tcx, &[self.into()])
|
||||
})
|
||||
fn surface_async_dropper_ty(self, tcx: TyCtxt<'tcx>) -> Option<Ty<'tcx>> {
|
||||
let adt_def = self.ty_adt_def()?;
|
||||
let dropper = adt_def
|
||||
.async_destructor(tcx)
|
||||
.map(|_| LangItem::SurfaceAsyncDropInPlace)
|
||||
.or_else(|| adt_def.destructor(tcx).map(|_| LangItem::AsyncDropSurfaceDropInPlace))?;
|
||||
Some(Ty::async_destructor_combinator(tcx, dropper).instantiate(tcx, &[self.into()]))
|
||||
}
|
||||
|
||||
fn async_destructor_combinator(
|
||||
|
@ -4,8 +4,8 @@
|
||||
use crate::query::{IntoQueryParam, Providers};
|
||||
use crate::ty::layout::{FloatExt, IntegerExt};
|
||||
use crate::ty::{
|
||||
self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt, Upcast,
|
||||
self, Asyncness, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt, Upcast,
|
||||
};
|
||||
use crate::ty::{GenericArgKind, GenericArgsRef};
|
||||
use rustc_apfloat::Float as _;
|
||||
@ -382,6 +382,45 @@ pub fn calculate_dtor(
|
||||
Some(ty::Destructor { did, constness })
|
||||
}
|
||||
|
||||
/// Calculate the async destructor of a given type.
|
||||
pub fn calculate_async_dtor(
|
||||
self,
|
||||
adt_did: DefId,
|
||||
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
|
||||
) -> Option<ty::AsyncDestructor> {
|
||||
let async_drop_trait = self.lang_items().async_drop_trait()?;
|
||||
self.ensure().coherent_trait(async_drop_trait).ok()?;
|
||||
|
||||
let ty = self.type_of(adt_did).instantiate_identity();
|
||||
let mut dtor_candidate = None;
|
||||
self.for_each_relevant_impl(async_drop_trait, ty, |impl_did| {
|
||||
if validate(self, impl_did).is_err() {
|
||||
// Already `ErrorGuaranteed`, no need to delay a span bug here.
|
||||
return;
|
||||
}
|
||||
|
||||
let [future, ctor] = self.associated_item_def_ids(impl_did) else {
|
||||
self.dcx().span_delayed_bug(
|
||||
self.def_span(impl_did),
|
||||
"AsyncDrop impl without async_drop function or Dropper type",
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some((_, _, old_impl_did)) = dtor_candidate {
|
||||
self.dcx()
|
||||
.struct_span_err(self.def_span(impl_did), "multiple async drop impls found")
|
||||
.with_span_note(self.def_span(old_impl_did), "other impl here")
|
||||
.delay_as_bug();
|
||||
}
|
||||
|
||||
dtor_candidate = Some((*future, *ctor, impl_did));
|
||||
});
|
||||
|
||||
let (future, ctor, _) = dtor_candidate?;
|
||||
Some(ty::AsyncDestructor { future, ctor })
|
||||
}
|
||||
|
||||
/// Returns the set of types that are required to be alive in
|
||||
/// order to run the destructor of `def` (see RFCs 769 and
|
||||
/// 1238).
|
||||
@ -1303,72 +1342,19 @@ fn is_trivially_unpin(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` implements the `AsyncDrop`
|
||||
/// trait.
|
||||
pub fn has_surface_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
self.could_have_surface_async_drop() && tcx.has_surface_async_drop_raw(param_env.and(self))
|
||||
}
|
||||
|
||||
/// Fast path helper for testing if a type has `AsyncDrop`
|
||||
/// implementation.
|
||||
///
|
||||
/// Returning `false` means the type is known to not have `AsyncDrop`
|
||||
/// implementation. Returning `true` means nothing -- could be
|
||||
/// `AsyncDrop`, might not be.
|
||||
fn could_have_surface_async_drop(self) -> bool {
|
||||
!self.is_async_destructor_trivially_noop()
|
||||
&& !matches!(
|
||||
self.kind(),
|
||||
ty::Tuple(_)
|
||||
| ty::Slice(_)
|
||||
| ty::Array(_, _)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` implements the `Drop`
|
||||
/// trait.
|
||||
pub fn has_surface_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
self.could_have_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self))
|
||||
}
|
||||
|
||||
/// Fast path helper for testing if a type has `Drop` implementation.
|
||||
///
|
||||
/// Returning `false` means the type is known to not have `Drop`
|
||||
/// implementation. Returning `true` means nothing -- could be
|
||||
/// `Drop`, might not be.
|
||||
fn could_have_surface_drop(self) -> bool {
|
||||
!self.is_async_destructor_trivially_noop()
|
||||
&& !matches!(
|
||||
self.kind(),
|
||||
ty::Tuple(_)
|
||||
| ty::Slice(_)
|
||||
| ty::Array(_, _)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` implement has noop async destructor.
|
||||
//
|
||||
// FIXME: implement optimization to make ADTs, which do not need drop,
|
||||
// to skip fields or to have noop async destructor.
|
||||
// to skip fields or to have noop async destructor, use `needs_(async_)drop`
|
||||
pub fn is_async_destructor_noop(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> bool {
|
||||
// TODO: check on the most generic version of your type
|
||||
self.is_async_destructor_trivially_noop()
|
||||
|| if let ty::Adt(adt_def, _) = self.kind() {
|
||||
(adt_def.is_union() || adt_def.is_payloadfree())
|
||||
&& !self.has_surface_async_drop(tcx, param_env)
|
||||
&& !self.has_surface_drop(tcx, param_env)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|| self.needs_async_drop(tcx, param_env)
|
||||
|| self.needs_drop(tcx, param_env)
|
||||
}
|
||||
|
||||
/// Fast path helper for testing if a type has noop async destructor.
|
||||
@ -1391,7 +1377,34 @@ fn is_async_destructor_trivially_noop(self) -> bool {
|
||||
| ty::FnPtr(_) => true,
|
||||
ty::Tuple(tys) => tys.is_empty(),
|
||||
ty::Adt(adt_def, _) => adt_def.is_manually_drop(),
|
||||
_ => false,
|
||||
ty::Bool => todo!(),
|
||||
ty::Char => todo!(),
|
||||
ty::Int(_) => todo!(),
|
||||
ty::Uint(_) => todo!(),
|
||||
ty::Float(_) => todo!(),
|
||||
ty::Adt(_, _) => todo!(),
|
||||
ty::Foreign(_) => todo!(),
|
||||
ty::Str => todo!(),
|
||||
ty::Array(_, _) => todo!(),
|
||||
ty::Pat(_, _) => todo!(),
|
||||
ty::Slice(_) => todo!(),
|
||||
ty::RawPtr(_, _) => todo!(),
|
||||
ty::Ref(_, _, _) => todo!(),
|
||||
ty::FnDef(_, _) => todo!(),
|
||||
ty::FnPtr(_) => todo!(),
|
||||
ty::Dynamic(_, _, _) => todo!(),
|
||||
ty::Closure(_, _) => todo!(),
|
||||
ty::CoroutineClosure(_, _) => todo!(),
|
||||
ty::Coroutine(_, _) => todo!(),
|
||||
ty::CoroutineWitness(_, _) => todo!(),
|
||||
ty::Never => todo!(),
|
||||
ty::Tuple(_) => todo!(),
|
||||
ty::Alias(_, _) => todo!(),
|
||||
ty::Param(_) => todo!(),
|
||||
ty::Bound(_, _) => todo!(),
|
||||
ty::Placeholder(_) => todo!(),
|
||||
ty::Infer(_) => todo!(),
|
||||
ty::Error(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1430,6 +1443,42 @@ pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> boo
|
||||
}
|
||||
}
|
||||
|
||||
/// If `ty.needs_async_drop(...)` returns `true`, then `ty` is definitely
|
||||
/// non-copy and *might* have a async destructor attached; if it returns
|
||||
/// `false`, then `ty` definitely has no async destructor (i.e., no async
|
||||
/// drop glue).
|
||||
///
|
||||
/// (Note that this implies that if `ty` has an async destructor attached,
|
||||
/// then `needs_async_drop` will definitely return `true` for `ty`.)
|
||||
///
|
||||
/// Note that this method is used to check eligible types in unions.
|
||||
#[inline]
|
||||
pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// Avoid querying in simple cases.
|
||||
match needs_drop_components(tcx, self) {
|
||||
Err(AlwaysRequiresDrop) => true,
|
||||
Ok(components) => {
|
||||
let query_ty = match *components {
|
||||
[] => return false,
|
||||
// If we've got a single component, call the query with that
|
||||
// to increase the chance that we hit the query cache.
|
||||
[component_ty] => component_ty,
|
||||
_ => self,
|
||||
};
|
||||
|
||||
// This doesn't depend on regions, so try to minimize distinct
|
||||
// query keys used.
|
||||
// If normalization fails, we just use `query_ty`.
|
||||
debug_assert!(!param_env.has_infer());
|
||||
let query_ty = tcx
|
||||
.try_normalize_erasing_regions(param_env, query_ty)
|
||||
.unwrap_or_else(|_| tcx.erase_regions(query_ty));
|
||||
|
||||
tcx.needs_async_drop_raw(param_env.and(query_ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `ty` has a significant drop.
|
||||
///
|
||||
/// Note that this method can return false even if `ty` has a destructor
|
||||
@ -1598,12 +1647,24 @@ pub fn determine<P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> ExplicitSelf<'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(zetanumbers): make specifying asyncness explicit
|
||||
/// Returns a list of types such that the given type needs drop if and only if
|
||||
/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
|
||||
/// this type always needs drop.
|
||||
pub fn needs_drop_components<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
|
||||
needs_drop_components_with_async(tcx, ty, Asyncness::No)
|
||||
}
|
||||
|
||||
/// Returns a list of types such that the given type needs drop if and only if
|
||||
/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
|
||||
/// this type always needs drop.
|
||||
pub fn needs_drop_components_with_async<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
asyncness: Asyncness,
|
||||
) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
|
||||
match *ty.kind() {
|
||||
ty::Infer(ty::FreshIntTy(_))
|
||||
@ -1623,11 +1684,18 @@ pub fn needs_drop_components<'tcx>(
|
||||
// Foreign types can never have destructors.
|
||||
ty::Foreign(..) => Ok(SmallVec::new()),
|
||||
|
||||
ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
|
||||
// FIXME(zetanumbers): Temporary workaround for async drop of dynamic types
|
||||
ty::Dynamic(..) | ty::Error(_) => {
|
||||
if asyncness.is_async() {
|
||||
Ok(SmallVec::new())
|
||||
} else {
|
||||
Err(AlwaysRequiresDrop)
|
||||
}
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(tcx, ty),
|
||||
ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components_with_async(tcx, ty, asyncness),
|
||||
ty::Array(elem_ty, size) => {
|
||||
match needs_drop_components(tcx, elem_ty) {
|
||||
match needs_drop_components_with_async(tcx, elem_ty, asyncness) {
|
||||
Ok(v) if v.is_empty() => Ok(v),
|
||||
res => match size.try_to_target_usize(tcx) {
|
||||
// Arrays of size zero don't need drop, even if their element
|
||||
@ -1643,7 +1711,7 @@ pub fn needs_drop_components<'tcx>(
|
||||
}
|
||||
// If any field needs drop, then the whole tuple does.
|
||||
ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| {
|
||||
acc.extend(needs_drop_components(tcx, elem)?);
|
||||
acc.extend(needs_drop_components_with_async(tcx, elem, asyncness)?);
|
||||
Ok(acc)
|
||||
}),
|
||||
|
||||
|
@ -22,17 +22,6 @@ fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
|
||||
is_item_raw(tcx, query, LangItem::Unpin)
|
||||
}
|
||||
|
||||
fn has_surface_async_drop_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
) -> bool {
|
||||
is_item_raw(tcx, query, LangItem::AsyncDrop)
|
||||
}
|
||||
|
||||
fn has_surface_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
is_item_raw(tcx, query, LangItem::Drop)
|
||||
}
|
||||
|
||||
fn is_item_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||
@ -45,13 +34,5 @@ fn is_item_raw<'tcx>(
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
is_copy_raw,
|
||||
is_sized_raw,
|
||||
is_freeze_raw,
|
||||
is_unpin_raw,
|
||||
has_surface_async_drop_raw,
|
||||
has_surface_drop_raw,
|
||||
..*providers
|
||||
};
|
||||
*providers = Providers { is_copy_raw, is_sized_raw, is_freeze_raw, is_unpin_raw, ..*providers };
|
||||
}
|
||||
|
@ -30,6 +30,21 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
|
||||
res
|
||||
}
|
||||
|
||||
fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
// If we don't know a type doesn't need async drop, for example if it's a
|
||||
// type parameter without a `Copy` bound, then we conservatively return that
|
||||
// it needs async drop.
|
||||
let adt_has_async_dtor =
|
||||
|adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant);
|
||||
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
|
||||
@ -389,6 +404,7 @@ fn adt_significant_drop_tys(
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
needs_drop_raw,
|
||||
needs_async_drop_raw,
|
||||
has_significant_drop_raw,
|
||||
adt_drop_tys,
|
||||
adt_significant_drop_tys,
|
||||
|
Loading…
Reference in New Issue
Block a user