diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index d567c8dae43a4..ddce86f216538 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -148,7 +148,7 @@ pub enum Breaks { Inconsistent, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] enum IndentStyle { /// Vertically aligned under whatever column this block begins at. /// @@ -164,19 +164,20 @@ enum IndentStyle { Block { offset: isize }, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default, PartialEq)] pub struct BreakToken { offset: isize, blank_space: isize, + pre_break: Option, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub struct BeginToken { indent: IndentStyle, breaks: Breaks, } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub 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, @@ -313,6 +314,12 @@ impl Printer { } } + pub fn offset(&mut self, offset: isize) { + if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() { + token.offset += offset; + } + } + fn check_stream(&mut self) { while self.right_total - self.left_total > self.space { if *self.scan_stack.front().unwrap() == self.buf.index_of_first() { @@ -391,7 +398,9 @@ impl Printer { if size > self.space { self.print_stack.push(PrintFrame::Broken { indent: self.indent, breaks: token.breaks }); self.indent = match token.indent { - IndentStyle::Block { offset } => (self.indent as isize + offset) as usize, + IndentStyle::Block { offset } => { + usize::try_from(self.indent as isize + offset).unwrap() + } IndentStyle::Visual => (MARGIN - self.space) as usize, }; } else { @@ -415,6 +424,9 @@ impl Printer { self.pending_indentation += token.blank_space; self.space -= token.blank_space; } else { + if let Some(pre_break) = token.pre_break { + self.out.push(pre_break); + } self.out.push('\n'); let indent = self.indent as isize + token.offset; self.pending_indentation = indent; diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs index 1b9ac705883af..785e6886d8a38 100644 --- a/compiler/rustc_ast_pretty/src/pp/convenience.rs +++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs @@ -3,20 +3,17 @@ use std::borrow::Cow; impl Printer { /// "raw box" - pub fn rbox(&mut self, indent: usize, breaks: Breaks) { - self.scan_begin(BeginToken { - indent: IndentStyle::Block { offset: indent as isize }, - breaks, - }) + pub fn rbox(&mut self, indent: isize, breaks: Breaks) { + self.scan_begin(BeginToken { indent: IndentStyle::Block { offset: indent }, breaks }) } /// Inconsistent breaking box - pub fn ibox(&mut self, indent: usize) { + pub fn ibox(&mut self, indent: isize) { self.rbox(indent, Breaks::Inconsistent) } /// Consistent breaking box - pub fn cbox(&mut self, indent: usize) { + pub fn cbox(&mut self, indent: isize) { self.rbox(indent, Breaks::Consistent) } @@ -25,7 +22,11 @@ impl Printer { } pub fn break_offset(&mut self, n: usize, off: isize) { - self.scan_break(BreakToken { offset: off, blank_space: n as isize }) + self.scan_break(BreakToken { + offset: off, + blank_space: n as isize, + ..BreakToken::default() + }); } pub fn end(&mut self) { @@ -66,12 +67,24 @@ impl Printer { } pub fn hardbreak_tok_offset(off: isize) -> Token { - Token::Break(BreakToken { offset: off, blank_space: SIZE_INFINITY }) + Token::Break(BreakToken { + offset: off, + blank_space: SIZE_INFINITY, + ..BreakToken::default() + }) + } + + pub fn trailing_comma(&mut self) { + self.scan_break(BreakToken { + blank_space: 1, + pre_break: Some(','), + ..BreakToken::default() + }); } } impl Token { pub fn is_hardbreak_tok(&self) -> bool { - matches!(self, Token::Break(BreakToken { offset: 0, blank_space: SIZE_INFINITY })) + *self == Printer::hardbreak_tok_offset(0) } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b575dc2196133..b2c62383fb69a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1,3 +1,4 @@ +mod delimited; mod expr; mod item; @@ -23,6 +24,8 @@ use rustc_span::{BytePos, FileName, Span}; use std::borrow::Cow; +pub use self::delimited::IterDelimited; + pub enum MacHeader<'a> { Path(&'a ast::Path), Keyword(&'static str), @@ -92,7 +95,7 @@ pub struct State<'a> { ann: &'a (dyn PpAnn + 'a), } -crate const INDENT_UNIT: usize = 4; +crate 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. diff --git a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs b/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs new file mode 100644 index 0000000000000..fe0640baaa1b0 --- /dev/null +++ b/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs @@ -0,0 +1,41 @@ +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 6a5bba30b8bca..44116fa76a0c1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -1,5 +1,5 @@ -use crate::pp::Breaks::{Consistent, Inconsistent}; -use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; +use crate::pp::Breaks::Inconsistent; +use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT}; use rustc_ast::ptr::P; use rustc_ast::util::parser::{self, AssocOp, Fixity}; @@ -117,38 +117,46 @@ impl<'a> State<'a> { } else { self.print_path(path, true, 0); } + self.nbsp(); self.word("{"); - self.commasep_cmnt( - Consistent, - fields, - |s, field| { - s.print_outer_attributes(&field.attrs); - s.ibox(INDENT_UNIT); - if !field.is_shorthand { - s.print_ident(field.ident); - s.word_space(":"); - } - s.print_expr(&field.expr); - s.end(); - }, - |f| f.span, - ); - match rest { - ast::StructRest::Base(_) | ast::StructRest::Rest(_) => { - self.ibox(INDENT_UNIT); - if !fields.is_empty() { - self.word(","); - self.space(); - } - self.word(".."); - if let ast::StructRest::Base(ref expr) = *rest { - self.print_expr(expr); - } - self.end(); + let has_rest = match rest { + ast::StructRest::Base(_) | ast::StructRest::Rest(_) => true, + ast::StructRest::None => false, + }; + if fields.is_empty() && !has_rest { + self.word("}"); + return; + } + self.cbox(0); + for field in fields.iter().delimited() { + self.maybe_print_comment(field.span.hi()); + self.print_outer_attributes(&field.attrs); + if field.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.word_space(","); + } else { + self.trailing_comma(); } - ast::StructRest::None if !fields.is_empty() => self.word(","), - _ => {} } + if has_rest { + if fields.is_empty() { + self.space(); + } + self.word(".."); + if let ast::StructRest::Base(expr) = rest { + self.print_expr(expr); + } + self.space(); + } + self.offset(-INDENT_UNIT); + self.end(); self.word("}"); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a47ebaf1237a1..13008a8337979 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -139,7 +139,7 @@ impl<'a> PrintState<'a> for State<'a> { } } -pub const INDENT_UNIT: usize = 4; +pub 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. diff --git a/src/test/pretty/ast-stmt-expr-attr.rs b/src/test/pretty/ast-stmt-expr-attr.rs index 2404b32194289..27c86ec22b84e 100644 --- a/src/test/pretty/ast-stmt-expr-attr.rs +++ b/src/test/pretty/ast-stmt-expr-attr.rs @@ -119,9 +119,9 @@ fn syntax() { let _ = #[attr] foo![#! [attr]]; let _ = #[attr] foo! {}; let _ = #[attr] foo! { #! [attr] }; - let _ = #[attr] Foo{bar: baz,}; - let _ = #[attr] Foo{..foo}; - let _ = #[attr] Foo{bar: baz, ..foo}; + let _ = #[attr] Foo { bar: baz }; + let _ = #[attr] Foo { ..foo }; + let _ = #[attr] Foo { bar: baz, ..foo }; let _ = #[attr] (0); { diff --git a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs index 87f525a6178e6..80f739f4f9e1a 100644 --- a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs +++ b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs @@ -8,9 +8,10 @@ struct C { #[allow()] const C: C = - C{ + C { #[cfg(debug_assertions)] field: 0, #[cfg(not(debug_assertions))] - field: 1,}; + field: 1, + }; diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 96bde96200af9..7ab22f1960c2d 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -90,9 +90,9 @@ struct Bar(()); fn _7() { #[rustc_dummy] - Foo{data: (),}; + Foo { data: () }; - let _ = #[rustc_dummy] Foo{data: (),}; + let _ = #[rustc_dummy] Foo { data: () }; } fn _8() { @@ -209,7 +209,7 @@ fn _11() { let mut x = 0; let _ = #[rustc_dummy] x = 15; let _ = #[rustc_dummy] x += 15; - let s = Foo{data: (),}; + let s = Foo { data: () }; let _ = #[rustc_dummy] s.data; let _ = (#[rustc_dummy] s).data; let t = Bar(()); @@ -235,9 +235,9 @@ fn _11() { let _ = #[rustc_dummy] expr_mac!(); let _ = #[rustc_dummy] expr_mac![]; let _ = #[rustc_dummy] expr_mac! {}; - let _ = #[rustc_dummy] Foo{data: (),}; - let _ = #[rustc_dummy] Foo{..s}; - let _ = #[rustc_dummy] Foo{data: (), ..s}; + let _ = #[rustc_dummy] Foo { data: () }; + let _ = #[rustc_dummy] Foo { ..s }; + let _ = #[rustc_dummy] Foo { data: (), ..s }; let _ = #[rustc_dummy] (0); } diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 004ab386b3ff0..57e5ab42f79d3 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -315,17 +315,17 @@ fn test_expr() { assert_eq!(stringify_expr!(mac! { ... }), "mac! { ... }"); // ExprKind::Struct - assert_eq!(stringify_expr!(Struct {}), "Struct{}"); // FIXME + assert_eq!(stringify_expr!(Struct {}), "Struct {}"); #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151 - assert_eq!(stringify_expr!(::Type {}), "::Type{}"); - assert_eq!(stringify_expr!(Struct { .. }), "Struct{..}"); // FIXME - assert_eq!(stringify_expr!(Struct { ..base }), "Struct{..base}"); // FIXME - assert_eq!(stringify_expr!(Struct { x }), "Struct{x,}"); - assert_eq!(stringify_expr!(Struct { x, .. }), "Struct{x, ..}"); - assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct{x, ..base}"); - assert_eq!(stringify_expr!(Struct { x: true }), "Struct{x: true,}"); - assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct{x: true, ..}"); - assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct{x: true, ..base}"); + assert_eq!(stringify_expr!(::Type {}), "::Type {}"); + assert_eq!(stringify_expr!(Struct { .. }), "Struct { .. }"); + assert_eq!(stringify_expr!(Struct { ..base }), "Struct { ..base }"); + assert_eq!(stringify_expr!(Struct { x }), "Struct { x }"); + assert_eq!(stringify_expr!(Struct { x, .. }), "Struct { x, .. }"); + assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct { x, ..base }"); + assert_eq!(stringify_expr!(Struct { x: true }), "Struct { x: true }"); + assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct { x: true, .. }"); + assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct { x: true, ..base }"); // ExprKind::Repeat assert_eq!(stringify_expr!([(); 0]), "[(); 0]"); diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr index 707b38cf37af0..49d72158e92ba 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr @@ -1,6 +1,6 @@ [$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit [$DIR/dbg-macro-expected-behavior.rs:21] a = Unit -[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point { +[$DIR/dbg-macro-expected-behavior.rs:27] Point { x: 42, y: 24 } = Point { x: 42, y: 24, }