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

@ -1472,7 +1472,7 @@ fn suggest_ampmut<'tcx>(
}
fn is_closure_or_coroutine(ty: Ty<'_>) -> bool {
ty.is_closure() || ty.is_coroutine()
ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure()
}
/// Given a field that needs to be mutable, returns a span where the " mut " could go.

View File

@ -1303,7 +1303,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// moved into the closure and subsequently used by the closure,
// in order to populate our used_mut set.
match **aggregate_kind {
AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => {
AggregateKind::Closure(def_id, _)
| AggregateKind::CoroutineClosure(def_id, _)
| AggregateKind::Coroutine(def_id, _) => {
let def_id = def_id.expect_local();
let BorrowCheckResult { used_mut_upvars, .. } =
self.infcx.tcx.mir_borrowck(def_id);
@ -1609,6 +1611,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
@ -1633,7 +1636,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return;
}
}
ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (),
ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::Tuple(_) => (),
ty::Bool
| ty::Char
| ty::Int(_)

View File

@ -164,7 +164,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>(
match place_ref.last_projection() {
Some((place_base, ProjectionElem::Field(field, _ty))) => {
let base_ty = place_base.ty(body, tcx).ty;
if (base_ty.is_closure() || base_ty.is_coroutine())
if (base_ty.is_closure() || base_ty.is_coroutine() || base_ty.is_coroutine_closure())
&& (!by_ref || upvars[field.index()].is_by_ref())
{
Some(field)

View File

@ -808,6 +808,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}),
};
}
ty::CoroutineClosure(_, args) => {
return match args.as_coroutine_closure().upvar_tys().get(field.index()) {
Some(&ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: args.as_coroutine_closure().upvar_tys().len(),
}),
};
}
ty::Coroutine(_, args) => {
// Only prefix fields (upvars and current state) are
// accessible without a variant index.
@ -1875,6 +1883,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}),
}
}
AggregateKind::CoroutineClosure(_, args) => {
match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
Some(ty) => Ok(*ty),
None => Err(FieldAccessError::OutOfRange {
field_count: args.as_coroutine_closure().upvar_tys().len(),
}),
}
}
AggregateKind::Array(ty) => Ok(ty),
AggregateKind::Tuple => {
unreachable!("This should have been covered in check_rvalues");
@ -2478,6 +2494,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
AggregateKind::Tuple => None,
AggregateKind::Closure(_, _) => None,
AggregateKind::Coroutine(_, _) => None,
AggregateKind::CoroutineClosure(_, _) => None,
},
}
}
@ -2705,7 +2722,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// desugaring. A closure gets desugared to a struct, and
// these extra requirements are basically like where
// clauses on the struct.
AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => (
AggregateKind::Closure(def_id, args)
| AggregateKind::CoroutineClosure(def_id, args)
| AggregateKind::Coroutine(def_id, args) => (
def_id,
self.prove_closure_bounds(
tcx,
@ -2754,10 +2773,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
let parent_args = match tcx.def_kind(def_id) {
DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => {
args.as_coroutine().parent_args()
DefKind::Closure => {
// FIXME(async_closures): It's kind of icky to access HIR here.
match tcx.hir_node_by_def_id(def_id).expect_closure().kind {
hir::ClosureKind::Closure => args.as_closure().parent_args(),
hir::ClosureKind::Coroutine(_) => args.as_coroutine().parent_args(),
hir::ClosureKind::CoroutineClosure(_) => {
args.as_coroutine_closure().parent_args()
}
}
}
DefKind::Closure => args.as_closure().parent_args(),
DefKind::InlineConst => args.as_inline_const().parent_args(),
other => bug!("unexpected item {:?}", other),
};

View File

@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
// FIXME(eddyb) producing readable type names for trait objects can result
// in problematically distinct types due to HRTB and subtyping (see #47638).
// ty::Dynamic(..) |
ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
if !cx.sess().fewer_names() =>
{
let mut name = with_no_trimmed_paths!(layout.ty.to_string());

View File

@ -33,7 +33,7 @@ fn uncached_llvm_type<'a, 'tcx>(
// FIXME(eddyb) producing readable type names for trait objects can result
// in problematically distinct types due to HRTB and subtyping (see #47638).
// ty::Dynamic(..) |
ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
// For performance reasons we use names only when emitting LLVM IR.
if !cx.sess().fewer_names() =>
{

View File

@ -398,7 +398,9 @@ fn push_debuginfo_type_name<'tcx>(
// processing
visited.remove(&t);
}
ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
ty::Closure(def_id, args)
| ty::CoroutineClosure(def_id, args)
| ty::Coroutine(def_id, args, ..) => {
// Name will be "{closure_env#0}<T1, T2, ...>", "{coroutine_env#0}<T1, T2, ...>", or
// "{async_fn_env#0}<T1, T2, ...>", etc.
// In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
@ -768,6 +770,8 @@ fn push_closure_or_coroutine_name<'tcx>(
// Truncate the args to the length of the above generics. This will cut off
// anything closure- or coroutine-specific.
// FIXME(async_closures): This is probably not going to be correct w.r.t.
// multiple coroutine flavors. Maybe truncate to (parent + 1)?
let args = args.truncate_to(tcx, generics);
push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited);
}

View File

@ -172,6 +172,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
| ty::Infer(_)
// FIXME(oli-obk): we can probably encode closures just like structs
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType),
}
@ -301,6 +302,7 @@ pub fn valtree_to_const_value<'tcx>(
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::FnPtr(_)

View File

@ -1007,6 +1007,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
| ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Error(_) => true,

View File

@ -85,6 +85,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never

View File

@ -644,6 +644,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
| ty::Str
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..) => Ok(false),
// Some types only occur during typechecking, they have no layout.
// We should not see them here and we could not check them anyway.

View File

@ -665,6 +665,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
check_equal(self, location, f_ty);
}
ty::CoroutineClosure(_, args) => {
let args = args.as_coroutine_closure();
let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else {
fail_out_of_bounds(self, location);
return;
};
check_equal(self, location, f_ty);
}
&ty::Coroutine(def_id, args) => {
let f_ty = if let Some(var) = parent_ty.variant_index {
let gen_body = if def_id == self.body.source.def_id() {
@ -861,6 +869,20 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
}
AggregateKind::CoroutineClosure(_, args) => {
let upvars = args.as_coroutine_closure().upvar_tys();
if upvars.len() != fields.len() {
self.fail(
location,
"coroutine-closure has the wrong number of initialized fields",
);
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
self.fail(location, "coroutine-closure field has the wrong type");
}
}
}
},
Rvalue::Ref(_, BorrowKind::Fake, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {

View File

@ -51,6 +51,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::FnDef(def_id, args)
| ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
| ty::Closure(def_id, args)
| ty::CoroutineClosure(def_id, args)
| ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),

View File

@ -3703,6 +3703,7 @@ impl<'hir> Node<'hir> {
expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n;
expect_crate, &'hir Mod<'hir>, Node::Crate(n), n;
expect_infer, &'hir InferArg, Node::Infer(n), n;
expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n;
}
}

View File

@ -171,6 +171,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Bound(..)

View File

@ -244,6 +244,7 @@ fn do_orphan_check_impl<'tcx>(
| ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Bound(..)

View File

@ -349,7 +349,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
ClosureKind::Coroutine(_) => {
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
}
ClosureKind::CoroutineClosure(_) => todo!(),
ClosureKind::CoroutineClosure(_) => &[
"<closure_kind>",
"<closure_signature_parts>",
"<upvars>",
"<bound_captures_by_ref>",
"<witness>",
][..],
};
params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {

View File

@ -235,8 +235,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// leaf type -- noop
}
ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) => {
bug!("Unexpected closure type in variance computation");
ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => {
bug!("Unexpected coroutine/closure type in variance computation");
}
ty::Ref(region, ty, mutbl) => {

View File

@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check whether this is a call to a closure where we
// haven't yet decided on whether the closure is fn vs
// fnmut vs fnonce. If so, we have to defer further processing.
if self.closure_kind(args).is_none() {
if self.closure_kind(adjusted_ty).is_none() {
let closure_sig = args.as_closure().sig();
let closure_sig = self.instantiate_binder_with_fresh_vars(
call_expr.span,
@ -160,10 +160,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
DeferredCallResolution {
call_expr,
callee_expr,
adjusted_ty,
closure_ty: adjusted_ty,
adjustments,
fn_sig: closure_sig,
closure_args: args,
},
);
return Some(CallStep::DeferredClosure(def_id, closure_sig));
@ -886,10 +885,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub struct DeferredCallResolution<'tcx> {
call_expr: &'tcx hir::Expr<'tcx>,
callee_expr: &'tcx hir::Expr<'tcx>,
adjusted_ty: Ty<'tcx>,
closure_ty: Ty<'tcx>,
adjustments: Vec<Adjustment<'tcx>>,
fn_sig: ty::FnSig<'tcx>,
closure_args: GenericArgsRef<'tcx>,
}
impl<'a, 'tcx> DeferredCallResolution<'tcx> {
@ -898,10 +896,10 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
// we should not be invoked until the closure kind has been
// determined by upvar inference
assert!(fcx.closure_kind(self.closure_args).is_some());
assert!(fcx.closure_kind(self.closure_ty).is_some());
// We may now know enough to figure out fn vs fnmut etc.
match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) {
match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) {
Some((autoref, method_callee)) => {
// One problem is that when we get here, we are going
// to have a newly instantiated function signature

View File

@ -133,6 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::Adt(..)
| ty::Never

View File

@ -57,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match ty.kind() {
// Not all of these (e.g., unsafe fns) implement `FnOnce`,
// so we look for these beforehand.
// FIXME(async_closures): These don't impl `FnOnce` by default.
ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
// If it's not a simple function, look for things which implement `FnOnce`.
_ => {

View File

@ -170,9 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
// Extract the type of the closure.
let ty = self.node_ty(closure_hir_id);
let (closure_def_id, args) = match *ty.kind() {
ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)),
ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args)),
let (closure_def_id, args, infer_kind) = match *ty.kind() {
ty::Closure(def_id, args) => {
(def_id, UpvarArgs::Closure(args), self.closure_kind(ty).is_none())
}
ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args), false),
ty::Error(_) => {
// #51714: skip analysis when we have already encountered type errors
return;
@ -188,12 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let closure_def_id = closure_def_id.expect_local();
let infer_kind = if let UpvarArgs::Closure(closure_args) = args {
self.closure_kind(closure_args).is_none().then_some(closure_args)
} else {
None
};
assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
let mut delegate = InferBorrowKind {
closure_def_id,
@ -308,10 +304,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let before_feature_tys = self.final_upvar_tys(closure_def_id);
if let Some(closure_args) = infer_kind {
if infer_kind {
// Unify the (as yet unbound) type variable in the closure
// args with the kind we inferred.
let closure_kind_ty = closure_args.as_closure().kind_ty();
let closure_kind_ty = match args {
UpvarArgs::Closure(args) => args.as_closure().kind_ty(),
UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().kind_ty(),
UpvarArgs::Coroutine(_) => unreachable!("coroutines don't have an inferred kind"),
};
self.demand_eqtype(
span,
Ty::from_closure_kind(self.tcx, closure_kind),

View File

@ -414,6 +414,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Bool

View File

@ -2839,7 +2839,11 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
// say, also take a look at the error code, maybe we can
// tailor to that.
_ => match terr {
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => Error0644,
TypeError::CyclicTy(ty)
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() =>
{
Error0644
}
TypeError::IntrinsicCast => Error0308,
_ => Error0308,
},
@ -2886,7 +2890,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
// say, also take a look at the error code, maybe we can
// tailor to that.
_ => match terr {
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => {
TypeError::CyclicTy(ty)
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() =>
{
ObligationCauseFailureCode::ClosureSelfref { span }
}
TypeError::IntrinsicCast => {

View File

@ -883,7 +883,10 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
GenericArgKind::Type(ty) => {
if matches!(
ty.kind(),
ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Coroutine(..)
ty::Alias(ty::Opaque, ..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
) {
// Opaque types can't be named by the user right now.
//

View File

@ -228,7 +228,10 @@ impl<T> Trait<T> for X {
#traits-as-parameters",
);
}
(ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => {
(
ty::Param(p),
ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..),
) => {
let generics = tcx.generics_of(body_owner_def_id);
if let Some(param) = generics.opt_type_param(p, tcx) {
let p_span = tcx.def_span(param.def_id);
@ -497,7 +500,7 @@ impl<T> Trait<T> for X {
}
CyclicTy(ty) => {
// Watch out for various cases of cyclic types and try to explain.
if ty.is_closure() || ty.is_coroutine() {
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
diag.note(
"closures cannot capture themselves or take themselves as argument;\n\
this error may be the result of a recent compiler bug-fix,\n\

View File

@ -1538,9 +1538,13 @@ impl<'tcx> InferCtxt<'tcx> {
/// Obtains the latest type of the given closure; this may be a
/// closure in the current function, in which case its
/// `ClosureKind` may not yet be known.
pub fn closure_kind(&self, closure_args: GenericArgsRef<'tcx>) -> Option<ty::ClosureKind> {
let closure_kind_ty = closure_args.as_closure().kind_ty();
let closure_kind_ty = self.shallow_resolve(closure_kind_ty);
pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option<ty::ClosureKind> {
let unresolved_kind_ty = match *closure_ty.kind() {
ty::Closure(_, args) => args.as_closure().kind_ty(),
ty::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
_ => bug!("unexpected type {closure_ty}"),
};
let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
closure_kind_ty.to_opt_closure_kind()
}

View File

@ -456,6 +456,17 @@ where
args.as_closure().sig_as_fn_ptr_ty().visit_with(self);
}
ty::CoroutineClosure(_, args) => {
// Skip lifetime parameters of the enclosing item(s)
for upvar in args.as_coroutine_closure().upvar_tys() {
upvar.visit_with(self);
}
// FIXME(async_closures): Is this the right signature to visit here?
args.as_coroutine_closure().signature_parts_ty().visit_with(self);
}
ty::Coroutine(_, args) => {
// Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions.

View File

@ -103,6 +103,11 @@ fn compute_components<'tcx>(
compute_components(tcx, tupled_ty, out, visited);
}
ty::CoroutineClosure(_, args) => {
let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty();
compute_components(tcx, tupled_ty, out, visited);
}
ty::Coroutine(_, args) => {
// Same as the closure case
let tupled_ty = args.as_coroutine().tupled_upvars_ty();

View File

@ -1435,6 +1435,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
| ty::Bound(..)
| ty::Error(_)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Placeholder(..)

View File

@ -355,7 +355,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
Some(len) => is_ty_must_use(cx, ty, expr, span)
.map(|inner| MustUsePath::Array(Box::new(inner), len)),
},
ty::Closure(..) => Some(MustUsePath::Closure(span)),
ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)),
ty::Coroutine(def_id, ..) => {
// async fn should be treated as "implementor of `Future`"
let must_use = if cx.tcx.coroutine_is_async(def_id) {

View File

@ -990,7 +990,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
})
}
AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| {
AggregateKind::Closure(def_id, args)
| AggregateKind::CoroutineClosure(def_id, args) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
let args = tcx.lift(args).unwrap();
format!("{{closure@{}}}", tcx.def_path_str_with_args(def_id, args),)

View File

@ -1350,6 +1350,7 @@ pub enum AggregateKind<'tcx> {
Closure(DefId, GenericArgsRef<'tcx>),
Coroutine(DefId, GenericArgsRef<'tcx>),
CoroutineClosure(DefId, GenericArgsRef<'tcx>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]

View File

@ -202,6 +202,9 @@ impl<'tcx> Rvalue<'tcx> {
AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args),
AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args),
AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args),
AggregateKind::CoroutineClosure(did, args) => {
Ty::new_coroutine_closure(tcx, did, args)
}
},
Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,

View File

@ -739,6 +739,12 @@ macro_rules! make_mir_visitor {
) => {
self.visit_args(coroutine_args, location);
}
AggregateKind::CoroutineClosure(
_,
coroutine_closure_args,
) => {
self.visit_args(coroutine_closure_args, location);
}
}
for operand in operands {

View File

@ -1544,6 +1544,7 @@ impl<'tcx> TyCtxt<'tcx> {
CoroutineWitness,
Dynamic,
Closure,
CoroutineClosure,
Tuple,
Bound,
Param,

View File

@ -299,7 +299,7 @@ impl<'tcx> Ty<'tcx> {
},
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(),
ty::Coroutine(def_id, ..) => {
format!("{:#}", tcx.coroutine_kind(def_id).unwrap()).into()
}

View File

@ -128,7 +128,9 @@ pub fn simplify_type<'tcx>(
_ => Some(SimplifiedType::MarkerTraitObject),
},
ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)),
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)),
ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => {
Some(SimplifiedType::Closure(def_id))
}
ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id)),
ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)),
ty::Never => Some(SimplifiedType::Never),
@ -236,6 +238,7 @@ impl DeepRejectCtxt {
| ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()),
ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Placeholder(..)
@ -312,7 +315,7 @@ impl DeepRejectCtxt {
},
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) => false,
ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false,
// Placeholder types don't unify with anything on their own
ty::Placeholder(..) | ty::Bound(..) => false,

View File

@ -136,6 +136,22 @@ impl FlagComputation {
self.add_ty(args.tupled_upvars_ty());
}
&ty::CoroutineClosure(_, args) => {
let args = args.as_coroutine_closure();
let should_remove_further_specializable =
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
self.add_args(args.parent_args());
if should_remove_further_specializable {
self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
self.add_ty(args.signature_parts_ty());
self.add_ty(args.coroutine_witness_ty());
self.add_ty(args.coroutine_captures_by_ref_ty());
self.add_ty(args.kind_ty());
self.add_ty(args.tupled_upvars_ty());
}
&ty::Bound(debruijn, _) => {
self.add_bound_var(debruijn);
self.add_flags(TypeFlags::HAS_TY_BOUND);

View File

@ -2,7 +2,7 @@
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::sty::{ClosureArgs, CoroutineArgs, InlineConstArgs};
use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs};
use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
@ -288,6 +288,14 @@ impl<'tcx> GenericArgs<'tcx> {
ClosureArgs { args: self }
}
/// Interpret these generic args as the args of a coroutine-closure type.
/// Coroutine-closure args have a particular structure controlled by the
/// compiler that encodes information like the signature and closure kind;
/// see `ty::CoroutineClosureArgs` struct for more comments.
pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<'tcx> {
CoroutineClosureArgs { args: self }
}
/// Interpret these generic args as the args of a coroutine type.
/// Coroutine args have a particular structure controlled by the
/// compiler that encodes information like the signature and coroutine kind;

View File

@ -906,6 +906,12 @@ where
i,
),
ty::CoroutineClosure(_, args) => field_ty_or_layout(
TyAndLayout { ty: args.as_coroutine_closure().tupled_upvars_ty(), ..this },
cx,
i,
),
ty::Coroutine(def_id, args) => match this.variants {
Variants::Single { index } => TyMaybeWithLayout::Ty(
args.as_coroutine()

View File

@ -259,6 +259,7 @@ fn characteristic_def_id_of_type_cached<'a>(
ty::FnDef(def_id, _)
| ty::Closure(def_id, _)
| ty::CoroutineClosure(def_id, _)
| ty::Coroutine(def_id, _)
| ty::CoroutineWitness(def_id, _)
| ty::Foreign(def_id) => Some(def_id),

View File

@ -874,6 +874,48 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
p!("}}");
}
ty::CoroutineClosure(did, args) => {
p!(write("{{"));
if !self.should_print_verbose() {
p!(write("coroutine closure"));
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
if self.tcx().sess.opts.unstable_opts.span_free_formats {
p!("@", print_def_path(did.to_def_id(), args));
} else {
let span = self.tcx().def_span(did);
let preference = if with_forced_trimmed_paths() {
FileNameDisplayPreference::Short
} else {
FileNameDisplayPreference::Remapped
};
p!(write(
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx().sess.source_map().span_to_string(span, preference)
));
}
} else {
p!(write("@"), print_def_path(did, args));
}
} else {
p!(print_def_path(did, args));
p!(
" closure_kind_ty=",
print(args.as_coroutine_closure().kind_ty()),
" signature_parts_ty=",
print(args.as_coroutine_closure().signature_parts_ty()),
" upvar_tys=",
print(args.as_coroutine_closure().tupled_upvars_ty()),
" coroutine_captures_by_ref_ty=",
print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
" coroutine_witness_ty=",
print(args.as_coroutine_closure().coroutine_witness_ty())
);
}
p!("}}");
}
ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"),
ty::Slice(ty) => p!("[", print(ty), "]"),
}

View File

@ -481,6 +481,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Ok(Ty::new_closure(tcx, a_id, args))
}
(&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args))
if a_id == b_id =>
{
let args = relate_args_invariantly(relation, a_args, b_args)?;
Ok(Ty::new_coroutine_closure(tcx, a_id, args))
}
(&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
Ok(Ty::new_ptr(tcx, mt))

View File

@ -584,6 +584,9 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
ty::CoroutineWitness(did, args.try_fold_with(folder)?)
}
ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?),
ty::CoroutineClosure(did, args) => {
ty::CoroutineClosure(did, args.try_fold_with(folder)?)
}
ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
ty::Bool
@ -632,6 +635,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
ty::Coroutine(_did, ref args) => args.visit_with(visitor),
ty::CoroutineWitness(_did, ref args) => args.visit_with(visitor),
ty::Closure(_did, ref args) => args.visit_with(visitor),
ty::CoroutineClosure(_did, ref args) => args.visit_with(visitor),
ty::Alias(_, ref data) => data.visit_with(visitor),
ty::Bool

View File

@ -269,6 +269,97 @@ impl<'tcx> ClosureArgs<'tcx> {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
pub struct CoroutineClosureArgs<'tcx> {
pub args: GenericArgsRef<'tcx>,
}
pub struct CoroutineClosureArgsParts<'tcx> {
pub parent_args: &'tcx [GenericArg<'tcx>],
pub closure_kind_ty: Ty<'tcx>,
pub signature_parts_ty: Ty<'tcx>,
pub tupled_upvars_ty: Ty<'tcx>,
pub coroutine_captures_by_ref_ty: Ty<'tcx>,
pub coroutine_witness_ty: Ty<'tcx>,
}
impl<'tcx> CoroutineClosureArgs<'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
parts: CoroutineClosureArgsParts<'tcx>,
) -> CoroutineClosureArgs<'tcx> {
CoroutineClosureArgs {
args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
parts.closure_kind_ty.into(),
parts.signature_parts_ty.into(),
parts.tupled_upvars_ty.into(),
parts.coroutine_captures_by_ref_ty.into(),
parts.coroutine_witness_ty.into(),
])),
}
}
fn split(self) -> CoroutineClosureArgsParts<'tcx> {
match self.args[..] {
[
ref parent_args @ ..,
closure_kind_ty,
signature_parts_ty,
tupled_upvars_ty,
coroutine_captures_by_ref_ty,
coroutine_witness_ty,
] => CoroutineClosureArgsParts {
parent_args,
closure_kind_ty: closure_kind_ty.expect_ty(),
signature_parts_ty: signature_parts_ty.expect_ty(),
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
},
_ => bug!("closure args missing synthetics"),
}
}
pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
self.split().parent_args
}
#[inline]
pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
match self.tupled_upvars_ty().kind() {
TyKind::Error(_) => ty::List::empty(),
TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
}
}
#[inline]
pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
self.split().tupled_upvars_ty
}
pub fn kind_ty(self) -> Ty<'tcx> {
self.split().closure_kind_ty
}
pub fn kind(self) -> ty::ClosureKind {
self.kind_ty().to_opt_closure_kind().unwrap()
}
pub fn signature_parts_ty(self) -> Ty<'tcx> {
self.split().signature_parts_ty
}
pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> {
self.split().coroutine_captures_by_ref_ty
}
pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
self.split().coroutine_witness_ty
}
}
/// Similar to `ClosureArgs`; see the above documentation for more.
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
pub struct CoroutineArgs<'tcx> {
@ -479,6 +570,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
pub enum UpvarArgs<'tcx> {
Closure(GenericArgsRef<'tcx>),
Coroutine(GenericArgsRef<'tcx>),
CoroutineClosure(GenericArgsRef<'tcx>),
}
impl<'tcx> UpvarArgs<'tcx> {
@ -490,6 +582,7 @@ impl<'tcx> UpvarArgs<'tcx> {
let tupled_tys = match self {
UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(),
};
match tupled_tys.kind() {
@ -505,6 +598,7 @@ impl<'tcx> UpvarArgs<'tcx> {
match self {
UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(),
}
}
}
@ -1393,6 +1487,20 @@ impl<'tcx> Ty<'tcx> {
Ty::new(tcx, Closure(def_id, closure_args))
}
#[inline]
pub fn new_coroutine_closure(
tcx: TyCtxt<'tcx>,
def_id: DefId,
closure_args: GenericArgsRef<'tcx>,
) -> Ty<'tcx> {
debug_assert_eq!(
closure_args.len(),
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
"closure constructed with incorrect substitutions"
);
Ty::new(tcx, CoroutineClosure(def_id, closure_args))
}
#[inline]
pub fn new_coroutine(
tcx: TyCtxt<'tcx>,
@ -1795,7 +1903,7 @@ impl<'tcx> Ty<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Closure(_, _) = t.kind() {
if let ty::Closure(..) = t.kind() {
ControlFlow::Break(())
} else {
t.super_visit_with(self)
@ -1942,6 +2050,7 @@ impl<'tcx> Ty<'tcx> {
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Tuple(_)
@ -1980,6 +2089,7 @@ impl<'tcx> Ty<'tcx> {
| ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Error(_)
// Extern types have metadata = ().
@ -2077,6 +2187,7 @@ impl<'tcx> Ty<'tcx> {
| ty::CoroutineWitness(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Error(_) => true,
@ -2140,7 +2251,7 @@ impl<'tcx> Ty<'tcx> {
ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
ty::Adt(..) | ty::Closure(..) => false,
ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false,
// Needs normalization or revealing to determine, so no is the safe answer.
ty::Alias(..) => false,
@ -2212,6 +2323,7 @@ impl<'tcx> Ty<'tcx> {
| FnPtr(_)
| Dynamic(_, _, _)
| Closure(_, _)
| CoroutineClosure(_, _)
| Coroutine(_, _)
| CoroutineWitness(..)
| Never

View File

@ -1119,6 +1119,7 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(..)
| ty::Bound(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Dynamic(..)
| ty::Foreign(_)
| ty::Coroutine(..)
@ -1158,6 +1159,7 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(..)
| ty::Bound(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Dynamic(..)
| ty::Foreign(_)
| ty::Coroutine(..)
@ -1280,7 +1282,11 @@ impl<'tcx> Ty<'tcx> {
// Conservatively return `false` for all others...
// Anonymous function types
ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Coroutine(..) => false,
ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Dynamic(..)
| ty::Coroutine(..) => false,
// Generic or inferred types
//
@ -1424,6 +1430,7 @@ pub fn needs_drop_components<'tcx>(
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Ok(smallvec![ty]),
}
@ -1456,7 +1463,11 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
// Not trivial because they have components, and instead of looking inside,
// we'll just perform trait selection.
ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Adt(..) => false,
ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Adt(..) => false,
ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),

View File

@ -189,6 +189,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
}
ty::Adt(_, args)
| ty::Closure(_, args)
| ty::CoroutineClosure(_, args)
| ty::Coroutine(_, args)
| ty::CoroutineWitness(_, args)
| ty::FnDef(_, args) => {

View File

@ -483,6 +483,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
UpvarArgs::Closure(args) => {
Box::new(AggregateKind::Closure(closure_id.to_def_id(), args))
}
UpvarArgs::CoroutineClosure(args) => {
Box::new(AggregateKind::CoroutineClosure(closure_id.to_def_id(), args))
}
};
block.and(Rvalue::Aggregate(result, operands))
}

View File

@ -495,7 +495,7 @@ fn construct_fn<'tcx>(
args.as_coroutine().yield_ty(),
args.as_coroutine().resume_ty(),
))),
ty::Closure(..) | ty::FnDef(..) => None,
ty::Closure(..) | ty::CoroutineClosure(..) | ty::FnDef(..) => None,
ty => span_bug!(span_with_body, "unexpected type of body: {ty:?}"),
};

View File

@ -861,6 +861,9 @@ where
let ty = self.place_ty(self.place);
match ty.kind() {
ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()),
ty::CoroutineClosure(_, args) => {
self.open_drop_for_tuple(args.as_coroutine_closure().upvar_tys())
}
// Note that `elaborate_drops` only drops the upvars of a coroutine,
// and this is ok because `open_drop` here can only be reached
// within that own coroutine's resume function.

View File

@ -154,7 +154,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never
@ -177,7 +178,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
union_path.get_or_insert(base);
}
}
ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (),
ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::Tuple(_) => (),
ty::Bool
| ty::Char
| ty::Int(_)

View File

@ -39,6 +39,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => Abi::RustCall,
ty::CoroutineClosure(..) => Abi::RustCall,
ty::Coroutine(..) => Abi::Rust,
_ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
};

View File

@ -128,7 +128,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
),
}
}
&AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _) => {
&AggregateKind::Closure(def_id, _)
| &AggregateKind::CoroutineClosure(def_id, _)
| &AggregateKind::Coroutine(def_id, _) => {
let def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.mir_unsafety_check_result(def_id);

View File

@ -696,6 +696,7 @@ fn try_write_constant<'tcx>(
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"),

View File

@ -57,6 +57,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => Abi::RustCall,
ty::CoroutineClosure(..) => Abi::RustCall,
ty::Coroutine(..) => Abi::Rust,
_ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty),
};

View File

@ -861,9 +861,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let tcx = self.tcx;
if fields.is_empty() {
let is_zst = match *kind {
AggregateKind::Array(..) | AggregateKind::Tuple | AggregateKind::Closure(..) => {
true
}
AggregateKind::Array(..)
| AggregateKind::Tuple
| AggregateKind::Closure(..)
| AggregateKind::CoroutineClosure(..) => true,
// Only enums can be non-ZST.
AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum,
// Coroutines are never ZST, as they at least contain the implicit states.
@ -885,7 +886,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
assert!(!fields.is_empty());
(AggregateTy::Tuple, FIRST_VARIANT)
}
AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs) => {
AggregateKind::Closure(did, substs)
| AggregateKind::CoroutineClosure(did, substs)
| AggregateKind::Coroutine(did, substs) => {
(AggregateTy::Def(did, substs), FIRST_VARIANT)
}
AggregateKind::Adt(did, variant_index, substs, _, None) => {

View File

@ -46,6 +46,7 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
ty::Adt(..)
| ty::Array(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Tuple(..)
| ty::Alias(ty::Opaque, ..) => true,
// definitely ZST

View File

@ -332,7 +332,8 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::CoroutineWitness(..)
| ty::Never

View File

@ -719,6 +719,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
ty::ClosureKind::FnMut => {}
ty::ClosureKind::FnOnce => return succ,
},
ty::CoroutineClosure(_def_id, args) => match args.as_coroutine_closure().kind() {
ty::ClosureKind::Fn => {}
ty::ClosureKind::FnMut => {}
ty::ClosureKind::FnOnce => return succ,
},
ty::Coroutine(..) => return succ,
_ => {
span_bug!(

View File

@ -423,7 +423,8 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)
| ty::Alias(_, _)
| ty::Param(_)

View File

@ -182,6 +182,7 @@ where
| ty::Foreign(def_id)
| ty::FnDef(def_id, ..)
| ty::Closure(def_id, ..)
| ty::CoroutineClosure(def_id, ..)
| ty::Coroutine(def_id, ..) => {
self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
if V::SHALLOW {

View File

@ -538,6 +538,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
tables.tcx.coroutine_movability(*def_id).stable(tables),
)
}
mir::AggregateKind::CoroutineClosure(..) => {
todo!("FIXME(async_closure): Lower these to SMIR")
}
}
}
}

View File

@ -383,6 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
tables.closure_def(*def_id),
generic_args.stable(tables),
)),
ty::CoroutineClosure(..) => todo!("/* TODO */"),
ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine(
tables.coroutine_def(*def_id),
generic_args.stable(tables),

View File

@ -211,6 +211,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
ty::FnDef(def_id, args)
| ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
| ty::Closure(def_id, args)
| ty::CoroutineClosure(def_id, args)
| ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
// The `pretty_print_type` formatting of array size depends on
@ -281,7 +282,11 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
// Similar to `pretty_path_qualified`, but for the other
// types that are printed as paths (see `print_type` above).
match self_ty.kind() {
ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Coroutine(..)
ty::FnDef(..)
| ty::Alias(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
if trait_ref.is_none() =>
{
self.print_type(self_ty)

View File

@ -628,7 +628,9 @@ fn encode_ty<'tcx>(
}
// Function types
ty::FnDef(def_id, args) | ty::Closure(def_id, args) => {
ty::FnDef(def_id, args)
| ty::Closure(def_id, args)
| ty::CoroutineClosure(def_id, args) => {
// u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
// as vendor extended type.
let mut s = String::new();
@ -895,6 +897,10 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options));
}
ty::CoroutineClosure(def_id, args) => {
ty = Ty::new_coroutine_closure(tcx, *def_id, transform_args(tcx, args, options));
}
ty::Coroutine(def_id, args) => {
ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options));
}

View File

@ -386,6 +386,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
| ty::FnDef(def_id, args)
| ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
| ty::Closure(def_id, args)
| ty::CoroutineClosure(def_id, args)
| ty::Coroutine(def_id, args) => {
self.print_def_path(def_id, args)?;
}

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

View File

@ -215,6 +215,7 @@ fn resolve_associated_item<'tcx>(
ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Tuple(..) => {}
_ => return Ok(None),
};

View File

@ -328,6 +328,17 @@ fn layout_of_uncached<'tcx>(
)?
}
ty::CoroutineClosure(_, args) => {
let tys = args.as_coroutine_closure().upvar_tys();
univariant(
&tys.iter()
.map(|ty| Ok(cx.layout_of(ty)?.layout))
.try_collect::<IndexVec<_, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized,
)?
}
ty::Tuple(tys) => {
let kind =
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };

View File

@ -172,6 +172,12 @@ where
}
}
ty::CoroutineClosure(_, args) => {
for upvar in args.as_coroutine_closure().upvar_tys() {
queue_type(self, upvar);
}
}
// Check for a `Drop` impl and whether this is a union or
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
// impl then check whether the field types need `Drop`.

View File

@ -18,7 +18,9 @@ fn sized_constraint_for_ty<'tcx>(
let result = match ty.kind() {
Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
| FnPtr(_) | Array(..) | Closure(..) | Coroutine(..) | Never => vec![],
| FnPtr(_) | Array(..) | Closure(..) | CoroutineClosure(..) | Coroutine(..) | Never => {
vec![]
}
Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | CoroutineWitness(..) => {
// these are never sized - return the target type

View File

@ -202,6 +202,9 @@ pub enum TyKind<I: Interner> {
/// `ClosureArgs` for more details.
Closure(I::DefId, I::GenericArgs),
/// TODO
CoroutineClosure(I::DefId, I::GenericArgs),
/// The anonymous type of a coroutine. Used to represent the type of
/// `|a| yield a`.
///
@ -317,16 +320,17 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
FnPtr(_) => 13,
Dynamic(..) => 14,
Closure(_, _) => 15,
Coroutine(_, _) => 16,
CoroutineWitness(_, _) => 17,
Never => 18,
Tuple(_) => 19,
Alias(_, _) => 20,
Param(_) => 21,
Bound(_, _) => 22,
Placeholder(_) => 23,
Infer(_) => 24,
Error(_) => 25,
CoroutineClosure(_, _) => 16,
Coroutine(_, _) => 17,
CoroutineWitness(_, _) => 18,
Never => 19,
Tuple(_) => 20,
Alias(_, _) => 21,
Param(_) => 22,
Bound(_, _) => 23,
Placeholder(_) => 24,
Infer(_) => 25,
Error(_) => 26,
}
}
@ -356,6 +360,7 @@ impl<I: Interner> PartialEq for TyKind<I> {
a_p == b_p && a_r == b_r && a_repr == b_repr
}
(Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
(CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s,
(Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s,
(CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
(Tuple(a_t), Tuple(b_t)) => a_t == b_t,
@ -430,6 +435,9 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
}
},
Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
CoroutineClosure(d, s) => {
f.debug_tuple("CoroutineClosure").field(d).field(&this.wrap(s)).finish()
}
Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).finish(),
CoroutineWitness(d, s) => {
f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish()

View File

@ -2286,6 +2286,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
ty::Closure(..) => panic!("Closure"),
ty::CoroutineClosure(..) => panic!("CoroutineClosure"),
ty::Coroutine(..) => panic!("Coroutine"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::CoroutineWitness(..) => panic!("CoroutineWitness"),

View File

@ -503,6 +503,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
ty::Alias(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Dynamic(..)

View File

@ -881,6 +881,7 @@ impl TyCoercionStability {
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(ty::Projection, _) => Self::Deref,

View File

@ -490,6 +490,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
format!("ClosureKind::Coroutine(CoroutineKind::Coroutine(Movability::{movability:?})")
},
},
ClosureKind::CoroutineClosure(desugaring) => format!(
"ClosureKind::CoroutineClosure(CoroutineDesugaring::{desugaring:?})"
),
};
let ret_ty = match fn_decl.output {

View File

@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind
{
// report your lint here
}
if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::Closure, .. } = expr.kind
if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::CoroutineClosure(CoroutineDesugaring::Async), .. } = expr.kind
&& let FnRetTy::DefaultReturn(_) = fn_decl.output
&& expr1 = &cx.tcx.hir().body(body_id).value
&& let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind
&& let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
&& expr2 = &cx.tcx.hir().body(body_id1).value
&& let ExprKind::Block(block, None) = expr2.kind

View File

@ -29,6 +29,7 @@ fn main() {
TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::CoroutineClosure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Coroutine(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::CoroutineWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`

View File

@ -109,71 +109,77 @@ LL | TyKind::Closure(..) => (),
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:32:9
|
LL | TyKind::Coroutine(..) => (),
LL | TyKind::CoroutineClosure(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:33:9
|
LL | TyKind::CoroutineWitness(..) => (),
LL | TyKind::Coroutine(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:34:9
|
LL | TyKind::Never => (),
LL | TyKind::CoroutineWitness(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:35:9
|
LL | TyKind::Tuple(..) => (),
LL | TyKind::Never => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:36:9
|
LL | TyKind::Alias(..) => (),
LL | TyKind::Tuple(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:37:9
|
LL | TyKind::Param(..) => (),
LL | TyKind::Alias(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:38:9
|
LL | TyKind::Bound(..) => (),
LL | TyKind::Param(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:39:9
|
LL | TyKind::Placeholder(..) => (),
LL | TyKind::Bound(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:40:9
|
LL | TyKind::Infer(..) => (),
LL | TyKind::Placeholder(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:41:9
|
LL | TyKind::Infer(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:42:9
|
LL | TyKind::Error(_) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:46:12
--> $DIR/ty_tykind_usage.rs:47:12
|
LL | if let TyKind::Int(int_ty) = kind {}
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:48:24
--> $DIR/ty_tykind_usage.rs:49:24
|
LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
| ^^^^^^^^^^
@ -181,7 +187,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
= help: try using `Ty` instead
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:50:37
--> $DIR/ty_tykind_usage.rs:51:37
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@ -189,7 +195,7 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind`
--> $DIR/ty_tykind_usage.rs:50:53
--> $DIR/ty_tykind_usage.rs:51:53
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@ -197,12 +203,12 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:53:9
--> $DIR/ty_tykind_usage.rs:54:9
|
LL | IrTyKind::Bool
| --------^^^^^^
| |
| help: try using `ty::<kind>` directly: `ty`
error: aborting due to 32 previous errors
error: aborting due to 33 previous errors