diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-10-20 21:26:57 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-10-27 13:05:48 +0000 |
| commit | 621494382da59e3a899a968e7d445170dd37ba1d (patch) | |
| tree | 90f7d58cb716b2220815f764d303d616ba343e18 | |
| parent | 14423080f1f9e9729d372f9b5da06c0ab4aef6e3 (diff) | |
| download | rust-621494382da59e3a899a968e7d445170dd37ba1d.tar.gz rust-621494382da59e3a899a968e7d445170dd37ba1d.zip | |
Add gen blocks to ast and do some broken ast lowering
21 files changed, 131 insertions, 56 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 543c528db44..aceee07a734 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1232,7 +1232,7 @@ impl Expr { ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Block(..) => ExprPrecedence::Block, ExprKind::TryBlock(..) => ExprPrecedence::TryBlock, - ExprKind::Async(..) => ExprPrecedence::Async, + ExprKind::Gen(..) => ExprPrecedence::Gen, ExprKind::Await(..) => ExprPrecedence::Await, ExprKind::Assign(..) => ExprPrecedence::Assign, ExprKind::AssignOp(..) => ExprPrecedence::AssignOp, @@ -1401,11 +1401,9 @@ pub enum ExprKind { Closure(Box<Closure>), /// A block (`'label: { ... }`). Block(P<Block>, Option<Label>), - /// An async block (`async move { ... }`). - /// - /// The async block used to have a `NodeId`, which was removed in favor of - /// using the parent `NodeId` of the parent `Expr`. - Async(CaptureBy, P<Block>), + /// An `async` block (`async move { ... }`), + /// or a `gen` block (`gen move { ... }`) + Gen(CaptureBy, P<Block>, GenBlockKind), /// An await expression (`my_future.await`). Span is of await keyword. Await(P<Expr>, Span), @@ -1495,6 +1493,28 @@ pub enum ExprKind { Err, } +/// Used to differentiate between `async {}` blocks and `gen {}` blocks. +#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] +pub enum GenBlockKind { + Async, + Gen, +} + +impl fmt::Display for GenBlockKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.modifier().fmt(f) + } +} + +impl GenBlockKind { + pub fn modifier(&self) -> &'static str { + match self { + GenBlockKind::Async => "async", + GenBlockKind::Gen => "gen", + } + } +} + /// The explicit `Self` type in a "qualified path". The actual /// path, including the trait and the associated item, is stored /// separately. `position` represents the index of the associated diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ba2887146cf..0634ee970ec 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1418,7 +1418,7 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_block(blk); visit_opt(label, |label| vis.visit_label(label)); } - ExprKind::Async(_capture_by, body) => { + ExprKind::Gen(_capture_by, body, _) => { vis.visit_block(body); } ExprKind::Await(expr, await_kw_span) => { diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index f9f1c0cf956..821fca6656c 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -46,7 +46,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { Closure(closure) => { expr = &closure.body; } - Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..) + Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..) | TryBlock(..) | While(..) => break Some(expr), _ => break None, } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index d3e43e20235..13768c12017 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -285,7 +285,7 @@ pub enum ExprPrecedence { Block, TryBlock, Struct, - Async, + Gen, Await, Err, } @@ -351,7 +351,7 @@ impl ExprPrecedence { | ExprPrecedence::ConstBlock | ExprPrecedence::Block | ExprPrecedence::TryBlock - | ExprPrecedence::Async + | ExprPrecedence::Gen | ExprPrecedence::Struct | ExprPrecedence::Err => PREC_PAREN, } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e66c4a9ee26..e091961a144 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -872,7 +872,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } - ExprKind::Async(_, body) => { + ExprKind::Gen(_, body, _) => { visitor.visit_block(body); } ExprKind::Await(expr, _) => visitor.visit_expr(expr), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index ab82bbd46a6..cce0b44fd98 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -183,7 +183,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), hir::MatchSource::Normal, ), - ExprKind::Async(capture_clause, block) => self.make_async_expr( + ExprKind::Gen(capture_clause, block, GenBlockKind::Async) => self.make_async_expr( *capture_clause, e.id, None, @@ -317,6 +317,14 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } + ExprKind::Gen(capture_clause, block, GenBlockKind::Gen) => self.make_gen_expr( + *capture_clause, + e.id, + None, + e.span, + hir::CoroutineSource::Block, + |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), @@ -661,6 +669,57 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } + /// Lower a `gen` construct to a generator that implements `Iterator`. + /// + /// This results in: + /// + /// ```text + /// static move? |()| -> () { + /// <body> + /// } + /// ``` + pub(super) fn make_gen_expr( + &mut self, + capture_clause: CaptureBy, + closure_node_id: NodeId, + _yield_ty: Option<hir::FnRetTy<'hir>>, + span: Span, + gen_kind: hir::CoroutineSource, + body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, + ) -> hir::ExprKind<'hir> { + let output = hir::FnRetTy::DefaultReturn(self.lower_span(span)); + + // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. + let fn_decl = self.arena.alloc(hir::FnDecl { + inputs: &[], + output, + c_variadic: false, + implicit_self: hir::ImplicitSelfKind::None, + lifetime_elision_allowed: false, + }); + + let body = self.lower_body(move |this| { + this.coroutine_kind = Some(hir::CoroutineKind::Gen(gen_kind)); + + let res = body(this); + (&[], res) + }); + + // `static |()| -> () { body }`: + hir::ExprKind::Closure(self.arena.alloc(hir::Closure { + def_id: self.local_def_id(closure_node_id), + binder: hir::ClosureBinder::Default, + capture_clause, + bound_generic_params: &[], + fn_decl, + body, + fn_decl_span: self.lower_span(span), + fn_arg_span: None, + movability: Some(hir::Movability::Static), + constness: hir::Constness::NotConst, + })) + } + /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled. pub(super) fn maybe_forward_track_caller( diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 269cb8f2380..e84af12d3f9 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -445,8 +445,8 @@ impl<'a> State<'a> { self.ibox(0); self.print_block_with_attrs(blk, attrs); } - ast::ExprKind::Async(capture_clause, blk) => { - self.word_nbsp("async"); + ast::ExprKind::Gen(capture_clause, blk, kind) => { + self.word_nbsp(kind.modifier()); self.print_capture_clause(*capture_clause); // cbox/ibox in analogy to the `ExprKind::Block` arm above self.cbox(0); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 6733b9e56ad..2a4bfe9e200 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -294,7 +294,7 @@ impl<'cx, 'a> Context<'cx, 'a> { // sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test. ExprKind::Assign(_, _, _) | ExprKind::AssignOp(_, _, _) - | ExprKind::Async(_, _) + | ExprKind::Gen(_, _, _) | ExprKind::Await(_, _) | ExprKind::Block(_, _) | ExprKind::Break(_, _) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e59076acf4c..a1b04105a4c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -9,7 +9,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{Path, PathSegment}; +use ast::{GenBlockKind, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -1422,9 +1422,6 @@ impl<'a> Parser<'a> { } else if this.is_try_block() { this.expect_keyword(kw::Try)?; this.parse_try_block(lo) - } else if this.is_gen_block() { - this.expect_keyword(kw::Gen)?; - this.parse_gen_block(lo) } else if this.eat_keyword(kw::Return) { this.parse_expr_return() } else if this.eat_keyword(kw::Continue) { @@ -1446,12 +1443,14 @@ impl<'a> Parser<'a> { if this.check_keyword(kw::Async) { if this.is_async_block() { // Check for `async {` and `async move {`. - this.parse_async_block() + this.parse_gen_block() } else { this.parse_expr_closure() } } else if this.eat_keyword(kw::Await) { this.recover_incorrect_await_syntax(lo, this.prev_token.span) + } else if this.token.uninterpolated_span().at_least_rust_2024() { + if this.is_gen_block() { this.parse_gen_block() } else { this.parse_expr_lit() } } else { this.parse_expr_lit() } @@ -3043,14 +3042,6 @@ impl<'a> Parser<'a> { } } - /// Parses a `gen {...}` expression (`gen` token already eaten). - fn parse_gen_block(&mut self, _span_lo: Span) -> PResult<'a, P<Expr>> { - let (_attrs, _body) = self.parse_inner_attrs_and_block()?; - - Err(errors::GenBlock { span: self.prev_token.span } - .into_diagnostic(&self.sess.span_diagnostic)) - } - fn is_do_catch_block(&self) -> bool { self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Catch]) @@ -3077,13 +3068,18 @@ impl<'a> Parser<'a> { && self.token.uninterpolated_span().at_least_rust_2024() } - /// Parses an `async move? {...}` expression. - fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> { + /// Parses an `async move? {...}` or `gen move? {...}` expression. + fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> { let lo = self.token.span; - self.expect_keyword(kw::Async)?; + let kind = if self.eat_keyword(kw::Async) { + GenBlockKind::Async + } else { + assert!(self.eat_keyword(kw::Gen)); + GenBlockKind::Gen + }; let capture_clause = self.parse_capture_clause()?; let (attrs, body) = self.parse_inner_attrs_and_block()?; - let kind = ExprKind::Async(capture_clause, body); + let kind = ExprKind::Gen(capture_clause, body, kind); Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs)) } @@ -3614,7 +3610,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Match(_, _) | ExprKind::Closure(_) | ExprKind::Block(_, _) - | ExprKind::Async(_, _) + | ExprKind::Gen(_, _, _) | ExprKind::TryBlock(_) | ExprKind::Underscore | ExprKind::Path(_, _) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 24087a4eabb..f915c1057d6 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -567,10 +567,10 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { (self, e, e.kind, Id::None, ast, Expr, ExprKind), [ Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let, - If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign, + If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, - Become, IncludedBytes, Err + Become, IncludedBytes, Gen, Err ] ); ast_visit::walk_expr(self, e) diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 356d7f365fe..13df7efe636 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -260,7 +260,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { Async::No => closure_def, } } - ExprKind::Async(_, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span), + ExprKind::Gen(_, _, _) => self.create_def(expr.id, DefPathData::ClosureExpr, expr.span), _ => self.parent_def, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 42ca407cddf..83f9f3a4210 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4321,7 +4321,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); } ExprKind::Closure(..) => visit::walk_expr(self, expr), - ExprKind::Async(..) => { + ExprKind::Gen(..) => { self.with_label_rib(RibKind::ClosureOrAsync, |this| visit::walk_expr(this, expr)); } ExprKind::Repeat(ref elem, ref ct) => { diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index d10f10ef87e..7dff37a2b8f 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -578,7 +578,7 @@ fn ident_difference_expr_with_base_location( | (Assign(_, _, _), Assign(_, _, _)) | (TryBlock(_), TryBlock(_)) | (Await(_, _), Await(_, _)) - | (Async(_, _), Async(_, _)) + | (Gen(_, _, _), Gen(_, _, _)) | (Block(_, _), Block(_, _)) | (Closure(_), Closure(_)) | (Match(_, _), Match(_, _)) diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index a78ff02021f..a2c61e07b70 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -211,7 +211,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { && eq_fn_decl(lf, rf) && eq_expr(le, re) }, - (Async(lc, lb), Async(rc, rb)) => lc == rc && eq_block(lb, rb), + (Gen(lc, lb, lk), Gen(rc, rb, rk)) => lc == rc && eq_block(lb, rb) && lk == rk, (Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt), (AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re), (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp), diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index ae8ee371ffa..836f8cc1916 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -190,7 +190,7 @@ impl<'a> Sugg<'a> { (snip, false) => Sugg::MaybeParen(snip), (snip, true) => Sugg::NonParen(snip), }, - ast::ExprKind::Async(..) + ast::ExprKind::Gen(..) | ast::ExprKind::Block(..) | ast::ExprKind::Break(..) | ast::ExprKind::Call(..) diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index a09146e9592..16b8ce7a916 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -188,7 +188,7 @@ fn rewrite_closure_expr( fn allow_multi_line(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Match(..) - | ast::ExprKind::Async(..) + | ast::ExprKind::Gen(..) | ast::ExprKind::Block(..) | ast::ExprKind::TryBlock(..) | ast::ExprKind::Loop(..) diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index acde8809329..8c2262fde81 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -367,7 +367,7 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Async(capture_by, ref block) => { + ast::ExprKind::Gen(capture_by, ref block, ref kind) => { let mover = if capture_by == ast::CaptureBy::Value { "move " } else { @@ -375,7 +375,7 @@ pub(crate) fn format_expr( }; if let rw @ Some(_) = rewrite_single_line_block( context, - format!("async {mover}").as_str(), + format!("{kind} {mover}").as_str(), block, Some(&expr.attrs), None, @@ -386,7 +386,7 @@ pub(crate) fn format_expr( // 6 = `async ` let budget = shape.width.saturating_sub(6); Some(format!( - "async {mover}{}", + "{kind} {mover}{}", rewrite_block( block, Some(&expr.attrs), @@ -1371,7 +1371,7 @@ pub(crate) fn can_be_overflowed_expr( } // Handle always block-like expressions - ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true, + ast::ExprKind::Gen(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true, // Handle `[]` and `{}`-like expressions ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => { diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 79a759d68ce..fd49030bf1b 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -473,7 +473,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::If(..) | ast::ExprKind::Block(..) | ast::ExprKind::ConstBlock(..) - | ast::ExprKind::Async(..) + | ast::ExprKind::Gen(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::TryBlock(..) diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr index 099a9d13cee..28cf036b7e8 100644 --- a/tests/ui/coroutine/gen_block.e2024.stderr +++ b/tests/ui/coroutine/gen_block.e2024.stderr @@ -1,10 +1,9 @@ -error: `gen` blocks are not yet implemented - --> $DIR/gen_block.rs:5:18 +error[E0282]: type annotations needed + --> $DIR/gen_block.rs:6:17 | LL | let x = gen {}; - | ^ - | - = help: only the keyword is reserved for now + | ^^ cannot infer type error: aborting due to previous error +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr index 1cdd5d070ee..d5ed28c5317 100644 --- a/tests/ui/coroutine/gen_block.none.stderr +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -1,5 +1,5 @@ error: expected identifier, found reserved keyword `yield` - --> $DIR/gen_block.rs:8:19 + --> $DIR/gen_block.rs:9:19 | LL | let y = gen { yield 42 }; | --- ^^^^^ expected identifier, found reserved keyword @@ -7,19 +7,19 @@ LL | let y = gen { yield 42 }; | while parsing this struct error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:5:13 + --> $DIR/gen_block.rs:6:13 | LL | let x = gen {}; | ^^^ not found in this scope error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:8:13 + --> $DIR/gen_block.rs:9:13 | LL | let y = gen { yield 42 }; | ^^^ not found in this scope error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:11:5 + --> $DIR/gen_block.rs:12:5 | LL | gen {}; | ^^^ not found in this scope diff --git a/tests/ui/coroutine/gen_block.rs b/tests/ui/coroutine/gen_block.rs index 5c0db5b3d38..fa502768236 100644 --- a/tests/ui/coroutine/gen_block.rs +++ b/tests/ui/coroutine/gen_block.rs @@ -1,10 +1,11 @@ // revisions: e2024 none //[e2024] compile-flags: --edition 2024 -Zunstable-options +#![cfg_attr(e2024, feature(coroutines))] fn main() { let x = gen {}; //[none]~^ ERROR: cannot find - //[e2024]~^^ ERROR: `gen` blocks are not yet implemented + //[e2024]~^^ ERROR: type annotations needed let y = gen { yield 42 }; //[none]~^ ERROR: found reserved keyword `yield` //[none]~| ERROR: cannot find |
