|
45 | 45 | //! For coroutines with state 1 (returned) and state 2 (poisoned) it panics. |
46 | 46 | //! Otherwise it continues the execution from the last suspension point. |
47 | 47 | //! |
| 48 | +//! If -Zfused-futures is given however, then `Future::poll` from the state 1 (returned) |
| 49 | +//! will not panic and will instead return `Poll::Pending`. |
| 50 | +//! |
48 | 51 | //! The other function is the drop glue for the coroutine. |
49 | 52 | //! For coroutines with state 0 (unresumed) it drops the upvars of the coroutine. |
50 | 53 | //! For coroutines with state 1 (returned) and state 2 (poisoned) it does nothing. |
@@ -218,10 +221,17 @@ impl<'tcx> TransformVisitor<'tcx> { |
218 | 221 | let source_info = SourceInfo::outermost(body.span); |
219 | 222 |
|
220 | 223 | let none_value = match self.coroutine_kind { |
| 224 | + CoroutineKind::Coroutine(_) => span_bug!(body.span, "`Coroutine`s cannot be fused"), |
| 225 | + // Fused futures continue to return `Poll::Pending`. |
221 | 226 | CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { |
222 | | - span_bug!(body.span, "`Future`s are not fused inherently") |
| 227 | + let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, body.span); |
| 228 | + make_aggregate_adt( |
| 229 | + poll_def_id, |
| 230 | + VariantIdx::ONE, |
| 231 | + self.tcx.mk_args(&[self.old_yield_ty.into()]), |
| 232 | + IndexVec::new(), |
| 233 | + ) |
223 | 234 | } |
224 | | - CoroutineKind::Coroutine(_) => span_bug!(body.span, "`Coroutine`s cannot be fused"), |
225 | 235 | // `gen` continues return `None` |
226 | 236 | CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { |
227 | 237 | let option_def_id = self.tcx.require_lang_item(LangItem::Option, body.span); |
@@ -278,7 +288,7 @@ impl<'tcx> TransformVisitor<'tcx> { |
278 | 288 | statements: &mut Vec<Statement<'tcx>>, |
279 | 289 | ) { |
280 | 290 | const ZERO: VariantIdx = VariantIdx::ZERO; |
281 | | - const ONE: VariantIdx = VariantIdx::from_usize(1); |
| 291 | + const ONE: VariantIdx = VariantIdx::ONE; |
282 | 292 | let rvalue = match self.coroutine_kind { |
283 | 293 | CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { |
284 | 294 | let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, source_info.span); |
@@ -1099,7 +1109,7 @@ fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>, source_info: SourceInfo) -> |
1099 | 1109 | const_: Const::zero_sized(tcx.types.unit), |
1100 | 1110 | })); |
1101 | 1111 | let ready_val = Rvalue::Aggregate( |
1102 | | - Box::new(AggregateKind::Adt(poll_def_id, VariantIdx::from_usize(0), args, None, None)), |
| 1112 | + Box::new(AggregateKind::Adt(poll_def_id, VariantIdx::ZERO, args, None, None)), |
1103 | 1113 | IndexVec::from_raw(vec![val]), |
1104 | 1114 | ); |
1105 | 1115 | Statement::new(source_info, StatementKind::Assign(Box::new((Place::return_place(), ready_val)))) |
@@ -1252,13 +1262,18 @@ fn create_coroutine_resume_function<'tcx>( |
1252 | 1262 | } |
1253 | 1263 |
|
1254 | 1264 | if can_return { |
| 1265 | + // TODO: simplify this match |
1255 | 1266 | let block = match transform.coroutine_kind { |
1256 | 1267 | CoroutineKind::Desugared(CoroutineDesugaring::Async, _) |
1257 | 1268 | | CoroutineKind::Coroutine(_) => { |
1258 | 1269 | // For `async_drop_in_place<T>::{closure}` we just keep return Poll::Ready, |
1259 | 1270 | // because async drop of such coroutine keeps polling original coroutine |
1260 | 1271 | if tcx.is_async_drop_in_place_coroutine(body.source.def_id()) { |
1261 | 1272 | insert_poll_ready_block(tcx, body) |
| 1273 | + } else if tcx.sess.opts.unstable_opts.fused_futures |
| 1274 | + && !matches!(transform.coroutine_kind, CoroutineKind::Coroutine(_)) |
| 1275 | + { |
| 1276 | + transform.insert_none_ret_block(body) |
1262 | 1277 | } else { |
1263 | 1278 | insert_panic_block(tcx, body, ResumedAfterReturn(transform.coroutine_kind)) |
1264 | 1279 | } |
|
0 commit comments