@@ -6,6 +6,7 @@ use rustc_span::{symbol::kw, BytePos, Span};
66
77use crate :: config:: { lists:: * , IndentStyle , TypeDensity } ;
88use crate :: formatting:: {
9+ comment:: { combine_strs_with_missing_comments, contains_comment} ,
910 expr:: {
1011 format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix,
1112 ExprType ,
@@ -844,57 +845,131 @@ fn join_bounds(
844845 items : & [ ast:: GenericBound ] ,
845846 need_indent : bool ,
846847) -> Option < String > {
847- debug_assert ! ( !items. is_empty( ) ) ;
848-
849- // Try to join types in a single line
850- let joiner = match context. config . type_punctuation_density ( ) {
851- TypeDensity :: Compressed => "+" ,
852- TypeDensity :: Wide => " + " ,
853- } ;
854- let type_strs = items
855- . iter ( )
856- . map ( |item| item. rewrite ( context, shape) )
857- . collect :: < Option < Vec < _ > > > ( ) ?;
858- let result = type_strs. join ( joiner) ;
859- if items. len ( ) <= 1 || ( !result. contains ( '\n' ) && result. len ( ) <= shape. width ) {
860- return Some ( result) ;
861- }
848+ join_bounds_inner ( context, shape, items, need_indent, false )
849+ }
862850
863- // We need to use multiple lines.
864- let ( type_strs, offset) = if need_indent {
865- // Rewrite with additional indentation.
866- let nested_shape = shape
867- . block_indent ( context. config . tab_spaces ( ) )
868- . with_max_width ( context. config ) ;
869- let type_strs = items
870- . iter ( )
871- . map ( |item| item. rewrite ( context, nested_shape) )
872- . collect :: < Option < Vec < _ > > > ( ) ?;
873- ( type_strs, nested_shape. indent )
874- } else {
875- ( type_strs, shape. indent )
876- } ;
851+ fn join_bounds_inner (
852+ context : & RewriteContext < ' _ > ,
853+ shape : Shape ,
854+ items : & [ ast:: GenericBound ] ,
855+ need_indent : bool ,
856+ force_newline : bool ,
857+ ) -> Option < String > {
858+ debug_assert ! ( !items. is_empty( ) ) ;
877859
860+ let generic_bounds_in_order = is_generic_bounds_in_order ( items) ;
878861 let is_bound_extendable = |s : & str , b : & ast:: GenericBound | match b {
879862 ast:: GenericBound :: Outlives ( ..) => true ,
880863 ast:: GenericBound :: Trait ( ..) => last_line_extendable ( s) ,
881864 } ;
882- let mut result = String :: with_capacity ( 128 ) ;
883- result. push_str ( & type_strs[ 0 ] ) ;
884- let mut can_be_put_on_the_same_line = is_bound_extendable ( & result, & items[ 0 ] ) ;
885- let generic_bounds_in_order = is_generic_bounds_in_order ( items) ;
886- for ( bound, bound_str) in items[ 1 ..] . iter ( ) . zip ( type_strs[ 1 ..] . iter ( ) ) {
887- if generic_bounds_in_order && can_be_put_on_the_same_line {
888- result. push_str ( joiner) ;
889- } else {
890- result. push_str ( & offset. to_string_with_newline ( context. config ) ) ;
891- result. push_str ( "+ " ) ;
892- }
893- result. push_str ( bound_str) ;
894- can_be_put_on_the_same_line = is_bound_extendable ( bound_str, bound) ;
895- }
896865
897- Some ( result)
866+ let result = items. iter ( ) . enumerate ( ) . try_fold (
867+ ( String :: new ( ) , None , false ) ,
868+ |( strs, prev_trailing_span, prev_extendable) , ( i, item) | {
869+ let trailing_span = if i < items. len ( ) - 1 {
870+ let hi = context
871+ . snippet_provider
872+ . span_before ( mk_sp ( items[ i + 1 ] . span ( ) . lo ( ) , item. span ( ) . hi ( ) ) , "+" ) ;
873+
874+ Some ( mk_sp ( item. span ( ) . hi ( ) , hi) )
875+ } else {
876+ None
877+ } ;
878+ let ( leading_span, has_leading_comment) = if i > 0 {
879+ let lo = context
880+ . snippet_provider
881+ . span_after ( mk_sp ( items[ i - 1 ] . span ( ) . hi ( ) , item. span ( ) . lo ( ) ) , "+" ) ;
882+
883+ let span = mk_sp ( lo, item. span ( ) . lo ( ) ) ;
884+
885+ let has_comments = contains_comment ( context. snippet ( span) ) ;
886+
887+ ( Some ( mk_sp ( lo, item. span ( ) . lo ( ) ) ) , has_comments)
888+ } else {
889+ ( None , false )
890+ } ;
891+ let prev_has_trailing_comment = match prev_trailing_span {
892+ Some ( ts) => contains_comment ( context. snippet ( ts) ) ,
893+ _ => false ,
894+ } ;
895+
896+ let shape = if i > 0 && need_indent && force_newline {
897+ shape
898+ . block_indent ( context. config . tab_spaces ( ) )
899+ . with_max_width ( context. config )
900+ } else {
901+ shape
902+ } ;
903+ let whitespace = if force_newline && ( !prev_extendable || !generic_bounds_in_order) {
904+ shape
905+ . indent
906+ . to_string_with_newline ( context. config )
907+ . to_string ( )
908+ } else {
909+ String :: from ( " " )
910+ } ;
911+
912+ let joiner = match context. config . type_punctuation_density ( ) {
913+ TypeDensity :: Compressed => String :: from ( "+" ) ,
914+ TypeDensity :: Wide => whitespace + "+ " ,
915+ } ;
916+ let joiner = if has_leading_comment {
917+ joiner. trim_end ( )
918+ } else {
919+ & joiner
920+ } ;
921+ let joiner = if prev_has_trailing_comment {
922+ joiner. trim_start ( )
923+ } else {
924+ joiner
925+ } ;
926+
927+ let ( trailing_str, extendable) = if i == 0 {
928+ let bound_str = item. rewrite ( context, shape) ?;
929+ let bound_str_clone = bound_str. clone ( ) ;
930+ ( bound_str, is_bound_extendable ( & bound_str_clone, item) )
931+ } else {
932+ let bound_str = & item. rewrite ( context, shape) ?;
933+ match leading_span {
934+ Some ( ls) if has_leading_comment => (
935+ combine_strs_with_missing_comments (
936+ context, joiner, bound_str, ls, shape, true ,
937+ ) ?,
938+ is_bound_extendable ( bound_str, item) ,
939+ ) ,
940+ _ => (
941+ String :: from ( joiner) + bound_str,
942+ is_bound_extendable ( bound_str, item) ,
943+ ) ,
944+ }
945+ } ;
946+ match prev_trailing_span {
947+ Some ( ts) if prev_has_trailing_comment => combine_strs_with_missing_comments (
948+ context,
949+ & strs,
950+ & trailing_str,
951+ ts,
952+ shape,
953+ true ,
954+ )
955+ . map ( |v| ( v, trailing_span, extendable) ) ,
956+ _ => Some ( (
957+ String :: from ( strs) + & trailing_str,
958+ trailing_span,
959+ extendable,
960+ ) ) ,
961+ }
962+ } ,
963+ ) ?;
964+
965+ if !force_newline
966+ && items. len ( ) > 1
967+ && ( result. 0 . contains ( '\n' ) || result. 0 . len ( ) > shape. width )
968+ {
969+ join_bounds_inner ( context, shape, items, need_indent, true )
970+ } else {
971+ Some ( result. 0 )
972+ }
898973}
899974
900975pub ( crate ) fn can_be_overflowed_type (
0 commit comments