@@ -446,58 +446,21 @@ impl<'a> FmtVisitor<'a> {
446446}
447447
448448pub fn format_impl ( context : & RewriteContext , item : & ast:: Item , offset : Indent ) -> Option < String > {
449- if let ast:: ItemKind :: Impl ( unsafety,
450- polarity,
451- ref generics,
452- ref trait_ref,
453- ref self_ty,
454- ref items) = item. node {
449+ if let ast:: ItemKind :: Impl ( _, _, ref generics, ref trait_ref, _, ref items) = item. node {
455450 let mut result = String :: new ( ) ;
456451
457- result. push_str ( & * format_visibility ( & item. vis ) ) ;
458- result. push_str ( format_unsafety ( unsafety) ) ;
459- result. push_str ( "impl" ) ;
460-
461- let lo = context. codemap . span_after ( item. span , "impl" ) ;
462- let hi = match * trait_ref {
463- Some ( ref tr) => tr. path . span . lo ,
464- None => self_ty. span . lo ,
465- } ;
466- let generics_str = try_opt ! ( rewrite_generics( context,
467- generics,
468- offset,
469- context. config. max_width,
470- offset + result. len( ) ,
471- mk_sp( lo, hi) ) ) ;
472- result. push_str ( & generics_str) ;
473-
474- // FIXME might need to linebreak in the impl header, here would be a
475- // good place.
476- result. push ( ' ' ) ;
477- if polarity == ast:: ImplPolarity :: Negative {
478- result. push_str ( "!" ) ;
479- }
480- if let Some ( ref trait_ref) = * trait_ref {
481- let budget = try_opt ! ( context. config. max_width. checked_sub( result. len( ) ) ) ;
482- let indent = offset + result. len ( ) ;
483- result. push_str ( & * try_opt ! ( trait_ref. rewrite( context, budget, indent) ) ) ;
484- result. push_str ( " for " ) ;
485- }
452+ // First try to format the ref and type without a split at the 'for'.
453+ let mut ref_and_type = try_opt ! ( format_impl_ref_and_type( context, item, offset, false ) ) ;
486454
487- let mut used_space = result. len ( ) ;
488- if generics. where_clause . predicates . is_empty ( ) {
489- // If there is no where clause adapt budget for type formatting to take space and curly
490- // brace into account.
491- match context. config . item_brace_style {
492- BraceStyle :: AlwaysNextLine => { }
493- BraceStyle :: PreferSameLine => used_space += 2 ,
494- BraceStyle :: SameLineWhere => used_space += 2 ,
455+ // If there is a line break present in the first result format it again
456+ // with a split at the 'for'. Skip this if there is no trait ref and
457+ // therefore no 'for'.
458+ if let Some ( _) = * trait_ref {
459+ if ref_and_type. contains ( '\n' ) {
460+ ref_and_type = try_opt ! ( format_impl_ref_and_type( context, item, offset, true ) ) ;
495461 }
496462 }
497-
498- let budget = try_opt ! ( context. config. max_width. checked_sub( used_space) ) ;
499- let indent = offset + result. len ( ) ;
500- result. push_str ( & * try_opt ! ( self_ty. rewrite( context, budget, indent) ) ) ;
463+ result. push_str ( & ref_and_type) ;
501464
502465 let where_budget = try_opt ! ( context. config. max_width. checked_sub( last_line_width( & result) ) ) ;
503466 let where_clause_str = try_opt ! ( rewrite_where_clause( context,
@@ -594,6 +557,76 @@ fn is_impl_single_line(context: &RewriteContext,
594557 !contains_comment ( & snippet[ open_pos..] ) )
595558}
596559
560+ fn format_impl_ref_and_type ( context : & RewriteContext ,
561+ item : & ast:: Item ,
562+ offset : Indent ,
563+ split_at_for : bool )
564+ -> Option < String > {
565+ if let ast:: ItemKind :: Impl ( unsafety, polarity, ref generics, ref trait_ref, ref self_ty, _) =
566+ item. node {
567+ let mut result = String :: new ( ) ;
568+
569+ result. push_str ( & * format_visibility ( & item. vis ) ) ;
570+ result. push_str ( format_unsafety ( unsafety) ) ;
571+ result. push_str ( "impl" ) ;
572+
573+ let lo = context. codemap . span_after ( item. span , "impl" ) ;
574+ let hi = match * trait_ref {
575+ Some ( ref tr) => tr. path . span . lo ,
576+ None => self_ty. span . lo ,
577+ } ;
578+ let generics_str = try_opt ! ( rewrite_generics( context,
579+ generics,
580+ offset,
581+ context. config. max_width,
582+ offset + result. len( ) ,
583+ mk_sp( lo, hi) ) ) ;
584+ result. push_str ( & generics_str) ;
585+
586+ result. push ( ' ' ) ;
587+ if polarity == ast:: ImplPolarity :: Negative {
588+ result. push ( '!' ) ;
589+ }
590+ if let Some ( ref trait_ref) = * trait_ref {
591+ let budget = try_opt ! ( context. config. max_width. checked_sub( result. len( ) ) ) ;
592+ let indent = offset + result. len ( ) ;
593+ result. push_str ( & * try_opt ! ( trait_ref. rewrite( context, budget, indent) ) ) ;
594+
595+ if split_at_for {
596+ result. push ( '\n' ) ;
597+
598+ // Add indentation of one additional tab.
599+ let width = context. block_indent . width ( ) + context. config . tab_spaces ;
600+ let for_indent = Indent :: new ( 0 , width) ;
601+ result. push_str ( & for_indent. to_string ( context. config ) ) ;
602+
603+ result. push_str ( "for " ) ;
604+ } else {
605+ result. push_str ( " for " ) ;
606+ }
607+ }
608+
609+ let mut used_space = last_line_width ( & result) ;
610+ if generics. where_clause . predicates . is_empty ( ) {
611+ // If there is no where clause adapt budget for type formatting to take space and curly
612+ // brace into account.
613+ match context. config . item_brace_style {
614+ BraceStyle :: AlwaysNextLine => { }
615+ BraceStyle :: PreferSameLine => used_space += 2 ,
616+ BraceStyle :: SameLineWhere => used_space += 2 ,
617+ }
618+ }
619+
620+ let budget = try_opt ! ( context. config. max_width. checked_sub( used_space) ) ;
621+ let indent = offset + result. len ( ) ;
622+ result. push_str ( & * try_opt ! ( self_ty. rewrite( context, budget, indent) ) ) ;
623+
624+ Some ( result)
625+ } else {
626+ unreachable ! ( ) ;
627+ }
628+ }
629+
597630pub fn format_struct ( context : & RewriteContext ,
598631 item_name : & str ,
599632 ident : ast:: Ident ,
0 commit comments