mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Add gen blocks to ast and do some broken ast lowering
This commit is contained in:
parent
14423080f1
commit
621494382d
@ -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
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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(_, _)
|
||||
|
@ -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(_, _)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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(_, _))
|
||||
|
@ -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),
|
||||
|
@ -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(..)
|
||||
|
@ -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(..)
|
||||
|
@ -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(..) => {
|
||||
|
@ -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(..)
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user