Skip to content

Commit 21906bd

Browse files
Add CoroutineClosure to TyKind, AggregateKind, UpvarArgs
1 parent c05f4b5 commit 21906bd

File tree

91 files changed

+579
-101
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+579
-101
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1472,7 +1472,7 @@ fn suggest_ampmut<'tcx>(
14721472
}
14731473

14741474
fn is_closure_or_coroutine(ty: Ty<'_>) -> bool {
1475-
ty.is_closure() || ty.is_coroutine()
1475+
ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure()
14761476
}
14771477

14781478
/// Given a field that needs to be mutable, returns a span where the " mut " could go.

compiler/rustc_borrowck/src/lib.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13071307
// moved into the closure and subsequently used by the closure,
13081308
// in order to populate our used_mut set.
13091309
match **aggregate_kind {
1310-
AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => {
1310+
AggregateKind::Closure(def_id, _)
1311+
| AggregateKind::CoroutineClosure(def_id, _)
1312+
| AggregateKind::Coroutine(def_id, _) => {
13111313
let def_id = def_id.expect_local();
13121314
let BorrowCheckResult { used_mut_upvars, .. } =
13131315
self.infcx.tcx.mir_borrowck(def_id);
@@ -1613,6 +1615,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16131615
| ty::FnPtr(_)
16141616
| ty::Dynamic(_, _, _)
16151617
| ty::Closure(_, _)
1618+
| ty::CoroutineClosure(_, _)
16161619
| ty::Coroutine(_, _)
16171620
| ty::CoroutineWitness(..)
16181621
| ty::Never
@@ -1637,7 +1640,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16371640
return;
16381641
}
16391642
}
1640-
ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (),
1643+
ty::Closure(..)
1644+
| ty::CoroutineClosure(..)
1645+
| ty::Coroutine(_, _)
1646+
| ty::Tuple(_) => (),
16411647
ty::Bool
16421648
| ty::Char
16431649
| ty::Int(_)

compiler/rustc_borrowck/src/path_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>(
164164
match place_ref.last_projection() {
165165
Some((place_base, ProjectionElem::Field(field, _ty))) => {
166166
let base_ty = place_base.ty(body, tcx).ty;
167-
if (base_ty.is_closure() || base_ty.is_coroutine())
167+
if (base_ty.is_closure() || base_ty.is_coroutine() || base_ty.is_coroutine_closure())
168168
&& (!by_ref || upvars[field.index()].is_by_ref())
169169
{
170170
Some(field)

compiler/rustc_borrowck/src/type_check/mod.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
802802
}),
803803
};
804804
}
805+
ty::CoroutineClosure(_, args) => {
806+
return match args.as_coroutine_closure().upvar_tys().get(field.index()) {
807+
Some(&ty) => Ok(ty),
808+
None => Err(FieldAccessError::OutOfRange {
809+
field_count: args.as_coroutine_closure().upvar_tys().len(),
810+
}),
811+
};
812+
}
805813
ty::Coroutine(_, args) => {
806814
// Only prefix fields (upvars and current state) are
807815
// accessible without a variant index.
@@ -1829,6 +1837,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18291837
}),
18301838
}
18311839
}
1840+
AggregateKind::CoroutineClosure(_, args) => {
1841+
match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
1842+
Some(ty) => Ok(*ty),
1843+
None => Err(FieldAccessError::OutOfRange {
1844+
field_count: args.as_coroutine_closure().upvar_tys().len(),
1845+
}),
1846+
}
1847+
}
18321848
AggregateKind::Array(ty) => Ok(ty),
18331849
AggregateKind::Tuple => {
18341850
unreachable!("This should have been covered in check_rvalues");
@@ -2427,6 +2443,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24272443
AggregateKind::Tuple => None,
24282444
AggregateKind::Closure(_, _) => None,
24292445
AggregateKind::Coroutine(_, _) => None,
2446+
AggregateKind::CoroutineClosure(_, _) => None,
24302447
},
24312448
}
24322449
}
@@ -2654,7 +2671,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
26542671
// desugaring. A closure gets desugared to a struct, and
26552672
// these extra requirements are basically like where
26562673
// clauses on the struct.
2657-
AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => {
2674+
AggregateKind::Closure(def_id, args)
2675+
| AggregateKind::CoroutineClosure(def_id, args)
2676+
| AggregateKind::Coroutine(def_id, args) => {
26582677
(def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location))
26592678
}
26602679

@@ -2697,10 +2716,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
26972716
let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
26982717

26992718
let parent_args = match tcx.def_kind(def_id) {
2700-
DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => {
2701-
args.as_coroutine().parent_args()
2719+
DefKind::Closure => {
2720+
// FIXME(async_closures): It's kind of icky to access HIR here.
2721+
match tcx.hir_node_by_def_id(def_id).expect_closure().kind {
2722+
hir::ClosureKind::Closure => args.as_closure().parent_args(),
2723+
hir::ClosureKind::Coroutine(_) => args.as_coroutine().parent_args(),
2724+
hir::ClosureKind::CoroutineClosure(_) => {
2725+
args.as_coroutine_closure().parent_args()
2726+
}
2727+
}
27022728
}
2703-
DefKind::Closure => args.as_closure().parent_args(),
27042729
DefKind::InlineConst => args.as_inline_const().parent_args(),
27052730
other => bug!("unexpected item {:?}", other),
27062731
};

compiler/rustc_codegen_gcc/src/type_of.rs

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

compiler/rustc_codegen_llvm/src/type_of.rs

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

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,9 @@ fn push_debuginfo_type_name<'tcx>(
398398
// processing
399399
visited.remove(&t);
400400
}
401-
ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => {
401+
ty::Closure(def_id, args)
402+
| ty::CoroutineClosure(def_id, args)
403+
| ty::Coroutine(def_id, args, ..) => {
402404
// Name will be "{closure_env#0}<T1, T2, ...>", "{coroutine_env#0}<T1, T2, ...>", or
403405
// "{async_fn_env#0}<T1, T2, ...>", etc.
404406
// 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>(
768770

769771
// Truncate the args to the length of the above generics. This will cut off
770772
// anything closure- or coroutine-specific.
773+
// FIXME(async_closures): This is probably not going to be correct w.r.t.
774+
// multiple coroutine flavors. Maybe truncate to (parent + 1)?
771775
let args = args.truncate_to(tcx, generics);
772776
push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited);
773777
}

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
172172
| ty::Infer(_)
173173
// FIXME(oli-obk): we can probably encode closures just like structs
174174
| ty::Closure(..)
175+
| ty::CoroutineClosure(..)
175176
| ty::Coroutine(..)
176177
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType),
177178
}
@@ -301,6 +302,7 @@ pub fn valtree_to_const_value<'tcx>(
301302
| ty::Placeholder(..)
302303
| ty::Infer(_)
303304
| ty::Closure(..)
305+
| ty::CoroutineClosure(..)
304306
| ty::Coroutine(..)
305307
| ty::CoroutineWitness(..)
306308
| ty::FnPtr(_)

compiler/rustc_const_eval/src/interpret/eval_context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10071007
| ty::CoroutineWitness(..)
10081008
| ty::Array(..)
10091009
| ty::Closure(..)
1010+
| ty::CoroutineClosure(..)
10101011
| ty::Never
10111012
| ty::Error(_) => true,
10121013

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
8585
| ty::FnPtr(_)
8686
| ty::Dynamic(_, _, _)
8787
| ty::Closure(_, _)
88+
| ty::CoroutineClosure(_, _)
8889
| ty::Coroutine(_, _)
8990
| ty::CoroutineWitness(..)
9091
| ty::Never

compiler/rustc_const_eval/src/interpret/validity.rs

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

compiler/rustc_const_eval/src/transform/validate.rs

+22
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
665665
};
666666
check_equal(self, location, f_ty);
667667
}
668+
ty::CoroutineClosure(_, args) => {
669+
let args = args.as_coroutine_closure();
670+
let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else {
671+
fail_out_of_bounds(self, location);
672+
return;
673+
};
674+
check_equal(self, location, f_ty);
675+
}
668676
&ty::Coroutine(def_id, args) => {
669677
let f_ty = if let Some(var) = parent_ty.variant_index {
670678
let gen_body = if def_id == self.body.source.def_id() {
@@ -856,6 +864,20 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
856864
}
857865
}
858866
}
867+
AggregateKind::CoroutineClosure(_, args) => {
868+
let upvars = args.as_coroutine_closure().upvar_tys();
869+
if upvars.len() != fields.len() {
870+
self.fail(
871+
location,
872+
"coroutine-closure has the wrong number of initialized fields",
873+
);
874+
}
875+
for (src, dest) in std::iter::zip(fields, upvars) {
876+
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
877+
self.fail(location, "coroutine-closure field has the wrong type");
878+
}
879+
}
880+
}
859881
},
860882
Rvalue::Ref(_, BorrowKind::Fake, _) => {
861883
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {

compiler/rustc_const_eval/src/util/type_name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
5151
| ty::FnDef(def_id, args)
5252
| ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
5353
| ty::Closure(def_id, args)
54+
| ty::CoroutineClosure(def_id, args)
5455
| ty::Coroutine(def_id, args) => self.print_def_path(def_id, args),
5556
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
5657

compiler/rustc_hir/src/hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3713,6 +3713,7 @@ impl<'hir> Node<'hir> {
37133713
expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n;
37143714
expect_crate, &'hir Mod<'hir>, Node::Crate(n), n;
37153715
expect_infer, &'hir InferArg, Node::Infer(n), n;
3716+
expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n;
37163717
}
37173718
}
37183719

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ impl<'tcx> InherentCollect<'tcx> {
171171
}
172172
ty::FnDef(..)
173173
| ty::Closure(..)
174+
| ty::CoroutineClosure(..)
174175
| ty::Coroutine(..)
175176
| ty::CoroutineWitness(..)
176177
| ty::Bound(..)

compiler/rustc_hir_analysis/src/coherence/orphan.rs

+1
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ fn do_orphan_check_impl<'tcx>(
244244
| ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
245245

246246
ty::Closure(..)
247+
| ty::CoroutineClosure(..)
247248
| ty::Coroutine(..)
248249
| ty::CoroutineWitness(..)
249250
| ty::Bound(..)

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
349349
ClosureKind::Coroutine(_) => {
350350
&["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
351351
}
352-
ClosureKind::CoroutineClosure(_) => todo!(),
352+
ClosureKind::CoroutineClosure(_) => &[
353+
"<closure_kind>",
354+
"<closure_signature_parts>",
355+
"<upvars>",
356+
"<bound_captures_by_ref>",
357+
"<witness>",
358+
][..],
353359
};
354360

355361
params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {

compiler/rustc_hir_analysis/src/variance/constraints.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
235235
// leaf type -- noop
236236
}
237237

238-
ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) => {
239-
bug!("Unexpected closure type in variance computation");
238+
ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => {
239+
bug!("Unexpected coroutine/closure type in variance computation");
240240
}
241241

242242
ty::Ref(region, ty, mutbl) => {

compiler/rustc_hir_typeck/src/callee.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
146146
// Check whether this is a call to a closure where we
147147
// haven't yet decided on whether the closure is fn vs
148148
// fnmut vs fnonce. If so, we have to defer further processing.
149-
if self.closure_kind(args).is_none() {
149+
if self.closure_kind(adjusted_ty).is_none() {
150150
let closure_sig = args.as_closure().sig();
151151
let closure_sig = self.instantiate_binder_with_fresh_vars(
152152
call_expr.span,
@@ -159,10 +159,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
159159
DeferredCallResolution {
160160
call_expr,
161161
callee_expr,
162-
adjusted_ty,
162+
closure_ty: adjusted_ty,
163163
adjustments,
164164
fn_sig: closure_sig,
165-
closure_args: args,
166165
},
167166
);
168167
return Some(CallStep::DeferredClosure(def_id, closure_sig));
@@ -900,10 +899,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
900899
pub struct DeferredCallResolution<'tcx> {
901900
call_expr: &'tcx hir::Expr<'tcx>,
902901
callee_expr: &'tcx hir::Expr<'tcx>,
903-
adjusted_ty: Ty<'tcx>,
902+
closure_ty: Ty<'tcx>,
904903
adjustments: Vec<Adjustment<'tcx>>,
905904
fn_sig: ty::FnSig<'tcx>,
906-
closure_args: GenericArgsRef<'tcx>,
907905
}
908906

909907
impl<'a, 'tcx> DeferredCallResolution<'tcx> {
@@ -912,10 +910,10 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
912910

913911
// we should not be invoked until the closure kind has been
914912
// determined by upvar inference
915-
assert!(fcx.closure_kind(self.closure_args).is_some());
913+
assert!(fcx.closure_kind(self.closure_ty).is_some());
916914

917915
// We may now know enough to figure out fn vs fnmut etc.
918-
match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) {
916+
match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) {
919917
Some((autoref, method_callee)) => {
920918
// One problem is that when we get here, we are going
921919
// to have a newly instantiated function signature

compiler/rustc_hir_typeck/src/cast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
133133
| ty::FnDef(..)
134134
| ty::FnPtr(..)
135135
| ty::Closure(..)
136+
| ty::CoroutineClosure(..)
136137
| ty::Coroutine(..)
137138
| ty::Adt(..)
138139
| ty::Never

compiler/rustc_hir_typeck/src/method/suggest.rs

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

compiler/rustc_hir_typeck/src/upvar.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
170170
) {
171171
// Extract the type of the closure.
172172
let ty = self.node_ty(closure_hir_id);
173-
let (closure_def_id, args) = match *ty.kind() {
174-
ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)),
175-
ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args)),
173+
let (closure_def_id, args, infer_kind) = match *ty.kind() {
174+
ty::Closure(def_id, args) => {
175+
(def_id, UpvarArgs::Closure(args), self.closure_kind(ty).is_none())
176+
}
177+
ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args), false),
176178
ty::Error(_) => {
177179
// #51714: skip analysis when we have already encountered type errors
178180
return;
@@ -188,12 +190,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
188190
};
189191
let closure_def_id = closure_def_id.expect_local();
190192

191-
let infer_kind = if let UpvarArgs::Closure(closure_args) = args {
192-
self.closure_kind(closure_args).is_none().then_some(closure_args)
193-
} else {
194-
None
195-
};
196-
197193
assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
198194
let mut delegate = InferBorrowKind {
199195
closure_def_id,
@@ -308,10 +304,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
308304

309305
let before_feature_tys = self.final_upvar_tys(closure_def_id);
310306

311-
if let Some(closure_args) = infer_kind {
307+
if infer_kind {
312308
// Unify the (as yet unbound) type variable in the closure
313309
// args with the kind we inferred.
314-
let closure_kind_ty = closure_args.as_closure().kind_ty();
310+
let closure_kind_ty = match args {
311+
UpvarArgs::Closure(args) => args.as_closure().kind_ty(),
312+
UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().kind_ty(),
313+
UpvarArgs::Coroutine(_) => unreachable!("coroutines don't have an inferred kind"),
314+
};
315315
self.demand_eqtype(
316316
span,
317317
Ty::from_closure_kind(self.tcx, closure_kind),

0 commit comments

Comments
 (0)