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:
Matthias Krüger 2025-03-20 15:36:15 +01:00 committed by GitHub
commit d752721636
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 161 additions and 20 deletions

View file

@ -17,6 +17,7 @@ use rustc_ast::{
self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall,
MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind,
YieldKind,
};
use rustc_ast_pretty::pprust;
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);
}
// 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 mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
@ -1884,7 +1894,7 @@ impl<'a> Parser<'a> {
/// Parse `"yield" expr?`.
fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
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);
self.psess.gated_spans.gate(sym::yield_expr, span);
let expr = self.mk_expr(span, kind);