summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_pretty/src/pprust/state.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_ast_pretty/src/pprust/state.rs
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ast_pretty/src/pprust/state.rs')
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs404
1 files changed, 220 insertions, 184 deletions
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<Comment> {
+ fn next(&self) -> Option<Comment> {
self.comments.get(self.current).cloned()
}
- pub fn trailing_comment(
+ fn trailing_comment(
&self,
span: rustc_span::Span,
next_pos: Option<BytePos>,
@@ -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<Target = pp::Printer> + std::ops::DerefMut {
fn comments(&mut self) -> &mut Option<Comments<'a>>;
- 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<T, F>(
&mut self,
sep: &'static str,
@@ -401,15 +408,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + 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<Target = pp::Printer> + 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<Target = pp::Printer> + 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<Target = pp::Printer> + 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<Target = pp::Printer> + 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<Target = pp::Printer> + std::ops::Dere
convert_dollar_crate,
dspan.entire(),
);
+ spacing.close
}
}
}
@@ -585,9 +538,20 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + 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<Target = pp::Printer> + std::ops::Dere
}
token::Eof => "<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<Target = pp::Printer> + 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<Target = pp::Printer> + 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<Target = pp::Printer> + 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<T, F, G>(
- &mut self,
- b: Breaks,
- elts: &[T],
- mut op: F,
- mut get_span: G,
- ) where
+ fn commasep_cmnt<T, F, G>(&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<ast::Expr>]) {
- self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
+ fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
+ 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<ast::Lifetime>) {
@@ -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))
+ }
}