Add simple async drop glue generation
Explainer: https://zetanumbers.github.io/book/async-drop-design.html https://github.com/rust-lang/rust/pull/121801
This commit is contained in:
parent
1dea922ea6
commit
24a24ec6ba
40 changed files with 1921 additions and 20 deletions
|
@ -240,6 +240,11 @@ pub(super) trait GoalKind<'tcx>:
|
|||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
@ -520,6 +525,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
G::consider_builtin_coroutine_candidate(self, goal)
|
||||
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_discriminant_kind_candidate(self, goal)
|
||||
} else if lang_items.async_destruct_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_async_destruct_candidate(self, goal)
|
||||
} else if lang_items.destruct_trait() == Some(trait_def_id) {
|
||||
G::consider_builtin_destruct_candidate(self, goal)
|
||||
} else if lang_items.transmute_trait() == Some(trait_def_id) {
|
||||
|
|
|
@ -814,6 +814,59 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
let discriminant_ty = match *self_ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(..)
|
||||
| ty::Uint(..)
|
||||
| ty::Float(..)
|
||||
| ty::Array(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Never
|
||||
| ty::Adt(_, _)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
| ty::Dynamic(_, _, _)
|
||||
| ty::Tuple(_)
|
||||
| ty::Error(_) => self_ty.async_destructor_ty(ecx.tcx(), goal.param_env),
|
||||
|
||||
// We do not call `Ty::discriminant_ty` on alias, param, or placeholder
|
||||
// types, which return `<self_ty as DiscriminantKind>::Discriminant`
|
||||
// (or ICE in the case of placeholders). Projecting a type to itself
|
||||
// is never really productive.
|
||||
ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
|
||||
| ty::Foreign(..)
|
||||
| ty::Bound(..) => bug!(
|
||||
"unexpected self ty `{:?}` when normalizing `<T as AsyncDestruct>::AsyncDestructor`",
|
||||
goal.predicate.self_ty()
|
||||
),
|
||||
};
|
||||
|
||||
ecx.probe_misc_candidate("builtin async destruct").enter(|ecx| {
|
||||
ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())
|
||||
.expect("expected goal term to be fully unconstrained");
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
_ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
|
|
@ -544,6 +544,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
|||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
fn consider_builtin_async_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// `AsyncDestruct` is automatically implemented for every type.
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
fn consider_builtin_destruct_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
|
|
|
@ -1074,6 +1074,42 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
| ty::Infer(..)
|
||||
| ty::Error(_) => false,
|
||||
}
|
||||
} else if lang_items.async_destruct_trait() == Some(trait_ref.def_id) {
|
||||
match self_ty.kind() {
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Adt(..)
|
||||
| ty::Str
|
||||
| ty::Array(..)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Pat(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(..)
|
||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
||||
|
||||
// type parameters, opaques, and unnormalized projections don't have
|
||||
// a known discriminant and may need to be normalized further or rely
|
||||
// on param env for async destructor projections
|
||||
ty::Param(_)
|
||||
| ty::Foreign(_)
|
||||
| ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(..)
|
||||
| ty::Error(_) => false,
|
||||
}
|
||||
} else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
|
||||
let tail = selcx.tcx().struct_tail_with_normalize(
|
||||
self_ty,
|
||||
|
@ -1488,15 +1524,20 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
|
|||
) -> Progress<'tcx> {
|
||||
let tcx = selcx.tcx();
|
||||
let self_ty = obligation.predicate.self_ty();
|
||||
let args = tcx.mk_args(&[self_ty.into()]);
|
||||
let lang_items = tcx.lang_items();
|
||||
let item_def_id = obligation.predicate.def_id;
|
||||
let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
|
||||
let args = tcx.mk_args(&[self_ty.into()]);
|
||||
let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
|
||||
let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
|
||||
assert_eq!(discriminant_def_id, item_def_id);
|
||||
|
||||
(self_ty.discriminant_ty(tcx).into(), Vec::new())
|
||||
} else if lang_items.async_destruct_trait() == Some(trait_def_id) {
|
||||
let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0];
|
||||
assert_eq!(destructor_def_id, item_def_id);
|
||||
|
||||
(self_ty.async_destructor_ty(tcx, obligation.param_env).into(), Vec::new())
|
||||
} else if lang_items.pointee_trait() == Some(trait_def_id) {
|
||||
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
|
||||
assert_eq!(metadata_def_id, item_def_id);
|
||||
|
|
|
@ -81,6 +81,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
} else if lang_items.discriminant_kind_trait() == Some(def_id) {
|
||||
// `DiscriminantKind` is automatically implemented for every type.
|
||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||
} else if lang_items.async_destruct_trait() == Some(def_id) {
|
||||
// `AsyncDestruct` is automatically implemented for every type.
|
||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||
} else if lang_items.pointee_trait() == Some(def_id) {
|
||||
// `Pointee` is automatically implemented for every type.
|
||||
candidates.vec.push(BuiltinCandidate { has_nested: false });
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue