Auto merge of #116447 - oli-obk:gen_fn, r=compiler-errors
Implement `gen` blocks in the 2024 edition Coroutines tracking issue https://github.com/rust-lang/rust/issues/43122 `gen` block tracking issue https://github.com/rust-lang/rust/issues/117078 This PR implements `gen` blocks that implement `Iterator`. Most of the logic with `async` blocks is shared, and thus I renamed various types that were referring to `async` specifically. An example usage of `gen` blocks is ```rust fn foo() -> impl Iterator<Item = i32> { gen { yield 42; for i in 5..18 { if i.is_even() { continue } yield i * 2; } } } ``` The limitations (to be resolved) of the implementation are listed in the tracking issue
This commit is contained in:
commit
2cad938a81
75 changed files with 1096 additions and 148 deletions
|
@ -373,11 +373,12 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
|||
span: Span,
|
||||
yield_span: Span,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
let mut err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
E0626,
|
||||
"borrow may still be in use when coroutine yields",
|
||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||
);
|
||||
err.span_label(yield_span, "possible yield occurs here");
|
||||
err
|
||||
|
|
|
@ -2491,11 +2491,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
|
||||
Ok(string) => {
|
||||
if string.starts_with("async ") {
|
||||
let pos = args_span.lo() + BytePos(6);
|
||||
(args_span.with_lo(pos).with_hi(pos), "move ")
|
||||
} else if string.starts_with("async|") {
|
||||
let pos = args_span.lo() + BytePos(5);
|
||||
let coro_prefix = if string.starts_with("async") {
|
||||
// `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` to `u32`
|
||||
Some(5)
|
||||
} else if string.starts_with("gen") {
|
||||
// `gen` is 3 chars long
|
||||
Some(3)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(n) = coro_prefix {
|
||||
let pos = args_span.lo() + BytePos(n);
|
||||
(args_span.with_lo(pos).with_hi(pos), " move")
|
||||
} else {
|
||||
(args_span.shrink_to_lo(), "move ")
|
||||
|
@ -2505,6 +2511,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
};
|
||||
let kind = match use_span.coroutine_kind() {
|
||||
Some(coroutine_kind) => match coroutine_kind {
|
||||
CoroutineKind::Gen(kind) => match kind {
|
||||
CoroutineSource::Block => "gen block",
|
||||
CoroutineSource::Closure => "gen closure",
|
||||
_ => bug!("gen block/closure expected, but gen function found."),
|
||||
},
|
||||
CoroutineKind::Async(async_kind) => match async_kind {
|
||||
CoroutineSource::Block => "async block",
|
||||
CoroutineSource::Closure => "async closure",
|
||||
|
|
|
@ -698,6 +698,20 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
" of async function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Gen(gen)) => match gen {
|
||||
hir::CoroutineSource::Block => " of gen block",
|
||||
hir::CoroutineSource::Closure => " of gen closure",
|
||||
hir::CoroutineSource::Fn => {
|
||||
let parent_item =
|
||||
hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
|
||||
let output = &parent_item
|
||||
.fn_decl()
|
||||
.expect("coroutine lowered from gen fn should be in fn")
|
||||
.output;
|
||||
span = output.span();
|
||||
" of gen function"
|
||||
}
|
||||
},
|
||||
Some(hir::CoroutineKind::Coroutine) => " of coroutine",
|
||||
None => " of closure",
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue