1
Fork 0

Add CoroutineClosure to TyKind, AggregateKind, UpvarArgs

This commit is contained in:
Michael Goulet 2024-01-24 18:01:56 +00:00
parent a20421734b
commit c567eddec2
91 changed files with 579 additions and 101 deletions

View file

@ -340,7 +340,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::Never
| ty::Tuple(_) => {
@ -538,6 +539,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
@ -694,6 +696,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::FnPtr(_)
| ty::Alias(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never

View file

@ -57,6 +57,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]),
ty::Coroutine(_, args) => {
let coroutine_args = args.as_coroutine();
Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
@ -128,6 +130,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
| ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => Ok(vec![]),
@ -193,6 +196,8 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
ty::CoroutineClosure(..) => Err(NoSolution),
ty::Coroutine(def_id, args) => match ecx.tcx().coroutine_movability(def_id) {
Movability::Static => Err(NoSolution),
Movability::Movable => {
@ -267,6 +272,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
}
Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
}
// Coroutine closures don't implement `Fn` traits the normal way.
ty::CoroutineClosure(..) => Err(NoSolution),
ty::Bool
| ty::Char
| ty::Int(_)

View file

@ -391,6 +391,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
@ -627,6 +628,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
| ty::Coroutine(..)
| ty::CoroutineWitness(..)

View file

@ -950,7 +950,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never

View file

@ -863,7 +863,7 @@ where
}
}
ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
ty::Closure(did, ..) | ty::Coroutine(did, ..) => {
ty::Closure(did, ..) | ty::CoroutineClosure(did, ..) | ty::Coroutine(did, ..) => {
if self.def_id_is_local(did) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else {

View file

@ -959,9 +959,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Option<ErrorGuaranteed> {
if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind()
let self_ty = trait_ref.self_ty().skip_binder();
if let ty::Closure(closure_def_id, closure_args) = *self_ty.kind()
&& let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id())
&& let Some(found_kind) = self.closure_kind(closure_args)
&& let Some(found_kind) = self.closure_kind(self_ty)
&& !found_kind.extends(expected_kind)
&& let sig = closure_args.as_closure().sig()
&& self.can_sub(
@ -1875,6 +1876,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::Coroutine(..) => Some(18),
ty::Foreign(..) => Some(19),
ty::CoroutineWitness(..) => Some(20),
ty::CoroutineClosure(..) => Some(21),
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
}
}

View file

@ -1854,6 +1854,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
@ -1903,6 +1904,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never

View file

@ -48,7 +48,11 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
// (T1..Tn) and closures have same properties as T1..Tn --
// check if *all* of them are trivial.
ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)),
ty::Closure(_, args) => trivial_dropck_outlives(tcx, args.as_closure().tupled_upvars_ty()),
ty::CoroutineClosure(_, args) => {
trivial_dropck_outlives(tcx, args.as_coroutine_closure().tupled_upvars_ty())
}
ty::Adt(def, _) => {
if Some(def.did()) == tcx.lang_items().manually_drop() {
@ -239,6 +243,22 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
Ok::<_, NoSolution>(())
})?,
ty::CoroutineClosure(_, args) => {
rustc_data_structures::stack::ensure_sufficient_stack(|| {
for ty in args.as_coroutine_closure().upvar_tys() {
dtorck_constraint_for_ty_inner(
tcx,
param_env,
span,
depth + 1,
ty,
constraints,
)?;
}
Ok::<_, NoSolution>(())
})?
}
ty::Coroutine(_, args) => {
// rust-lang/rust#49918: types can be constructed, stored
// in the interior, and sit idle when coroutine yields

View file

@ -306,11 +306,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Okay to skip binder because the args on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters
match *obligation.self_ty().skip_binder().kind() {
ty::Closure(def_id, closure_args) => {
let self_ty = obligation.self_ty().skip_binder();
match *self_ty.kind() {
ty::Closure(def_id, _) => {
let is_const = self.tcx().is_const_fn_raw(def_id);
debug!(?kind, ?obligation, "assemble_unboxed_candidates");
match self.infcx.closure_kind(closure_args) {
match self.infcx.closure_kind(self_ty) {
Some(closure_kind) => {
debug!(?closure_kind, "assemble_unboxed_candidates");
if closure_kind.extends(kind) {
@ -488,7 +489,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Slice(_)
| ty::RawPtr(_)
| ty::Ref(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
@ -623,7 +625,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::Never
| ty::Tuple(_)
@ -1000,6 +1003,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Array(..)
| ty::Slice(_)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::Tuple(_)
| ty::CoroutineWitness(..) => {
@ -1076,7 +1080,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
@ -1139,6 +1144,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never

View file

@ -2106,6 +2106,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => {
@ -2227,6 +2228,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}
// FIXME(async_closures): These are never clone, for now.
ty::CoroutineClosure(_, _) => None,
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {
// Fallback to whatever user-defined impls exist in this case.
None
@ -2305,6 +2309,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
t.rebind(vec![ty])
}
ty::CoroutineClosure(_, args) => {
let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
t.rebind(vec![ty])
}
ty::Coroutine(_, args) => {
let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
let witness = args.as_coroutine().witness();

View file

@ -79,6 +79,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
ty::Closure(..) => {
return ControlFlow::Break(ty);
}
ty::CoroutineClosure(..) => {
return ControlFlow::Break(ty);
}
ty::Coroutine(..) | ty::CoroutineWitness(..) => {
return ControlFlow::Break(ty);
}

View file

@ -727,6 +727,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.out.extend(obligations);
}
ty::CoroutineClosure(did, args) => {
// See the above comments.
walker.skip_current_subtree();
self.compute(args.as_coroutine_closure().tupled_upvars_ty().into());
let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}
ty::FnPtr(_) => {
// let the loop iterate into the argument/return
// types appearing in the fn signature