Skip to content

Commit 988fccb

Browse files
committed
Exhaustively match CoroutineKind in fn_sig_for_fn_abi
1 parent b7bc8d5 commit 988fccb

File tree

1 file changed

+70
-60
lines changed
  • compiler/rustc_ty_utils/src

1 file changed

+70
-60
lines changed

compiler/rustc_ty_utils/src/abi.rs

+70-60
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ fn fn_sig_for_fn_abi<'tcx>(
9898
)
9999
}
100100
ty::Coroutine(did, args, _) => {
101+
let coroutine_kind = tcx.coroutine_kind(did).unwrap();
101102
let sig = args.as_coroutine().poly_sig();
102103

103104
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
@@ -112,74 +113,83 @@ fn fn_sig_for_fn_abi<'tcx>(
112113
let pin_did = tcx.require_lang_item(LangItem::Pin, None);
113114
let pin_adt_ref = tcx.adt_def(pin_did);
114115
let pin_args = tcx.mk_args(&[env_ty.into()]);
115-
let env_ty = if tcx.coroutine_is_gen(did) {
116-
// Iterator::next doesn't accept a pinned argument,
117-
// unlike for all other coroutine kinds.
118-
env_ty
119-
} else {
120-
Ty::new_adt(tcx, pin_adt_ref, pin_args)
116+
let env_ty = match coroutine_kind {
117+
hir::CoroutineKind::Gen(_) => {
118+
// Iterator::next doesn't accept a pinned argument,
119+
// unlike for all other coroutine kinds.
120+
env_ty
121+
}
122+
hir::CoroutineKind::Async(_) | hir::CoroutineKind::Coroutine => {
123+
Ty::new_adt(tcx, pin_adt_ref, pin_args)
124+
}
121125
};
122126

123127
let sig = sig.skip_binder();
124128
// The `FnSig` and the `ret_ty` here is for a coroutines main
125129
// `Coroutine::resume(...) -> CoroutineState` function in case we
126-
// have an ordinary coroutine, or the `Future::poll(...) -> Poll`
127-
// function in case this is a special coroutine backing an async construct.
128-
let (resume_ty, ret_ty) = if tcx.coroutine_is_async(did) {
129-
// The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
130-
assert_eq!(sig.yield_ty, tcx.types.unit);
131-
132-
let poll_did = tcx.require_lang_item(LangItem::Poll, None);
133-
let poll_adt_ref = tcx.adt_def(poll_did);
134-
let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
135-
let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
136-
137-
// We have to replace the `ResumeTy` that is used for type and borrow checking
138-
// with `&mut Context<'_>` which is used in codegen.
139-
#[cfg(debug_assertions)]
140-
{
141-
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
142-
let expected_adt =
143-
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
144-
assert_eq!(*resume_ty_adt, expected_adt);
145-
} else {
146-
panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
147-
};
148-
}
149-
let context_mut_ref = Ty::new_task_context(tcx);
150-
151-
(Some(context_mut_ref), ret_ty)
152-
} else if tcx.coroutine_is_gen(did) {
153-
// The signature should be `Iterator::next(_) -> Option<Yield>`
154-
let option_did = tcx.require_lang_item(LangItem::Option, None);
155-
let option_adt_ref = tcx.adt_def(option_did);
156-
let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
157-
let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
158-
159-
assert_eq!(sig.return_ty, tcx.types.unit);
130+
// have an ordinary coroutine, the `Future::poll(...) -> Poll`
131+
// function in case this is a special coroutine backing an async construct
132+
// or the `Iterator::next(...) -> Option` function in case this is a
133+
// special coroutine backing a gen construct.
134+
let (resume_ty, ret_ty) = match coroutine_kind {
135+
hir::CoroutineKind::Async(_) => {
136+
// The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
137+
assert_eq!(sig.yield_ty, tcx.types.unit);
138+
139+
let poll_did = tcx.require_lang_item(LangItem::Poll, None);
140+
let poll_adt_ref = tcx.adt_def(poll_did);
141+
let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
142+
let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
143+
144+
// We have to replace the `ResumeTy` that is used for type and borrow checking
145+
// with `&mut Context<'_>` which is used in codegen.
146+
#[cfg(debug_assertions)]
147+
{
148+
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
149+
let expected_adt =
150+
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
151+
assert_eq!(*resume_ty_adt, expected_adt);
152+
} else {
153+
panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
154+
};
155+
}
156+
let context_mut_ref = Ty::new_task_context(tcx);
160157

161-
// We have to replace the `ResumeTy` that is used for type and borrow checking
162-
// with `()` which is used in codegen.
163-
#[cfg(debug_assertions)]
164-
{
165-
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
166-
let expected_adt =
167-
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
168-
assert_eq!(*resume_ty_adt, expected_adt);
169-
} else {
170-
panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
171-
};
158+
(Some(context_mut_ref), ret_ty)
172159
}
160+
hir::CoroutineKind::Gen(_) => {
161+
// The signature should be `Iterator::next(_) -> Option<Yield>`
162+
let option_did = tcx.require_lang_item(LangItem::Option, None);
163+
let option_adt_ref = tcx.adt_def(option_did);
164+
let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
165+
let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
166+
167+
assert_eq!(sig.return_ty, tcx.types.unit);
168+
169+
// We have to replace the `ResumeTy` that is used for type and borrow checking
170+
// with `()` which is used in codegen.
171+
#[cfg(debug_assertions)]
172+
{
173+
if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
174+
let expected_adt =
175+
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None));
176+
assert_eq!(*resume_ty_adt, expected_adt);
177+
} else {
178+
panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
179+
};
180+
}
173181

174-
(None, ret_ty)
175-
} else {
176-
// The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
177-
let state_did = tcx.require_lang_item(LangItem::CoroutineState, None);
178-
let state_adt_ref = tcx.adt_def(state_did);
179-
let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
180-
let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
181-
182-
(Some(sig.resume_ty), ret_ty)
182+
(None, ret_ty)
183+
}
184+
hir::CoroutineKind::Coroutine => {
185+
// The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
186+
let state_did = tcx.require_lang_item(LangItem::CoroutineState, None);
187+
let state_adt_ref = tcx.adt_def(state_did);
188+
let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
189+
let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
190+
191+
(Some(sig.resume_ty), ret_ty)
192+
}
183193
};
184194

185195
let fn_sig = if let Some(resume_ty) = resume_ty {

0 commit comments

Comments
 (0)