Rollup merge of #138435 - eholk:prefix-yield, r=oli-obk
Add support for postfix yield expressions We've been having a discussion about whether we want postfix yield, or want to stick with prefix yield, or have both. I figured it's easy enough to support both for now and let us play around with them while the feature is still experimental. This PR treats `yield x` and `x.yield` as semantically equivalent. There was a suggestion to make `yield x` have a `()` type (so it only works in coroutines with `Resume = ()`. I think that'd be worth trying, either in a later PR, or before this one merges, depending on people's opinions. #43122
This commit is contained in:
commit
d752721636
14 changed files with 161 additions and 20 deletions
|
@ -1657,7 +1657,7 @@ pub enum ExprKind {
|
||||||
Try(P<Expr>),
|
Try(P<Expr>),
|
||||||
|
|
||||||
/// A `yield`, with an optional value to be yielded.
|
/// A `yield`, with an optional value to be yielded.
|
||||||
Yield(Option<P<Expr>>),
|
Yield(YieldKind),
|
||||||
|
|
||||||
/// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),
|
/// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),
|
||||||
/// with an optional value to be returned.
|
/// with an optional value to be returned.
|
||||||
|
@ -1903,6 +1903,44 @@ pub enum MatchKind {
|
||||||
Postfix,
|
Postfix,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The kind of yield expression
|
||||||
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
|
pub enum YieldKind {
|
||||||
|
/// yield expr { ... }
|
||||||
|
Prefix(Option<P<Expr>>),
|
||||||
|
/// expr.yield { ... }
|
||||||
|
Postfix(P<Expr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl YieldKind {
|
||||||
|
/// Returns the expression inside the yield expression, if any.
|
||||||
|
///
|
||||||
|
/// For postfix yields, this is guaranteed to be `Some`.
|
||||||
|
pub const fn expr(&self) -> Option<&P<Expr>> {
|
||||||
|
match self {
|
||||||
|
YieldKind::Prefix(expr) => expr.as_ref(),
|
||||||
|
YieldKind::Postfix(expr) => Some(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the expression being yielded, if any.
|
||||||
|
pub const fn expr_mut(&mut self) -> Option<&mut P<Expr>> {
|
||||||
|
match self {
|
||||||
|
YieldKind::Prefix(expr) => expr.as_mut(),
|
||||||
|
YieldKind::Postfix(expr) => Some(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if both yields are prefix or both are postfix.
|
||||||
|
pub const fn same_kind(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(YieldKind::Prefix(_), YieldKind::Prefix(_)) => true,
|
||||||
|
(YieldKind::Postfix(_), YieldKind::Postfix(_)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A literal in a meta item.
|
/// A literal in a meta item.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||||
pub struct MetaItemLit {
|
pub struct MetaItemLit {
|
||||||
|
|
|
@ -1813,8 +1813,11 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
|
||||||
ExprKind::Paren(expr) => {
|
ExprKind::Paren(expr) => {
|
||||||
vis.visit_expr(expr);
|
vis.visit_expr(expr);
|
||||||
}
|
}
|
||||||
ExprKind::Yield(expr) => {
|
ExprKind::Yield(kind) => {
|
||||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
let expr = kind.expr_mut();
|
||||||
|
if let Some(expr) = expr {
|
||||||
|
vis.visit_expr(expr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Try(expr) => vis.visit_expr(expr),
|
ExprKind::Try(expr) => vis.visit_expr(expr),
|
||||||
ExprKind::TryBlock(body) => vis.visit_block(body),
|
ExprKind::TryBlock(body) => vis.visit_block(body),
|
||||||
|
|
|
@ -182,11 +182,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||||
| Range(_, Some(e), _)
|
| Range(_, Some(e), _)
|
||||||
| Ret(Some(e))
|
| Ret(Some(e))
|
||||||
| Unary(_, e)
|
| Unary(_, e)
|
||||||
| Yield(Some(e))
|
|
||||||
| Yeet(Some(e))
|
| Yeet(Some(e))
|
||||||
| Become(e) => {
|
| Become(e) => {
|
||||||
expr = e;
|
expr = e;
|
||||||
}
|
}
|
||||||
|
Yield(kind) => match kind.expr() {
|
||||||
|
Some(e) => expr = e,
|
||||||
|
None => break None,
|
||||||
|
},
|
||||||
Closure(closure) => {
|
Closure(closure) => {
|
||||||
expr = &closure.body;
|
expr = &closure.body;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +220,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||||
Break(_, None)
|
Break(_, None)
|
||||||
| Range(_, None, _)
|
| Range(_, None, _)
|
||||||
| Ret(None)
|
| Ret(None)
|
||||||
| Yield(None)
|
|
||||||
| Array(_)
|
| Array(_)
|
||||||
| Call(_, _)
|
| Call(_, _)
|
||||||
| MethodCall(_)
|
| MethodCall(_)
|
||||||
|
@ -237,7 +239,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||||
| Yeet(None)
|
| Yeet(None)
|
||||||
| UnsafeBinderCast(..)
|
| UnsafeBinderCast(..)
|
||||||
| Err(_)
|
| Err(_)
|
||||||
| Dummy => break None,
|
| Dummy => {
|
||||||
|
break None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1269,8 +1269,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||||
try_visit!(visitor.visit_ty(container));
|
try_visit!(visitor.visit_ty(container));
|
||||||
walk_list!(visitor, visit_ident, fields.iter());
|
walk_list!(visitor, visit_ident, fields.iter());
|
||||||
}
|
}
|
||||||
ExprKind::Yield(optional_expression) => {
|
ExprKind::Yield(kind) => {
|
||||||
visit_opt!(visitor, visit_expr, optional_expression);
|
visit_opt!(visitor, visit_expr, kind.expr());
|
||||||
}
|
}
|
||||||
ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
|
ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
|
||||||
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
|
ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
|
||||||
|
|
|
@ -351,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
rest,
|
rest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
ExprKind::Yield(kind) => self.lower_expr_yield(e.span, kind.expr().map(|x| &**x)),
|
||||||
ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
|
ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
|
||||||
|
|
||||||
ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
|
ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
|
||||||
|
|
|
@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||||
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
|
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
|
self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
|
||||||
FormatDebugHex, FormatSign, FormatTrait, token,
|
FormatDebugHex, FormatSign, FormatTrait, YieldKind, token,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::pp::Breaks::Inconsistent;
|
use crate::pp::Breaks::Inconsistent;
|
||||||
|
@ -761,7 +761,7 @@ impl<'a> State<'a> {
|
||||||
self.print_expr(e, FixupContext::default());
|
self.print_expr(e, FixupContext::default());
|
||||||
self.pclose();
|
self.pclose();
|
||||||
}
|
}
|
||||||
ast::ExprKind::Yield(e) => {
|
ast::ExprKind::Yield(YieldKind::Prefix(e)) => {
|
||||||
self.word("yield");
|
self.word("yield");
|
||||||
|
|
||||||
if let Some(expr) = e {
|
if let Some(expr) = e {
|
||||||
|
@ -773,6 +773,14 @@ impl<'a> State<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::ExprKind::Yield(YieldKind::Postfix(e)) => {
|
||||||
|
self.print_expr_cond_paren(
|
||||||
|
e,
|
||||||
|
e.precedence() < ExprPrecedence::Unambiguous,
|
||||||
|
fixup.leftmost_subexpression_with_dot(),
|
||||||
|
);
|
||||||
|
self.word(".yield");
|
||||||
|
}
|
||||||
ast::ExprKind::Try(e) => {
|
ast::ExprKind::Try(e) => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
e,
|
e,
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_ast::{
|
||||||
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
|
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
|
||||||
ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
|
ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
|
||||||
MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
|
MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
|
||||||
|
YieldKind,
|
||||||
};
|
};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
|
@ -1310,6 +1311,15 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
|
return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a postfix `yield`.
|
||||||
|
if self.eat_keyword(exp!(Yield)) {
|
||||||
|
let yield_span = self.prev_token.span;
|
||||||
|
self.psess.gated_spans.gate(sym::yield_expr, yield_span);
|
||||||
|
return Ok(
|
||||||
|
self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let fn_span_lo = self.token.span;
|
let fn_span_lo = self.token.span;
|
||||||
let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
|
let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
|
||||||
self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
|
self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
|
||||||
|
@ -1884,7 +1894,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse `"yield" expr?`.
|
/// Parse `"yield" expr?`.
|
||||||
fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let lo = self.prev_token.span;
|
let lo = self.prev_token.span;
|
||||||
let kind = ExprKind::Yield(self.parse_expr_opt()?);
|
let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?));
|
||||||
let span = lo.to(self.prev_token.span);
|
let span = lo.to(self.prev_token.span);
|
||||||
self.psess.gated_spans.gate(sym::yield_expr, span);
|
self.psess.gated_spans.gate(sym::yield_expr, span);
|
||||||
let expr = self.mk_expr(span, kind);
|
let expr = self.mk_expr(span, kind);
|
||||||
|
|
|
@ -201,7 +201,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||||
(Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt),
|
(Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt),
|
||||||
(Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb),
|
(Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb),
|
||||||
(TryBlock(l), TryBlock(r)) => eq_block(l, r),
|
(TryBlock(l), TryBlock(r)) => eq_block(l, r),
|
||||||
(Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()),
|
(Yield(l), Yield(r)) => eq_expr_opt(l.expr(), r.expr()) && l.same_kind(r),
|
||||||
|
(Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()),
|
||||||
(Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
(Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||||
(Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()),
|
(Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()),
|
||||||
(Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => {
|
(Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => {
|
||||||
|
|
|
@ -192,6 +192,7 @@ enum ChainItemKind {
|
||||||
StructField(symbol::Ident),
|
StructField(symbol::Ident),
|
||||||
TupleField(symbol::Ident, bool),
|
TupleField(symbol::Ident, bool),
|
||||||
Await,
|
Await,
|
||||||
|
Yield,
|
||||||
Comment(String, CommentPosition),
|
Comment(String, CommentPosition),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +204,7 @@ impl ChainItemKind {
|
||||||
| ChainItemKind::StructField(..)
|
| ChainItemKind::StructField(..)
|
||||||
| ChainItemKind::TupleField(..)
|
| ChainItemKind::TupleField(..)
|
||||||
| ChainItemKind::Await
|
| ChainItemKind::Await
|
||||||
|
| ChainItemKind::Yield
|
||||||
| ChainItemKind::Comment(..) => false,
|
| ChainItemKind::Comment(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,6 +259,10 @@ impl ChainItemKind {
|
||||||
let span = mk_sp(nested.span.hi(), expr.span.hi());
|
let span = mk_sp(nested.span.hi(), expr.span.hi());
|
||||||
(ChainItemKind::Await, span)
|
(ChainItemKind::Await, span)
|
||||||
}
|
}
|
||||||
|
ast::ExprKind::Yield(ast::YieldKind::Postfix(ref nested)) => {
|
||||||
|
let span = mk_sp(nested.span.hi(), expr.span.hi());
|
||||||
|
(ChainItemKind::Yield, span)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return (
|
return (
|
||||||
ChainItemKind::Parent {
|
ChainItemKind::Parent {
|
||||||
|
@ -306,6 +312,7 @@ impl Rewrite for ChainItem {
|
||||||
rewrite_ident(context, ident)
|
rewrite_ident(context, ident)
|
||||||
),
|
),
|
||||||
ChainItemKind::Await => ".await".to_owned(),
|
ChainItemKind::Await => ".await".to_owned(),
|
||||||
|
ChainItemKind::Yield => ".yield".to_owned(),
|
||||||
ChainItemKind::Comment(ref comment, _) => {
|
ChainItemKind::Comment(ref comment, _) => {
|
||||||
rewrite_comment(comment, false, shape, context.config)?
|
rewrite_comment(comment, false, shape, context.config)?
|
||||||
}
|
}
|
||||||
|
@ -508,7 +515,8 @@ impl Chain {
|
||||||
}),
|
}),
|
||||||
ast::ExprKind::Field(ref subexpr, _)
|
ast::ExprKind::Field(ref subexpr, _)
|
||||||
| ast::ExprKind::Try(ref subexpr)
|
| ast::ExprKind::Try(ref subexpr)
|
||||||
| ast::ExprKind::Await(ref subexpr, _) => Some(SubExpr {
|
| ast::ExprKind::Await(ref subexpr, _)
|
||||||
|
| ast::ExprKind::Yield(ast::YieldKind::Postfix(ref subexpr)) => Some(SubExpr {
|
||||||
expr: Self::convert_try(subexpr, context),
|
expr: Self::convert_try(subexpr, context),
|
||||||
is_method_call_receiver: false,
|
is_method_call_receiver: false,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -221,7 +221,7 @@ pub(crate) fn format_expr(
|
||||||
Ok(format!("break{id_str}"))
|
Ok(format!("break{id_str}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Yield(ref opt_expr) => {
|
ast::ExprKind::Yield(ast::YieldKind::Prefix(ref opt_expr)) => {
|
||||||
if let Some(ref expr) = *opt_expr {
|
if let Some(ref expr) = *opt_expr {
|
||||||
rewrite_unary_prefix(context, "yield ", &**expr, shape)
|
rewrite_unary_prefix(context, "yield ", &**expr, shape)
|
||||||
} else {
|
} else {
|
||||||
|
@ -243,7 +243,8 @@ pub(crate) fn format_expr(
|
||||||
ast::ExprKind::Try(..)
|
ast::ExprKind::Try(..)
|
||||||
| ast::ExprKind::Field(..)
|
| ast::ExprKind::Field(..)
|
||||||
| ast::ExprKind::MethodCall(..)
|
| ast::ExprKind::MethodCall(..)
|
||||||
| ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape),
|
| ast::ExprKind::Await(_, _)
|
||||||
|
| ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape),
|
||||||
ast::ExprKind::MacCall(ref mac) => {
|
ast::ExprKind::MacCall(ref mac) => {
|
||||||
rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
|
rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
|
||||||
wrap_str(
|
wrap_str(
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_ast::ast::{
|
||||||
self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility,
|
self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility,
|
||||||
VisibilityKind,
|
VisibilityKind,
|
||||||
};
|
};
|
||||||
use rustc_ast::ptr;
|
use rustc_ast::{YieldKind, ptr};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol};
|
use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
@ -485,7 +485,9 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
|
||||||
| ast::ExprKind::Index(_, ref expr, _)
|
| ast::ExprKind::Index(_, ref expr, _)
|
||||||
| ast::ExprKind::Unary(_, ref expr)
|
| ast::ExprKind::Unary(_, ref expr)
|
||||||
| ast::ExprKind::Try(ref expr)
|
| ast::ExprKind::Try(ref expr)
|
||||||
| ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr),
|
| ast::ExprKind::Yield(YieldKind::Prefix(Some(ref expr))) => {
|
||||||
|
is_block_expr(context, expr, repr)
|
||||||
|
}
|
||||||
ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr),
|
ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr),
|
||||||
// This can only be a string lit
|
// This can only be a string lit
|
||||||
ast::ExprKind::Lit(_) => {
|
ast::ExprKind::Lit(_) => {
|
||||||
|
@ -515,7 +517,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
|
||||||
| ast::ExprKind::Tup(..)
|
| ast::ExprKind::Tup(..)
|
||||||
| ast::ExprKind::Use(..)
|
| ast::ExprKind::Use(..)
|
||||||
| ast::ExprKind::Type(..)
|
| ast::ExprKind::Type(..)
|
||||||
| ast::ExprKind::Yield(None)
|
| ast::ExprKind::Yield(..)
|
||||||
| ast::ExprKind::Underscore => false,
|
| ast::ExprKind::Underscore => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
src/tools/rustfmt/tests/target/postfix-yield.rs
Normal file
17
src/tools/rustfmt/tests/target/postfix-yield.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// This demonstrates a proposed alternate or additional option of having yield in postfix position.
|
||||||
|
//@ edition: 2024
|
||||||
|
|
||||||
|
#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)]
|
||||||
|
|
||||||
|
use std::ops::{Coroutine, CoroutineState};
|
||||||
|
use std::pin::pin;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut coro = pin!(
|
||||||
|
#[coroutine]
|
||||||
|
|_: i32| {
|
||||||
|
let x = 1.yield;
|
||||||
|
(x + 2).await;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
15
tests/pretty/postfix-yield.rs
Normal file
15
tests/pretty/postfix-yield.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// This demonstrates a proposed alternate or additional option of having yield in postfix position.
|
||||||
|
//@ edition: 2024
|
||||||
|
//@ pp-exact
|
||||||
|
|
||||||
|
#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)]
|
||||||
|
|
||||||
|
use std::ops::{Coroutine, CoroutineState};
|
||||||
|
use std::pin::pin;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut gn = gen { yield 1; 2.yield; (1 + 2).yield; };
|
||||||
|
|
||||||
|
let mut coro =
|
||||||
|
pin!(#[coroutine] |_: i32| { let x = 1.yield; (x + 2).yield; });
|
||||||
|
}
|
34
tests/ui/coroutine/postfix-yield.rs
Normal file
34
tests/ui/coroutine/postfix-yield.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// This demonstrates a proposed alternate or additional option of having yield in postfix position.
|
||||||
|
|
||||||
|
//@ run-pass
|
||||||
|
//@ edition: 2024
|
||||||
|
|
||||||
|
#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)]
|
||||||
|
|
||||||
|
use std::ops::{Coroutine, CoroutineState};
|
||||||
|
use std::pin::pin;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// generators (i.e. yield doesn't return anything useful)
|
||||||
|
let mut gn = gen {
|
||||||
|
yield 1;
|
||||||
|
2.yield;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(gn.next(), Some(1));
|
||||||
|
assert_eq!(gn.next(), Some(2));
|
||||||
|
assert_eq!(gn.next(), None);
|
||||||
|
|
||||||
|
//coroutines (i.e. yield returns something useful)
|
||||||
|
let mut coro = pin!(
|
||||||
|
#[coroutine]
|
||||||
|
|_: i32| {
|
||||||
|
let x = 1.yield;
|
||||||
|
(x + 2).yield;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(coro.as_mut().resume(0), CoroutineState::Yielded(1));
|
||||||
|
assert_eq!(coro.as_mut().resume(2), CoroutineState::Yielded(4));
|
||||||
|
assert_eq!(coro.as_mut().resume(3), CoroutineState::Complete(()));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue