1
Fork 0

Rollup merge of #91437 - dtolnay:emptybrace, r=nagisa

Pretty print empty blocks as {}

**Example:**

```rust
macro_rules! p {
    ($e:expr) => {
        println!("{}", stringify!($e));
    };
    ($i:item) => {
        println!("{}", stringify!($i));
    };
}

fn main() {
    p!(if true {});
    p!(struct S {});
}
```

**Before:**

```console
if true { }
struct S {
}
```

**After:**

```console
if true {}
struct S {}
```

This affects [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html), as well as ecosystem uses of stringify such as in [`anyhow::ensure!`](https://docs.rs/anyhow/1/anyhow/macro.ensure.html). Printing a `{ }` in today's heavily rustfmt'd world comes out looking jarring/sloppy.
This commit is contained in:
Matthias Krüger 2021-12-05 15:04:20 +01:00 committed by GitHub
commit a8f8f746fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 182 additions and 164 deletions

View file

@ -263,14 +263,17 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.strsep(",", false, b, elts, op) self.strsep(",", false, b, elts, op)
} }
fn maybe_print_comment(&mut self, pos: BytePos) { fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
let mut has_comment = false;
while let Some(ref cmnt) = self.next_comment() { while let Some(ref cmnt) = self.next_comment() {
if cmnt.pos < pos { if cmnt.pos < pos {
has_comment = true;
self.print_comment(cmnt); self.print_comment(cmnt);
} else { } else {
break; break;
} }
} }
has_comment
} }
fn print_comment(&mut self, cmnt: &Comment) { fn print_comment(&mut self, cmnt: &Comment) {
@ -570,7 +573,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.print_tts(tts, convert_dollar_crate); self.print_tts(tts, convert_dollar_crate);
self.end(); self.end();
match delim { match delim {
DelimToken::Brace => self.bclose(span), DelimToken::Brace => {
let empty = tts.is_empty();
self.bclose(span, empty);
}
_ => { _ => {
let token_str = self.token_kind_to_string(&token::CloseDelim(delim)); let token_str = self.token_kind_to_string(&token::CloseDelim(delim));
self.word(token_str) self.word(token_str)
@ -642,17 +648,20 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.end(); // Close the head-box. self.end(); // Close the head-box.
} }
fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) {
self.maybe_print_comment(span.hi()); let has_comment = self.maybe_print_comment(span.hi());
if !empty || has_comment {
self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
}
self.word("}"); self.word("}");
if close_box { if close_box {
self.end(); // Close the outer-box. self.end(); // Close the outer-box.
} }
} }
fn bclose(&mut self, span: rustc_span::Span) { fn bclose(&mut self, span: rustc_span::Span, empty: bool) {
self.bclose_maybe_open(span, true) let close_box = true;
self.bclose_maybe_open(span, empty, close_box)
} }
fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
@ -1196,7 +1205,8 @@ impl<'a> State<'a> {
for item in items { for item in items {
self.print_item(item); self.print_item(item);
} }
self.bclose(item.span); let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty);
} }
ModKind::Unloaded => { ModKind::Unloaded => {
self.s.word(";"); self.s.word(";");
@ -1216,7 +1226,8 @@ impl<'a> State<'a> {
} }
self.bopen(); self.bopen();
self.print_foreign_mod(nmod, &item.attrs); self.print_foreign_mod(nmod, &item.attrs);
self.bclose(item.span); let empty = item.attrs.is_empty() && nmod.items.is_empty();
self.bclose(item.span, empty);
} }
ast::ItemKind::GlobalAsm(ref asm) => { ast::ItemKind::GlobalAsm(ref asm) => {
self.head(visibility_qualified(&item.vis, "global_asm!")); self.head(visibility_qualified(&item.vis, "global_asm!"));
@ -1291,7 +1302,8 @@ impl<'a> State<'a> {
for impl_item in items { for impl_item in items {
self.print_assoc_item(impl_item); self.print_assoc_item(impl_item);
} }
self.bclose(item.span); let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty);
} }
ast::ItemKind::Trait(box ast::Trait { ast::ItemKind::Trait(box ast::Trait {
is_auto, is_auto,
@ -1326,7 +1338,8 @@ impl<'a> State<'a> {
for trait_item in items { for trait_item in items {
self.print_assoc_item(trait_item); self.print_assoc_item(trait_item);
} }
self.bclose(item.span); let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty);
} }
ast::ItemKind::TraitAlias(ref generics, ref bounds) => { ast::ItemKind::TraitAlias(ref generics, ref bounds) => {
self.head(""); self.head("");
@ -1410,7 +1423,8 @@ impl<'a> State<'a> {
self.end(); self.end();
self.maybe_print_trailing_comment(v.span, None); self.maybe_print_trailing_comment(v.span, None);
} }
self.bclose(span) let empty = variants.is_empty();
self.bclose(span, empty)
} }
crate fn print_visibility(&mut self, vis: &ast::Visibility) { crate fn print_visibility(&mut self, vis: &ast::Visibility) {
@ -1441,6 +1455,9 @@ impl<'a> State<'a> {
crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) { crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
self.nbsp(); self.nbsp();
self.bopen(); self.bopen();
let empty = fields.is_empty();
if !empty {
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
for field in fields { for field in fields {
@ -1453,8 +1470,9 @@ impl<'a> State<'a> {
self.print_type(&field.ty); self.print_type(&field.ty);
self.s.word(","); self.s.word(",");
} }
}
self.bclose(span) self.bclose(span, empty);
} }
crate fn print_struct( crate fn print_struct(
@ -1633,7 +1651,8 @@ impl<'a> State<'a> {
} }
} }
self.bclose_maybe_open(blk.span, close_box); let empty = attrs.is_empty() && blk.stmts.is_empty();
self.bclose_maybe_open(blk.span, empty, close_box);
self.ann.post(self, AnnNode::Block(blk)) self.ann.post(self, AnnNode::Block(blk))
} }
@ -2010,7 +2029,8 @@ impl<'a> State<'a> {
for arm in arms { for arm in arms {
self.print_arm(arm); self.print_arm(arm);
} }
self.bclose(expr.span); let empty = attrs.is_empty() && arms.is_empty();
self.bclose(expr.span, empty);
} }
ast::ExprKind::Closure( ast::ExprKind::Closure(
capture_clause, capture_clause,

View file

@ -2174,7 +2174,7 @@ impl<'a> State<'a> {
match decl.output { match decl.output {
hir::FnRetTy::Return(ref ty) => { hir::FnRetTy::Return(ref ty) => {
self.print_type(&ty); self.print_type(&ty);
self.maybe_print_comment(ty.span.lo()) self.maybe_print_comment(ty.span.lo());
} }
hir::FnRetTy::DefaultReturn(..) => unreachable!(), hir::FnRetTy::DefaultReturn(..) => unreachable!(),
} }
@ -2368,7 +2368,7 @@ impl<'a> State<'a> {
self.end(); self.end();
if let hir::FnRetTy::Return(ref output) = decl.output { if let hir::FnRetTy::Return(ref output) = decl.output {
self.maybe_print_comment(output.span.lo()) self.maybe_print_comment(output.span.lo());
} }
} }

View file

@ -1,8 +1,7 @@
// compile-flags: --crate-type=lib // compile-flags: --crate-type=lib
// pp-exact // pp-exact
fn f() { fn f() {} /*
} /*
The next line should not be indented. The next line should not be indented.
That one. It shouldn't have been indented. That one. It shouldn't have been indented.

View file

@ -13,7 +13,6 @@ extern crate std;
// [pretty]compile-flags: -Zunpretty=everybody_loops // [pretty]compile-flags: -Zunpretty=everybody_loops
// [pretty]check-pass // [pretty]check-pass
#[repr("C")] #[repr("C")]
struct A { struct A {}
}
fn main() { loop {} } fn main() { loop {} }