From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_ast_pretty/src/lib.rs | 8 +- compiler/rustc_ast_pretty/src/pp.rs | 17 +- compiler/rustc_ast_pretty/src/pp/convenience.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 404 +++++++++++---------- .../rustc_ast_pretty/src/pprust/state/delimited.rs | 41 --- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 211 +++++++---- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 24 +- 7 files changed, 378 insertions(+), 329 deletions(-) delete mode 100644 compiler/rustc_ast_pretty/src/pprust/state/delimited.rs (limited to 'compiler/rustc_ast_pretty/src') diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 475bdb023..670f2a458 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,11 +1,9 @@ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -#![feature(associated_type_bounds)] #![feature(box_patterns)] -#![feature(with_negative_coherence)] #![recursion_limit = "256"] mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index 7ab8c3eab..96f5eff68 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -165,20 +165,20 @@ enum IndentStyle { } #[derive(Clone, Copy, Default, PartialEq)] -pub struct BreakToken { +pub(crate) struct BreakToken { offset: isize, blank_space: isize, pre_break: Option, } #[derive(Clone, Copy, PartialEq)] -pub struct BeginToken { +pub(crate) struct BeginToken { indent: IndentStyle, breaks: Breaks, } -#[derive(Clone, PartialEq)] -pub enum Token { +#[derive(PartialEq)] +pub(crate) enum Token { // In practice a string token contains either a `&'static str` or a // `String`. `Cow` is overkill for this because we never modify the data, // but it's more convenient than rolling our own more specialized type. @@ -229,7 +229,6 @@ pub struct Printer { last_printed: Option, } -#[derive(Clone)] struct BufEntry { token: Token, size: isize, @@ -251,16 +250,16 @@ impl Printer { } } - pub fn last_token(&self) -> Option<&Token> { + pub(crate) fn last_token(&self) -> Option<&Token> { self.last_token_still_buffered().or_else(|| self.last_printed.as_ref()) } - pub fn last_token_still_buffered(&self) -> Option<&Token> { + pub(crate) fn last_token_still_buffered(&self) -> Option<&Token> { self.buf.last().map(|last| &last.token) } /// Be very careful with this! - pub fn replace_last_token_still_buffered(&mut self, token: Token) { + pub(crate) fn replace_last_token_still_buffered(&mut self, token: Token) { self.buf.last_mut().unwrap().token = token; } @@ -314,7 +313,7 @@ impl Printer { } } - pub fn offset(&mut self, offset: isize) { + pub(crate) fn offset(&mut self, offset: isize) { if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() { token.offset += offset; } diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 93310dd45..c4c4fdce7 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -66,7 +66,7 @@ impl Printer { } } - pub fn hardbreak_tok_offset(off: isize) -> Token { + pub(crate) fn hardbreak_tok_offset(off: isize) -> Token { Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 48421ff71..d6c15ec35 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1,13 +1,17 @@ -mod delimited; +//! AST pretty printing. +//! +//! Note that HIR pretty printing is layered on top of this crate. + mod expr; mod item; use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::{self, Breaks}; +use crate::pprust::state::expr::FixupContext; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser; @@ -23,8 +27,6 @@ use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use std::borrow::Cow; use thin_vec::ThinVec; -pub use self::delimited::IterDelimited; - pub enum MacHeader<'a> { Path(&'a ast::Path), Keyword(&'static str), @@ -46,8 +48,7 @@ pub trait PpAnn { fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {} } -#[derive(Copy, Clone)] -pub struct NoAnn; +struct NoAnn; impl PpAnn for NoAnn {} @@ -64,11 +65,11 @@ impl<'a> Comments<'a> { } // FIXME: This shouldn't probably clone lmao - pub fn next(&self) -> Option { + fn next(&self) -> Option { self.comments.get(self.current).cloned() } - pub fn trailing_comment( + fn trailing_comment( &self, span: rustc_span::Span, next_pos: Option, @@ -95,7 +96,7 @@ pub struct State<'a> { ann: &'a (dyn PpAnn + 'a), } -pub(crate) const INDENT_UNIT: isize = 4; +const INDENT_UNIT: isize = 4; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments to copy forward. @@ -151,7 +152,7 @@ pub fn print_crate<'a>( /// Note: some old proc macros parse pretty-printed output, so changes here can /// break old code. For example: /// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,` -/// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)] +/// - #73345: `#[allow(unused)]` must be printed rather than `# [allow(unused)]` /// fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { use token::*; @@ -183,10 +184,10 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { // // FIXME: Incorrect cases: // - Let: `let(a, b) = (1, 2)` - (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false, + (Tok(Token { kind: Ident(..), .. }, _), Del(_, _, Parenthesis, _)) => false, // `#` + `[`: `#[attr]` - (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false, + (Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false, _ => true, } @@ -220,7 +221,7 @@ fn doc_comment_to_string( } } -pub fn literal_to_string(lit: token::Lit) -> String { +fn literal_to_string(lit: token::Lit) -> String { let token::Lit { kind, symbol, suffix } = lit; let mut out = match kind { token::Byte => format!("b'{symbol}'"), @@ -260,11 +261,17 @@ impl std::ops::DerefMut for State<'_> { } } +/// This trait is used for both AST and HIR pretty-printing. pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefMut { fn comments(&mut self) -> &mut Option>; - fn print_ident(&mut self, ident: Ident); + fn ann_post(&mut self, ident: Ident); fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool); + fn print_ident(&mut self, ident: Ident) { + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.ann_post(ident) + } + fn strsep( &mut self, sep: &'static str, @@ -401,15 +408,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } - fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { - self.print_token_literal(lit.as_token_lit(), lit.span) - } - - fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { - self.maybe_print_comment(span.lo()); - self.word(token_lit.to_string()) - } - fn print_string(&mut self, st: &str, style: ast::StrStyle) { let st = match style { ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()), @@ -420,30 +418,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.word(st) } - fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { - self.print_string(sym.as_str(), style); - } - fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } - fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) - } - fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) } - fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) - } - - fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { - self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) - } - fn print_either_attributes( &mut self, attrs: &[ast::Attribute], @@ -467,10 +449,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere printed } - fn print_attribute(&mut self, attr: &ast::Attribute) { - self.print_attribute_inline(attr, false) - } - fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) { if !is_inline { self.hardbreak_if_not_bol(); @@ -525,33 +503,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.end(); } - fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { - match item { - ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi), - ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit), - } - } - - fn print_meta_item(&mut self, item: &ast::MetaItem) { - self.ibox(INDENT_UNIT); - match &item.kind { - ast::MetaItemKind::Word => self.print_path(&item.path, false, 0), - ast::MetaItemKind::NameValue(value) => { - self.print_path(&item.path, false, 0); - self.space(); - self.word_space("="); - self.print_meta_item_lit(value); - } - ast::MetaItemKind::List(items) => { - self.print_path(&item.path, false, 0); - self.popen(); - self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i)); - self.pclose(); - } - } - self.end(); - } - /// This doesn't deserve to be called "pretty" printing, but it should be /// meaning-preserving. A quick hack that might help would be to look at the /// spans embedded in the TTs to decide where to put spaces and newlines. @@ -559,16 +510,17 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere /// appropriate macro, transcribe back into the grammar we just parsed from, /// and then pretty-print the resulting AST nodes (so, e.g., we print /// expression arguments as expressions). It can be done! I think. - fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) { + fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) -> Spacing { match tt { - TokenTree::Token(token, _) => { + TokenTree::Token(token, spacing) => { let token_str = self.token_to_string_ext(token, convert_dollar_crate); self.word(token_str); if let token::DocComment(..) = token.kind { self.hardbreak() } + *spacing } - TokenTree::Delimited(dspan, delim, tts) => { + TokenTree::Delimited(dspan, spacing, delim, tts) => { self.print_mac_common( None, false, @@ -578,6 +530,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere convert_dollar_crate, dspan.entire(), ); + spacing.close } } } @@ -585,9 +538,20 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) { let mut iter = tts.trees().peekable(); while let Some(tt) = iter.next() { - self.print_tt(tt, convert_dollar_crate); + let spacing = self.print_tt(tt, convert_dollar_crate); if let Some(next) = iter.peek() { - if space_between(tt, next) { + // Should we print a space after `tt`? There are two guiding + // factors. + // - `spacing` is the more important and accurate one. Most + // tokens have good spacing information, and + // `Joint`/`JointHidden` get used a lot. + // - `space_between` is the backup. Code produced by proc + // macros has worse spacing information, with no + // `JointHidden` usage and too much `Alone` usage, which + // would result in over-spaced output such as + // `( x () , y . z )`. `space_between` avoids some of the + // excess whitespace. + if spacing == Spacing::Alone && space_between(tt, next) { self.space(); } } @@ -825,7 +789,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } token::Eof => "".into(), - token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(), + token::Interpolated(ref nt) => self.nonterminal_to_string(&nt.0).into(), } } @@ -843,37 +807,18 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_type(ty)) } - fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { - Self::to_string(|s| s.print_type_bounds(bounds)) - } - - fn where_bound_predicate_to_string( - &self, - where_bound_predicate: &ast::WhereBoundPredicate, - ) -> String { - Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate)) - } - fn pat_to_string(&self, pat: &ast::Pat) -> String { Self::to_string(|s| s.print_pat(pat)) } fn expr_to_string(&self, e: &ast::Expr) -> String { - Self::to_string(|s| s.print_expr(e)) + Self::to_string(|s| s.print_expr(e, FixupContext::default())) } fn meta_item_lit_to_string(&self, lit: &ast::MetaItemLit) -> String { Self::to_string(|s| s.print_meta_item_lit(lit)) } - fn tt_to_string(&self, tt: &TokenTree) -> String { - Self::to_string(|s| s.print_tt(tt, false)) - } - - fn tts_to_string(&self, tokens: &TokenStream) -> String { - Self::to_string(|s| s.print_tts(tokens, false)) - } - fn stmt_to_string(&self, stmt: &ast::Stmt) -> String { Self::to_string(|s| s.print_stmt(stmt)) } @@ -882,26 +827,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere Self::to_string(|s| s.print_item(i)) } - fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String { - Self::to_string(|s| s.print_assoc_item(i)) - } - - fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String { - Self::to_string(|s| s.print_foreign_item(i)) - } - - fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String { - Self::to_string(|s| s.print_generic_params(generic_params)) - } - fn path_to_string(&self, p: &ast::Path) -> String { Self::to_string(|s| s.print_path(p, false, 0)) } - fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { - Self::to_string(|s| s.print_path_segment(p, false)) - } - fn vis_to_string(&self, v: &ast::Visibility) -> String { Self::to_string(|s| s.print_visibility(v)) } @@ -916,22 +845,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere }) } - fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { - Self::to_string(|s| s.print_meta_list_item(li)) - } - fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String { Self::to_string(|s| s.print_attr_item(ai, ai.path.span)) } - fn attribute_to_string(&self, attr: &ast::Attribute) -> String { - Self::to_string(|s| s.print_attribute(attr)) - } - - fn param_to_string(&self, arg: &ast::Param) -> String { - Self::to_string(|s| s.print_param(arg, false)) - } - fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { let mut printer = State::new(); f(&mut printer); @@ -944,9 +861,8 @@ impl<'a> PrintState<'a> for State<'a> { &mut self.comments } - fn print_ident(&mut self, ident: Ident) { - self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); - self.ann.post(self, AnnNode::Ident(&ident)) + fn ann_post(&mut self, ident: Ident) { + self.ann.post(self, AnnNode::Ident(&ident)); } fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { @@ -979,13 +895,8 @@ impl<'a> State<'a> { State { s: pp::Printer::new(), comments: None, ann: &NoAnn } } - pub(crate) fn commasep_cmnt( - &mut self, - b: Breaks, - elts: &[T], - mut op: F, - mut get_span: G, - ) where + fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) + where F: FnMut(&mut State<'_>, &T), G: FnMut(&T) -> rustc_span::Span, { @@ -1005,8 +916,8 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) { - self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span) + fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) { + self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e, FixupContext::default()), |e| e.span) } pub fn print_opt_lifetime(&mut self, lifetime: &Option) { @@ -1043,7 +954,7 @@ impl<'a> State<'a> { match generic_arg { GenericArg::Lifetime(lt) => self.print_lifetime(*lt), GenericArg::Type(ty) => self.print_type(ty), - GenericArg::Const(ct) => self.print_expr(&ct.value), + GenericArg::Const(ct) => self.print_expr(&ct.value, FixupContext::default()), } } @@ -1078,11 +989,11 @@ impl<'a> State<'a> { } ast::TyKind::AnonStruct(fields) => { self.head("struct"); - self.print_record_struct_body(&fields, ty.span); + self.print_record_struct_body(fields, ty.span); } ast::TyKind::AnonUnion(fields) => { self.head("union"); - self.print_record_struct_body(&fields, ty.span); + self.print_record_struct_body(fields, ty.span); } ast::TyKind::Paren(typ) => { self.popen(); @@ -1110,12 +1021,12 @@ impl<'a> State<'a> { self.word("["); self.print_type(ty); self.word("; "); - self.print_expr(&length.value); + self.print_expr(&length.value, FixupContext::default()); self.word("]"); } ast::TyKind::Typeof(e) => { self.word("typeof("); - self.print_expr(&e.value); + self.print_expr(&e.value, FixupContext::default()); self.word(")"); } ast::TyKind::Infer => { @@ -1156,7 +1067,7 @@ impl<'a> State<'a> { self.print_trait_ref(&t.trait_ref) } - pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) { + fn print_stmt(&mut self, st: &ast::Stmt) { self.maybe_print_comment(st.span.lo()); match &st.kind { ast::StmtKind::Local(loc) => { @@ -1171,7 +1082,7 @@ impl<'a> State<'a> { if let Some((init, els)) = loc.kind.init_else_opt() { self.nbsp(); self.word_space("="); - self.print_expr(init); + self.print_expr(init, FixupContext::default()); if let Some(els) = els { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); @@ -1185,14 +1096,14 @@ impl<'a> State<'a> { ast::StmtKind::Item(item) => self.print_item(item), ast::StmtKind::Expr(expr) => { self.space_if_not_bol(); - self.print_expr_outer_attr_style(expr, false); + self.print_expr_outer_attr_style(expr, false, FixupContext::default()); if classify::expr_requires_semi_to_be_stmt(expr) { self.word(";"); } } ast::StmtKind::Semi(expr) => { self.space_if_not_bol(); - self.print_expr_outer_attr_style(expr, false); + self.print_expr_outer_attr_style(expr, false, FixupContext::default()); self.word(";"); } ast::StmtKind::Empty => { @@ -1211,19 +1122,19 @@ impl<'a> State<'a> { self.maybe_print_trailing_comment(st.span, None) } - pub(crate) fn print_block(&mut self, blk: &ast::Block) { + fn print_block(&mut self, blk: &ast::Block) { self.print_block_with_attrs(blk, &[]) } - pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) { + fn print_block_unclosed_indent(&mut self, blk: &ast::Block) { self.print_block_maybe_unclosed(blk, &[], false) } - pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) { + fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) { self.print_block_maybe_unclosed(blk, attrs, true) } - pub(crate) fn print_block_maybe_unclosed( + fn print_block_maybe_unclosed( &mut self, blk: &ast::Block, attrs: &[ast::Attribute], @@ -1244,7 +1155,7 @@ impl<'a> State<'a> { ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => { self.maybe_print_comment(st.span.lo()); self.space_if_not_bol(); - self.print_expr_outer_attr_style(expr, false); + self.print_expr_outer_attr_style(expr, false, FixupContext::default()); self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi())); } _ => self.print_stmt(st), @@ -1257,16 +1168,44 @@ impl<'a> State<'a> { } /// Print a `let pat = expr` expression. - pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { + /// + /// Parentheses are inserted surrounding `expr` if a round-trip through the + /// parser would otherwise work out the wrong way in a condition position. + /// + /// For example each of the following would mean the wrong thing without + /// parentheses. + /// + /// ```ignore (illustrative) + /// if let _ = (Struct {}) {} + /// + /// if let _ = (true && false) {} + /// ``` + /// + /// In a match guard, the second case still requires parens, but the first + /// case no longer does because anything until `=>` is considered part of + /// the match guard expression. Parsing of the expression is not terminated + /// by `{` in that position. + /// + /// ```ignore (illustrative) + /// match () { + /// () if let _ = Struct {} => {} + /// () if let _ = (true && false) => {} + /// } + /// ``` + fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, fixup: FixupContext) { self.word("let "); self.print_pat(pat); self.space(); self.word_space("="); - let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); - self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) + self.print_expr_cond_paren( + expr, + fixup.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr) + || parser::needs_par_as_let_scrutinee(expr.precedence().order()), + FixupContext::default(), + ); } - pub(crate) fn print_mac(&mut self, m: &ast::MacCall) { + fn print_mac(&mut self, m: &ast::MacCall) { self.print_mac_common( Some(MacHeader::Path(&m.path)), true, @@ -1310,7 +1249,7 @@ impl<'a> State<'a> { print_reg_or_class(s, reg); s.pclose(); s.space(); - s.print_expr(expr); + s.print_expr(expr, FixupContext::default()); } InlineAsmOperand::Out { reg, late, expr } => { s.word(if *late { "lateout" } else { "out" }); @@ -1319,7 +1258,7 @@ impl<'a> State<'a> { s.pclose(); s.space(); match expr { - Some(expr) => s.print_expr(expr), + Some(expr) => s.print_expr(expr, FixupContext::default()), None => s.word("_"), } } @@ -1329,7 +1268,7 @@ impl<'a> State<'a> { print_reg_or_class(s, reg); s.pclose(); s.space(); - s.print_expr(expr); + s.print_expr(expr, FixupContext::default()); } InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { s.word(if *late { "inlateout" } else { "inout" }); @@ -1337,18 +1276,18 @@ impl<'a> State<'a> { print_reg_or_class(s, reg); s.pclose(); s.space(); - s.print_expr(in_expr); + s.print_expr(in_expr, FixupContext::default()); s.space(); s.word_space("=>"); match out_expr { - Some(out_expr) => s.print_expr(out_expr), + Some(out_expr) => s.print_expr(out_expr, FixupContext::default()), None => s.word("_"), } } InlineAsmOperand::Const { anon_const } => { s.word("const"); s.space(); - s.print_expr(&anon_const.value); + s.print_expr(&anon_const.value, FixupContext::default()); } InlineAsmOperand::Sym { sym } => { s.word("sym"); @@ -1407,7 +1346,7 @@ impl<'a> State<'a> { self.pclose(); } - pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) { + fn print_local_decl(&mut self, loc: &ast::Local) { self.print_pat(&loc.pat); if let Some(ty) = &loc.ty { self.word_space(":"); @@ -1415,7 +1354,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_name(&mut self, name: Symbol) { + fn print_name(&mut self, name: Symbol) { self.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) } @@ -1439,13 +1378,14 @@ impl<'a> State<'a> { } } - pub(crate) fn print_pat(&mut self, pat: &ast::Pat) { + fn print_pat(&mut self, pat: &ast::Pat) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match &pat.kind { PatKind::Wild => self.word("_"), + PatKind::Never => self.word("!"), PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => { if *by_ref == ByRef::Yes { self.word_nbsp("ref"); @@ -1541,10 +1481,10 @@ impl<'a> State<'a> { self.print_pat(inner); } } - PatKind::Lit(e) => self.print_expr(e), + PatKind::Lit(e) => self.print_expr(e, FixupContext::default()), PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => { if let Some(e) = begin { - self.print_expr(e); + self.print_expr(e, FixupContext::default()); } match end_kind { RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."), @@ -1552,7 +1492,7 @@ impl<'a> State<'a> { RangeEnd::Excluded => self.word(".."), } if let Some(e) = end { - self.print_expr(e); + self.print_expr(e, FixupContext::default()); } } PatKind::Slice(elts) => { @@ -1592,9 +1532,18 @@ impl<'a> State<'a> { } } - pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) { - if asyncness.is_async() { - self.word_nbsp("async"); + fn print_coroutine_kind(&mut self, coroutine_kind: ast::CoroutineKind) { + match coroutine_kind { + ast::CoroutineKind::Gen { .. } => { + self.word_nbsp("gen"); + } + ast::CoroutineKind::Async { .. } => { + self.word_nbsp("async"); + } + ast::CoroutineKind::AsyncGen { .. } => { + self.word_nbsp("async"); + self.word_nbsp("gen"); + } } } @@ -1618,7 +1567,7 @@ impl<'a> State<'a> { TraitBoundModifier::Maybe => { self.word("?"); } - TraitBoundModifier::MaybeConst => { + TraitBoundModifier::MaybeConst(_) => { self.word_space("~const"); } TraitBoundModifier::MaybeConstNegative => { @@ -1637,23 +1586,25 @@ impl<'a> State<'a> { } } - pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) { + fn print_lifetime(&mut self, lifetime: ast::Lifetime) { self.print_name(lifetime.ident.name) } - pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { + fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { for (i, bound) in bounds.iter().enumerate() { if i != 0 { self.word(" + "); } match bound { ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt), - _ => panic!(), + _ => { + panic!("expected a lifetime bound, found a trait bound") + } } } } - pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) { + fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) { if generic_params.is_empty() { return; } @@ -1697,7 +1648,7 @@ impl<'a> State<'a> { if let Some(default) = default { s.space(); s.word_space("="); - s.print_expr(&default.value); + s.print_expr(&default.value, FixupContext::default()); } } } @@ -1717,12 +1668,12 @@ impl<'a> State<'a> { } } - pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { + fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { self.print_mutability(mt.mutbl, print_const); self.print_type(&mt.ty) } - pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) { + fn print_param(&mut self, input: &ast::Param, is_closure: bool) { self.ibox(INDENT_UNIT); self.print_outer_attributes_inline(&input.attrs); @@ -1750,7 +1701,7 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { + fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { if let ast::FnRetTy::Ty(ty) = fn_ret_ty { self.space_if_not_bol(); self.ibox(INDENT_UNIT); @@ -1761,7 +1712,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_ty_fn( + fn print_ty_fn( &mut self, ext: ast::Extern, unsafety: ast::Unsafe, @@ -1785,9 +1736,9 @@ impl<'a> State<'a> { self.end(); } - pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) { + fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); - self.print_asyncness(header.asyncness); + header.coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind)); self.print_unsafety(header.unsafety); match header.ext { @@ -1805,24 +1756,109 @@ impl<'a> State<'a> { self.word("fn") } - pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) { + fn print_unsafety(&mut self, s: ast::Unsafe) { match s { ast::Unsafe::No => {} ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"), } } - pub(crate) fn print_constness(&mut self, s: ast::Const) { + fn print_constness(&mut self, s: ast::Const) { match s { ast::Const::No => {} ast::Const::Yes(_) => self.word_nbsp("const"), } } - pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) { + fn print_is_auto(&mut self, s: ast::IsAuto) { match s { ast::IsAuto::Yes => self.word_nbsp("auto"), ast::IsAuto::No => {} } } + + fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { + self.print_token_literal(lit.as_token_lit(), lit.span) + } + + fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { + self.maybe_print_comment(span.lo()); + self.word(token_lit.to_string()) + } + + fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { + self.print_string(sym.as_str(), style); + } + + fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { + self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) + } + + fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { + self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) + } + + fn print_attribute(&mut self, attr: &ast::Attribute) { + self.print_attribute_inline(attr, false) + } + + fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { + match item { + ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi), + ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit), + } + } + + fn print_meta_item(&mut self, item: &ast::MetaItem) { + self.ibox(INDENT_UNIT); + match &item.kind { + ast::MetaItemKind::Word => self.print_path(&item.path, false, 0), + ast::MetaItemKind::NameValue(value) => { + self.print_path(&item.path, false, 0); + self.space(); + self.word_space("="); + self.print_meta_item_lit(value); + } + ast::MetaItemKind::List(items) => { + self.print_path(&item.path, false, 0); + self.popen(); + self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i)); + self.pclose(); + } + } + self.end(); + } + + pub(crate) fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { + Self::to_string(|s| s.print_type_bounds(bounds)) + } + + pub(crate) fn where_bound_predicate_to_string( + &self, + where_bound_predicate: &ast::WhereBoundPredicate, + ) -> String { + Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate)) + } + + pub(crate) fn tt_to_string(&self, tt: &TokenTree) -> String { + Self::to_string(|s| { + s.print_tt(tt, false); + }) + } + + pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String { + Self::to_string(|s| s.print_tts(tokens, false)) + } + + pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { + Self::to_string(|s| s.print_path_segment(p, false)) + } + + pub(crate) fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { + Self::to_string(|s| s.print_meta_list_item(li)) + } + + pub(crate) fn attribute_to_string(&self, attr: &ast::Attribute) -> String { + Self::to_string(|s| s.print_attribute(attr)) + } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs b/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs deleted file mode 100644 index fe0640baa..000000000 --- a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::iter::Peekable; -use std::mem; -use std::ops::Deref; - -pub struct Delimited { - is_first: bool, - iter: Peekable, -} - -pub trait IterDelimited: Iterator + Sized { - fn delimited(self) -> Delimited { - Delimited { is_first: true, iter: self.peekable() } - } -} - -impl IterDelimited for I {} - -pub struct IteratorItem { - value: T, - pub is_first: bool, - pub is_last: bool, -} - -impl Iterator for Delimited { - type Item = IteratorItem; - - fn next(&mut self) -> Option { - let value = self.iter.next()?; - let is_first = mem::replace(&mut self.is_first, false); - let is_last = self.iter.peek().is_none(); - Some(IteratorItem { value, is_first, is_last }) - } -} - -impl Deref for IteratorItem { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.value - } -} diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index edbc35003..f5ffcddb8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -1,6 +1,6 @@ use crate::pp::Breaks::Inconsistent; -use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT}; - +use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; +use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::util::literal::escape_byte_str_symbol; @@ -12,6 +12,19 @@ use rustc_ast::{ }; use std::fmt::Write; +#[derive(Copy, Clone, Debug)] +pub(crate) struct FixupContext { + pub parenthesize_exterior_struct_lit: bool, +} + +/// The default amount of fixing is minimal fixing. Fixups should be turned on +/// in a targetted fashion where needed. +impl Default for FixupContext { + fn default() -> Self { + FixupContext { parenthesize_exterior_struct_lit: false } + } +} + impl<'a> State<'a> { fn print_else(&mut self, els: Option<&ast::Expr>) { if let Some(_else) = els { @@ -55,21 +68,22 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) { - self.print_expr_cond_paren(expr, expr.precedence().order() < prec) + fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8, fixup: FixupContext) { + self.print_expr_cond_paren(expr, expr.precedence().order() < prec, fixup); } /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in /// `if cond { ... }`. fn print_expr_as_cond(&mut self, expr: &ast::Expr) { - self.print_expr_cond_paren(expr, Self::cond_needs_par(expr)) + let fixup = FixupContext { parenthesize_exterior_struct_lit: true }; + self.print_expr_cond_paren(expr, Self::cond_needs_par(expr), fixup) } /// Does `expr` need parentheses when printed in a condition position? /// /// These cases need parens due to the parse error observed in #26461: `if return {}` /// parses as the erroneous construct `if (return {})`, not `if (return) {}`. - pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool { + fn cond_needs_par(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Break(..) | ast::ExprKind::Closure(..) @@ -80,11 +94,32 @@ impl<'a> State<'a> { } /// Prints `expr` or `(expr)` when `needs_par` holds. - pub(super) fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) { + pub(super) fn print_expr_cond_paren( + &mut self, + expr: &ast::Expr, + needs_par: bool, + fixup: FixupContext, + ) { if needs_par { self.popen(); } - self.print_expr(expr); + + // If we are surrounding the whole cond in parentheses, such as: + // + // if (return Struct {}) {} + // + // then there is no need for parenthesizing the individual struct + // expressions within. On the other hand if the whole cond is not + // parenthesized, then print_expr must parenthesize exterior struct + // literals. + // + // if x == (Struct {}) {} + // + let fixup = FixupContext { + parenthesize_exterior_struct_lit: fixup.parenthesize_exterior_struct_lit && !needs_par, + }; + self.print_expr(expr, fixup); + if needs_par { self.pclose(); } @@ -111,7 +146,7 @@ impl<'a> State<'a> { self.ibox(0); self.print_block_with_attrs(block, attrs); } else { - self.print_expr(&expr.value); + self.print_expr(&expr.value, FixupContext::default()); } self.end(); } @@ -119,9 +154,9 @@ impl<'a> State<'a> { fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) { self.ibox(INDENT_UNIT); self.word("["); - self.print_expr(element); + self.print_expr(element, FixupContext::default()); self.word_space(";"); - self.print_expr(&count.value); + self.print_expr(&count.value, FixupContext::default()); self.word("]"); self.end(); } @@ -149,18 +184,20 @@ impl<'a> State<'a> { return; } self.cbox(0); - for field in fields.iter().delimited() { + for (pos, field) in fields.iter().with_position() { + let is_first = matches!(pos, Position::First | Position::Only); + let is_last = matches!(pos, Position::Last | Position::Only); self.maybe_print_comment(field.span.hi()); self.print_outer_attributes(&field.attrs); - if field.is_first { + if is_first { self.space_if_not_bol(); } if !field.is_shorthand { self.print_ident(field.ident); self.word_nbsp(":"); } - self.print_expr(&field.expr); - if !field.is_last || has_rest { + self.print_expr(&field.expr, FixupContext::default()); + if !is_last || has_rest { self.word_space(","); } else { self.trailing_comma_or_space(); @@ -172,7 +209,7 @@ impl<'a> State<'a> { } self.word(".."); if let ast::StructRest::Base(expr) = rest { - self.print_expr(expr); + self.print_expr(expr, FixupContext::default()); } self.space(); } @@ -190,13 +227,13 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_call(&mut self, func: &ast::Expr, args: &[P]) { + fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { let prec = match func.kind { ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, _ => parser::PREC_POSTFIX, }; - self.print_expr_maybe_paren(func, prec); + self.print_expr_maybe_paren(func, prec, fixup); self.print_call_post(args) } @@ -205,8 +242,9 @@ impl<'a> State<'a> { segment: &ast::PathSegment, receiver: &ast::Expr, base_args: &[P], + fixup: FixupContext, ) { - self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup); self.word("."); self.print_ident(segment.ident); if let Some(args) = &segment.args { @@ -215,7 +253,13 @@ impl<'a> State<'a> { self.print_call_post(base_args) } - fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr) { + fn print_expr_binary( + &mut self, + op: ast::BinOp, + lhs: &ast::Expr, + rhs: &ast::Expr, + fixup: FixupContext, + ) { let assoc_op = AssocOp::from_ast_binop(op.node); let prec = assoc_op.precedence() as i8; let fixity = assoc_op.fixity(); @@ -251,15 +295,15 @@ impl<'a> State<'a> { _ => left_prec, }; - self.print_expr_maybe_paren(lhs, left_prec); + self.print_expr_maybe_paren(lhs, left_prec, fixup); self.space(); - self.word_space(op.node.to_string()); - self.print_expr_maybe_paren(rhs, right_prec) + self.word_space(op.node.as_str()); + self.print_expr_maybe_paren(rhs, right_prec, fixup) } - fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.word(ast::UnOp::to_string(op)); - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) { + self.word(op.as_str()); + self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup) } fn print_expr_addr_of( @@ -267,6 +311,7 @@ impl<'a> State<'a> { kind: ast::BorrowKind, mutability: ast::Mutability, expr: &ast::Expr, + fixup: FixupContext, ) { self.word("&"); match kind { @@ -276,14 +321,19 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup) } - pub fn print_expr(&mut self, expr: &ast::Expr) { - self.print_expr_outer_attr_style(expr, true) + pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) { + self.print_expr_outer_attr_style(expr, true, fixup) } - pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) { + pub(super) fn print_expr_outer_attr_style( + &mut self, + expr: &ast::Expr, + is_inline: bool, + fixup: FixupContext, + ) { self.maybe_print_comment(expr.span.lo()); let attrs = &expr.attrs; @@ -312,19 +362,19 @@ impl<'a> State<'a> { self.print_expr_tup(exprs); } ast::ExprKind::Call(func, args) => { - self.print_expr_call(func, args); + self.print_expr_call(func, args, fixup); } ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => { - self.print_expr_method_call(seg, receiver, args); + self.print_expr_method_call(seg, receiver, args, fixup); } ast::ExprKind::Binary(op, lhs, rhs) => { - self.print_expr_binary(*op, lhs, rhs); + self.print_expr_binary(*op, lhs, rhs, fixup); } ast::ExprKind::Unary(op, expr) => { - self.print_expr_unary(*op, expr); + self.print_expr_unary(*op, expr, fixup); } ast::ExprKind::AddrOf(k, m, expr) => { - self.print_expr_addr_of(*k, *m, expr); + self.print_expr_addr_of(*k, *m, expr, fixup); } ast::ExprKind::Lit(token_lit) => { self.print_token_literal(*token_lit, expr.span); @@ -335,7 +385,7 @@ impl<'a> State<'a> { } ast::ExprKind::Cast(expr, ty) => { let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(expr, prec); + self.print_expr_maybe_paren(expr, prec, fixup); self.space(); self.word_space("as"); self.print_type(ty); @@ -343,7 +393,7 @@ impl<'a> State<'a> { ast::ExprKind::Type(expr, ty) => { self.word("type_ascribe!("); self.ibox(0); - self.print_expr(expr); + self.print_expr(expr, FixupContext::default()); self.word(","); self.space_if_not_bol(); @@ -353,7 +403,7 @@ impl<'a> State<'a> { self.word(")"); } ast::ExprKind::Let(pat, scrutinee, _, _) => { - self.print_let(pat, scrutinee); + self.print_let(pat, scrutinee, fixup); } ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()), ast::ExprKind::While(test, blk, opt_label) => { @@ -411,7 +461,7 @@ impl<'a> State<'a> { binder, capture_clause, constness, - asyncness, + coroutine_kind, movability, fn_decl, body, @@ -421,12 +471,12 @@ impl<'a> State<'a> { self.print_closure_binder(binder); self.print_constness(*constness); self.print_movability(*movability); - self.print_asyncness(*asyncness); + coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind)); self.print_capture_clause(*capture_clause); self.print_fn_params_and_ret(fn_decl, true); self.space(); - self.print_expr(body); + self.print_expr(body, FixupContext::default()); self.end(); // need to close a box // a box will be closed by print_expr, but we didn't want an overall @@ -454,33 +504,33 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Await(expr, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1, fixup); self.space(); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_maybe_paren(rhs, prec, fixup); } ast::ExprKind::AssignOp(op, lhs, rhs) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_maybe_paren(lhs, prec + 1, fixup); self.space(); - self.word(op.node.to_string()); + self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_maybe_paren(rhs, prec, fixup); } ast::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); self.word("."); self.print_ident(*ident); } ast::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); self.word("["); - self.print_expr(index); + self.print_expr(index, FixupContext::default()); self.word("]"); } ast::ExprKind::Range(start, end, limits) => { @@ -490,14 +540,14 @@ impl<'a> State<'a> { // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) let fake_prec = AssocOp::LOr.precedence() as i8; if let Some(e) = start { - self.print_expr_maybe_paren(e, fake_prec); + self.print_expr_maybe_paren(e, fake_prec, fixup); } match limits { ast::RangeLimits::HalfOpen => self.word(".."), ast::RangeLimits::Closed => self.word("..="), } if let Some(e) = end { - self.print_expr_maybe_paren(e, fake_prec); + self.print_expr_maybe_paren(e, fake_prec, fixup); } } ast::ExprKind::Underscore => self.word("_"), @@ -511,7 +561,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup); } } ast::ExprKind::Continue(opt_label) => { @@ -525,7 +575,7 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup); } } ast::ExprKind::Yeet(result) => { @@ -534,13 +584,13 @@ impl<'a> State<'a> { self.word("yeet"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup); } } ast::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_maybe_paren(result, parser::PREC_JUMP); + self.print_expr_maybe_paren(result, parser::PREC_JUMP, fixup); } ast::ExprKind::InlineAsm(a) => { // FIXME: This should have its own syntax, distinct from a macro invocation. @@ -555,7 +605,7 @@ impl<'a> State<'a> { self.word(reconstruct_format_args_template_string(&fmt.template)); for arg in fmt.arguments.all_args() { self.word_space(","); - self.print_expr(&arg.expr); + self.print_expr(&arg.expr, FixupContext::default()); } self.end(); self.pclose(); @@ -582,7 +632,7 @@ impl<'a> State<'a> { ast::ExprKind::MacCall(m) => self.print_mac(m), ast::ExprKind::Paren(e) => { self.popen(); - self.print_expr(e); + self.print_expr(e, FixupContext::default()); self.pclose(); } ast::ExprKind::Yield(e) => { @@ -590,11 +640,11 @@ impl<'a> State<'a> { if let Some(expr) = e { self.space(); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup); } } ast::ExprKind::Try(e) => { - self.print_expr_maybe_paren(e, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { @@ -626,31 +676,36 @@ impl<'a> State<'a> { self.space(); if let Some(e) = &arm.guard { self.word_space("if"); - self.print_expr(e); + self.print_expr(e, FixupContext::default()); self.space(); } - self.word_space("=>"); - match &arm.body.kind { - ast::ExprKind::Block(blk, opt_label) => { - if let Some(label) = opt_label { - self.print_ident(label.ident); - self.word_space(":"); - } + if let Some(body) = &arm.body { + self.word_space("=>"); + + match &body.kind { + ast::ExprKind::Block(blk, opt_label) => { + if let Some(label) = opt_label { + self.print_ident(label.ident); + self.word_space(":"); + } - // The block will close the pattern's ibox. - self.print_block_unclosed_indent(blk); + // The block will close the pattern's ibox. + self.print_block_unclosed_indent(blk); - // If it is a user-provided unsafe block, print a comma after it. - if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { + // If it is a user-provided unsafe block, print a comma after it. + if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { + self.word(","); + } + } + _ => { + self.end(); // Close the ibox for the pattern. + self.print_expr(body, FixupContext::default()); self.word(","); } } - _ => { - self.end(); // Close the ibox for the pattern. - self.print_expr(&arm.body); - self.word(","); - } + } else { + self.word(","); } self.end(); // Close enclosing cbox. } @@ -679,7 +734,7 @@ impl<'a> State<'a> { } } -pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String { +fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String { let mut template = "\"".to_string(); for piece in pieces { match piece { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 3393f034b..405ccc722 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -1,8 +1,9 @@ use crate::pp::Breaks::Inconsistent; -use crate::pprust::state::delimited::IterDelimited; +use crate::pprust::state::expr::FixupContext; use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use ast::StaticItem; +use itertools::{Itertools, Position}; use rustc_ast as ast; use rustc_ast::GenericBound; use rustc_ast::ModKind; @@ -20,7 +21,7 @@ impl<'a> State<'a> { } } - pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) { + fn print_foreign_item(&mut self, item: &ast::ForeignItem) { let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); @@ -97,7 +98,7 @@ impl<'a> State<'a> { self.end(); // end the head-ibox if let Some(body) = body { self.word_space("="); - self.print_expr(body); + self.print_expr(body, FixupContext::default()); } self.print_where_clause(&generics.where_clause); self.word(";"); @@ -368,7 +369,7 @@ impl<'a> State<'a> { self.nbsp(); if !bounds.is_empty() { self.word_nbsp("="); - self.print_type_bounds(&bounds); + self.print_type_bounds(bounds); } self.print_where_clause(&generics.where_clause); self.word(";"); @@ -499,7 +500,7 @@ impl<'a> State<'a> { self.end(); self.end(); // Close the outer-box. } - ast::VariantData::Struct(fields, ..) => { + ast::VariantData::Struct { fields, .. } => { self.print_where_clause(&generics.where_clause); self.print_record_struct_body(fields, span); } @@ -514,11 +515,11 @@ impl<'a> State<'a> { if let Some(d) = &v.disr_expr { self.space(); self.word_space("="); - self.print_expr(&d.value) + self.print_expr(&d.value, FixupContext::default()) } } - pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) { + fn print_assoc_item(&mut self, item: &ast::AssocItem) { let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); @@ -621,7 +622,7 @@ impl<'a> State<'a> { self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates); } - pub(crate) fn print_where_clause_parts( + fn print_where_clause_parts( &mut self, has_where_token: bool, predicates: &[ast::WherePredicate], @@ -668,7 +669,7 @@ impl<'a> State<'a> { } } - pub fn print_where_bound_predicate( + pub(crate) fn print_where_bound_predicate( &mut self, where_bound_predicate: &ast::WhereBoundPredicate, ) { @@ -712,9 +713,10 @@ impl<'a> State<'a> { self.word("{"); self.zerobreak(); self.ibox(0); - for use_tree in items.iter().delimited() { + for (pos, use_tree) in items.iter().with_position() { + let is_last = matches!(pos, Position::Last | Position::Only); self.print_use_tree(&use_tree.0); - if !use_tree.is_last { + if !is_last { self.word(","); if let ast::UseTreeKind::Nested(_) = use_tree.0.kind { self.hardbreak(); -- cgit v1.2.3