1
Fork 0

Preserve yield position during pretty printing

This commit is contained in:
Eric Holk 2025-03-12 16:27:52 -07:00
parent edf65e735c
commit 1c0916a2b3
No known key found for this signature in database
GPG key ID: F1A772BB658A63E1
12 changed files with 55 additions and 18 deletions

View file

@ -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(Option<P<Expr>>, 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,15 @@ pub enum MatchKind {
Postfix, Postfix,
} }
/// The kind of yield expression
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
pub enum YieldKind {
/// yield expr { ... }
Prefix,
/// expr.yield { ... }
Postfix,
}
/// 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 {

View file

@ -1813,7 +1813,7 @@ 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(expr, _) => {
visit_opt(expr, |expr| vis.visit_expr(expr)); visit_opt(expr, |expr| vis.visit_expr(expr));
} }
ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::Try(expr) => vis.visit_expr(expr),

View file

@ -182,7 +182,7 @@ 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)) | Yield(Some(e), _)
| Yeet(Some(e)) | Yeet(Some(e))
| Become(e) => { | Become(e) => {
expr = e; expr = e;
@ -217,7 +217,7 @@ 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) | Yield(None, _)
| Array(_) | Array(_)
| Call(_, _) | Call(_, _)
| MethodCall(_) | MethodCall(_)

View file

@ -1269,7 +1269,7 @@ 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(optional_expression, _) => {
visit_opt!(visitor, visit_expr, optional_expression); visit_opt!(visitor, visit_expr, optional_expression);
} }
ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),

View file

@ -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(opt_expr, _) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
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(

View file

@ -642,7 +642,7 @@ fn may_contain_yield_point(e: &ast::Expr) -> bool {
type Result = ControlFlow<()>; type Result = ControlFlow<()>;
fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> { fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> {
if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind { if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_, _) = e.kind {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {
visit::walk_expr(self, e) visit::walk_expr(self, e)

View file

@ -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(e, YieldKind::Prefix) => {
self.word("yield"); self.word("yield");
if let Some(expr) = e { if let Some(expr) = e {
@ -773,6 +773,16 @@ impl<'a> State<'a> {
); );
} }
} }
ast::ExprKind::Yield(e, YieldKind::Postfix) => {
// it's not possible to have a postfix yield with no expression.
let e = e.as_ref().unwrap();
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,

View file

@ -323,7 +323,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::While(_, _, _) | ExprKind::While(_, _, _)
| ExprKind::Yeet(_) | ExprKind::Yeet(_)
| ExprKind::Become(_) | ExprKind::Become(_)
| ExprKind::Yield(_) | ExprKind::Yield(_, _)
| ExprKind::UnsafeBinderCast(..) => {} | ExprKind::UnsafeBinderCast(..) => {}
} }
} }

View file

@ -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;
@ -1314,7 +1315,9 @@ impl<'a> Parser<'a> {
if self.eat_keyword(exp!(Yield)) { if self.eat_keyword(exp!(Yield)) {
let yield_span = self.prev_token.span; let yield_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::yield_expr, yield_span); self.psess.gated_spans.gate(sym::yield_expr, yield_span);
return Ok(self.mk_expr(yield_span, ExprKind::Yield(Some(self_arg)))); return Ok(
self.mk_expr(yield_span, ExprKind::Yield(Some(self_arg), YieldKind::Postfix))
);
} }
let fn_span_lo = self.token.span; let fn_span_lo = self.token.span;
@ -1891,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(self.parse_expr_opt()?, YieldKind::Prefix);
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);
@ -4045,7 +4048,7 @@ impl MutVisitor for CondChecker<'_> {
| ExprKind::MacCall(_) | ExprKind::MacCall(_)
| ExprKind::Struct(_) | ExprKind::Struct(_)
| ExprKind::Repeat(_, _) | ExprKind::Repeat(_, _)
| ExprKind::Yield(_) | ExprKind::Yield(_, _)
| ExprKind::Yeet(_) | ExprKind::Yeet(_)
| ExprKind::Become(_) | ExprKind::Become(_)
| ExprKind::IncludedBytes(_) | ExprKind::IncludedBytes(_)

View file

@ -485,7 +485,7 @@ 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(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 +515,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(None, _)
| ast::ExprKind::Underscore => false, | ast::ExprKind::Underscore => false,
} }
} }

View 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; });
}

View file

@ -23,8 +23,8 @@ fn main() {
let mut coro = pin!( let mut coro = pin!(
#[coroutine] #[coroutine]
|_: i32| { |_: i32| {
let x = yield 1; let x = 1.yield;
yield x + 2; (x + 2).yield;
} }
); );