Skip to content

Commit 7eeaaa2

Browse files
Compute yield and return types outside of check_fn
1 parent 71dacdf commit 7eeaaa2

File tree

6 files changed

+81
-68
lines changed

6 files changed

+81
-68
lines changed

compiler/rustc_hir_typeck/src/check.rs

+2-43
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
2828
pub(super) fn check_fn<'a, 'tcx>(
2929
fcx: &mut FnCtxt<'a, 'tcx>,
3030
fn_sig: ty::FnSig<'tcx>,
31+
coroutine_types: Option<CoroutineTypes<'tcx>>,
3132
decl: &'tcx hir::FnDecl<'tcx>,
3233
fn_def_id: LocalDefId,
3334
body: &'tcx hir::Body<'tcx>,
34-
closure_kind: Option<hir::ClosureKind>,
3535
params_can_be_unsized: bool,
3636
) -> Option<CoroutineTypes<'tcx>> {
3737
let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id);
@@ -49,54 +49,13 @@ pub(super) fn check_fn<'a, 'tcx>(
4949
fcx.param_env,
5050
));
5151

52+
fcx.coroutine_types = coroutine_types;
5253
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
5354

5455
let span = body.value.span;
5556

5657
forbid_intrinsic_abi(tcx, span, fn_sig.abi);
5758

58-
if let Some(hir::ClosureKind::Coroutine(kind)) = closure_kind {
59-
let yield_ty = match kind {
60-
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
61-
| hir::CoroutineKind::Coroutine(_) => {
62-
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
63-
kind: TypeVariableOriginKind::TypeInference,
64-
span,
65-
});
66-
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
67-
yield_ty
68-
}
69-
// HACK(-Ztrait-solver=next): In the *old* trait solver, we must eagerly
70-
// guide inference on the yield type so that we can handle `AsyncIterator`
71-
// in this block in projection correctly. In the new trait solver, it is
72-
// not a problem.
73-
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
74-
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
75-
kind: TypeVariableOriginKind::TypeInference,
76-
span,
77-
});
78-
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
79-
80-
Ty::new_adt(
81-
tcx,
82-
tcx.adt_def(tcx.require_lang_item(hir::LangItem::Poll, Some(span))),
83-
tcx.mk_args(&[Ty::new_adt(
84-
tcx,
85-
tcx.adt_def(tcx.require_lang_item(hir::LangItem::Option, Some(span))),
86-
tcx.mk_args(&[yield_ty.into()]),
87-
)
88-
.into()]),
89-
)
90-
}
91-
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => Ty::new_unit(tcx),
92-
};
93-
94-
// Resume type defaults to `()` if the coroutine has no argument.
95-
let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| Ty::new_unit(tcx));
96-
97-
fcx.coroutine_types = Some(CoroutineTypes { resume_ty, yield_ty });
98-
}
99-
10059
GatherLocalsVisitor::new(fcx).visit_body(body);
10160

10261
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`

compiler/rustc_hir_typeck/src/closure.rs

+70-16
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7272
opt_kind: Option<ty::ClosureKind>,
7373
expected_sig: Option<ExpectedSig<'tcx>>,
7474
) -> Ty<'tcx> {
75-
let body = self.tcx.hir().body(closure.body);
75+
let tcx = self.tcx;
76+
let body = tcx.hir().body(closure.body);
7677

7778
trace!("decl = {:#?}", closure.fn_decl);
7879
let expr_def_id = closure.def_id;
@@ -83,26 +84,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8384

8485
debug!(?bound_sig, ?liberated_sig);
8586

87+
// FIXME: We could probably actually just unify this further --
88+
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
89+
// we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
90+
// similar to how `ty::GenSig` is a distinct data structure.
91+
let coroutine_types = match closure.kind {
92+
hir::ClosureKind::Closure => None,
93+
hir::ClosureKind::Coroutine(kind) => {
94+
let yield_ty = match kind {
95+
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
96+
| hir::CoroutineKind::Coroutine(_) => {
97+
let yield_ty = self.next_ty_var(TypeVariableOrigin {
98+
kind: TypeVariableOriginKind::TypeInference,
99+
span: expr_span,
100+
});
101+
self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
102+
yield_ty
103+
}
104+
// HACK(-Ztrait-solver=next): In the *old* trait solver, we must eagerly
105+
// guide inference on the yield type so that we can handle `AsyncIterator`
106+
// in this block in projection correctly. In the new trait solver, it is
107+
// not a problem.
108+
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
109+
let yield_ty = self.next_ty_var(TypeVariableOrigin {
110+
kind: TypeVariableOriginKind::TypeInference,
111+
span: expr_span,
112+
});
113+
self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType);
114+
115+
Ty::new_adt(
116+
tcx,
117+
tcx.adt_def(
118+
tcx.require_lang_item(hir::LangItem::Poll, Some(expr_span)),
119+
),
120+
tcx.mk_args(&[Ty::new_adt(
121+
tcx,
122+
tcx.adt_def(
123+
tcx.require_lang_item(hir::LangItem::Option, Some(expr_span)),
124+
),
125+
tcx.mk_args(&[yield_ty.into()]),
126+
)
127+
.into()]),
128+
)
129+
}
130+
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => {
131+
tcx.types.unit
132+
}
133+
};
134+
135+
// Resume type defaults to `()` if the coroutine has no argument.
136+
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
137+
138+
Some(CoroutineTypes { resume_ty, yield_ty })
139+
}
140+
};
141+
86142
let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
87-
let coroutine_types = check_fn(
143+
check_fn(
88144
&mut fcx,
89145
liberated_sig,
146+
coroutine_types,
90147
closure.fn_decl,
91148
expr_def_id,
92149
body,
93-
Some(closure.kind),
94150
// Closure "rust-call" ABI doesn't support unsized params
95151
false,
96152
);
97153

98-
let parent_args = GenericArgs::identity_for_item(
99-
self.tcx,
100-
self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
101-
);
154+
let parent_args =
155+
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
102156

103157
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
104158
kind: TypeVariableOriginKind::ClosureSynthetic,
105-
span: self.tcx.def_span(expr_def_id),
159+
span: expr_span,
106160
});
107161

108162
match closure.kind {
@@ -111,8 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
111165
// Tuple up the arguments and insert the resulting function type into
112166
// the `closures` table.
113167
let sig = bound_sig.map_bound(|sig| {
114-
self.tcx.mk_fn_sig(
115-
[Ty::new_tup(self.tcx, sig.inputs())],
168+
tcx.mk_fn_sig(
169+
[Ty::new_tup(tcx, sig.inputs())],
116170
sig.output(),
117171
sig.c_variadic,
118172
sig.unsafety,
@@ -123,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
123177
debug!(?sig, ?opt_kind);
124178

125179
let closure_kind_ty = match opt_kind {
126-
Some(kind) => Ty::from_closure_kind(self.tcx, kind),
180+
Some(kind) => Ty::from_closure_kind(tcx, kind),
127181

128182
// Create a type variable (for now) to represent the closure kind.
129183
// It will be unified during the upvar inference phase (`upvar.rs`)
@@ -135,16 +189,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135189
};
136190

137191
let closure_args = ty::ClosureArgs::new(
138-
self.tcx,
192+
tcx,
139193
ty::ClosureArgsParts {
140194
parent_args,
141195
closure_kind_ty,
142-
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(self.tcx, sig),
196+
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
143197
tupled_upvars_ty,
144198
},
145199
);
146200

147-
Ty::new_closure(self.tcx, expr_def_id.to_def_id(), closure_args.args)
201+
Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args)
148202
}
149203
hir::ClosureKind::Coroutine(_) => {
150204
let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
@@ -161,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
161215
));
162216

163217
let coroutine_args = ty::CoroutineArgs::new(
164-
self.tcx,
218+
tcx,
165219
ty::CoroutineArgsParts {
166220
parent_args,
167221
resume_ty,
@@ -172,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172226
},
173227
);
174228

175-
Ty::new_coroutine(self.tcx, expr_def_id.to_def_id(), coroutine_args.args)
229+
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args)
176230
}
177231
}
178232
}

compiler/rustc_hir_typeck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ fn typeck_with_fallback<'tcx>(
193193
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
194194
let fn_sig = fcx.normalize(body.value.span, fn_sig);
195195

196-
check_fn(&mut fcx, fn_sig, decl, def_id, body, None, tcx.features().unsized_fn_params);
196+
check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params);
197197
} else {
198198
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
199199
Some(fcx.next_ty_var(TypeVariableOrigin {

tests/ui/coroutine/gen_block.e2024.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | let _ = || yield true;
88
= help: add `#![feature(coroutines)]` to the crate attributes to enable
99

1010
error[E0282]: type annotations needed
11-
--> $DIR/gen_block.rs:6:17
11+
--> $DIR/gen_block.rs:6:13
1212
|
1313
LL | let x = gen {};
14-
| ^^ cannot infer type
14+
| ^^^^^^ cannot infer type
1515

1616
error: aborting due to 2 previous errors
1717

tests/ui/coroutine/sized-yield.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0277]: the size for values of type `str` cannot be known at compilation time
2-
--> $DIR/sized-yield.rs:8:27
2+
--> $DIR/sized-yield.rs:8:19
33
|
44
LL | let mut gen = move || {
5-
| ___________________________^
5+
| ___________________^
66
LL | |
77
LL | | yield s[..];
88
LL | | };

tests/ui/feature-gates/feature-gate-gen_blocks.e2024.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ LL | async gen {};
3535
= help: add `#![feature(gen_blocks)]` to the crate attributes to enable
3636

3737
error[E0282]: type annotations needed
38-
--> $DIR/feature-gate-gen_blocks.rs:5:9
38+
--> $DIR/feature-gate-gen_blocks.rs:5:5
3939
|
4040
LL | gen {};
41-
| ^^ cannot infer type
41+
| ^^^^^^ cannot infer type
4242

4343
error[E0282]: type annotations needed
44-
--> $DIR/feature-gate-gen_blocks.rs:12:15
44+
--> $DIR/feature-gate-gen_blocks.rs:12:5
4545
|
4646
LL | async gen {};
47-
| ^^ cannot infer type
47+
| ^^^^^^^^^^^^ cannot infer type
4848

4949
error: aborting due to 6 previous errors
5050

0 commit comments

Comments
 (0)