@@ -634,6 +634,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
634634 false ,
635635 None ,
636636 * delim,
637+ None ,
637638 tokens,
638639 true ,
639640 span,
@@ -679,6 +680,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
679680 false ,
680681 None ,
681682 * delim,
683+ Some ( spacing. open ) ,
682684 tts,
683685 convert_dollar_crate,
684686 dspan. entire ( ) ,
@@ -735,6 +737,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
735737 has_bang : bool ,
736738 ident : Option < Ident > ,
737739 delim : Delimiter ,
740+ open_spacing : Option < Spacing > ,
738741 tts : & TokenStream ,
739742 convert_dollar_crate : bool ,
740743 span : Span ,
@@ -758,16 +761,26 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
758761 self . nbsp ( ) ;
759762 }
760763 self . word ( "{" ) ;
761- if !tts. is_empty ( ) {
764+
765+ // Respect `Alone`, if provided, and print a space. Unless the list is empty.
766+ let open_space = ( open_spacing == None || open_spacing == Some ( Spacing :: Alone ) )
767+ && !tts. is_empty ( ) ;
768+ if open_space {
762769 self . space ( ) ;
763770 }
764771 let ib = self . ibox ( 0 ) ;
765772 self . print_tts ( tts, convert_dollar_crate) ;
766773 self . end ( ib) ;
767- let empty = tts. is_empty ( ) ;
768- self . bclose ( span, empty, cb. unwrap ( ) ) ;
774+
775+ // Use `open_space` for the spacing *before* the closing delim.
776+ // Because spacing on delimiters is lost when going through
777+ // proc macros, and otherwise we can end up with ugly cases
778+ // like `{ x}`. Symmetry is better.
779+ self . bclose ( span, !open_space, cb. unwrap ( ) ) ;
769780 }
770781 delim => {
782+ // `open_spacing` is ignored. We never print spaces after
783+ // non-brace opening delims or before non-brace closing delims.
771784 let token_str = self . token_kind_to_string ( & delim. as_open_token_kind ( ) ) ;
772785 self . word ( token_str) ;
773786 let ib = self . ibox ( 0 ) ;
@@ -797,6 +810,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
797810 has_bang,
798811 Some ( * ident) ,
799812 macro_def. body . delim ,
813+ None ,
800814 & macro_def. body . tokens ,
801815 true ,
802816 sp,
@@ -844,9 +858,9 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
844858 self . end ( ib) ;
845859 }
846860
847- fn bclose_maybe_open ( & mut self , span : rustc_span:: Span , empty : bool , cb : Option < BoxMarker > ) {
861+ fn bclose_maybe_open ( & mut self , span : rustc_span:: Span , no_space : bool , cb : Option < BoxMarker > ) {
848862 let has_comment = self . maybe_print_comment ( span. hi ( ) ) ;
849- if !empty || has_comment {
863+ if !no_space || has_comment {
850864 self . break_offset_if_not_bol ( 1 , -INDENT_UNIT ) ;
851865 }
852866 self . word ( "}" ) ;
@@ -855,9 +869,9 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
855869 }
856870 }
857871
858- fn bclose ( & mut self , span : rustc_span:: Span , empty : bool , cb : BoxMarker ) {
872+ fn bclose ( & mut self , span : rustc_span:: Span , no_space : bool , cb : BoxMarker ) {
859873 let cb = Some ( cb) ;
860- self . bclose_maybe_open ( span, empty , cb)
874+ self . bclose_maybe_open ( span, no_space , cb)
861875 }
862876
863877 fn break_offset_if_not_bol ( & mut self , n : usize , off : isize ) {
@@ -1434,8 +1448,8 @@ impl<'a> State<'a> {
14341448 }
14351449 }
14361450
1437- let empty = !has_attrs && blk. stmts . is_empty ( ) ;
1438- self . bclose_maybe_open ( blk. span , empty , cb) ;
1451+ let no_space = !has_attrs && blk. stmts . is_empty ( ) ;
1452+ self . bclose_maybe_open ( blk. span , no_space , cb) ;
14391453 self . ann . post ( self , AnnNode :: Block ( blk) )
14401454 }
14411455
@@ -1482,6 +1496,7 @@ impl<'a> State<'a> {
14821496 true ,
14831497 None ,
14841498 m. args . delim ,
1499+ None ,
14851500 & m. args . tokens ,
14861501 true ,
14871502 m. span ( ) ,
0 commit comments