@@ -79,6 +79,9 @@ use thin_vec::ThinVec;
7979/// Provides the original input contents from the span
8080/// of a chain element with trailing spaces trimmed.
8181fn format_overflow_style ( span : Span , context : & RewriteContext < ' _ > ) -> Option < String > {
82+ // TODO(ding-young): Currently returning None when the given span is out of the range
83+ // covered by the snippet provider. If this is a common cause for internal
84+ // rewrite failure, add a new enum variant and return RewriteError instead of None
8285 context. snippet_provider . span_to_snippet ( span) . map ( |s| {
8386 s. lines ( )
8487 . map ( |l| l. trim_end ( ) )
@@ -92,12 +95,16 @@ fn format_chain_item(
9295 context : & RewriteContext < ' _ > ,
9396 rewrite_shape : Shape ,
9497 allow_overflow : bool ,
95- ) -> Option < String > {
98+ ) -> RewriteResult {
9699 if allow_overflow {
97- item. rewrite ( context, rewrite_shape)
98- . or_else ( || format_overflow_style ( item. span , context) )
100+ // TODO(ding-young): Consider calling format_overflow_style()
101+ // only when item.rewrite_result() returns RewriteError::ExceedsMaxWidth.
102+ // It may be inappropriate to call format_overflow_style on other RewriteError
103+ // since the current approach retries formatting if allow_overflow is true
104+ item. rewrite_result ( context, rewrite_shape)
105+ . or_else ( |_| format_overflow_style ( item. span , context) . unknown_error ( ) )
99106 } else {
100- item. rewrite ( context, rewrite_shape)
107+ item. rewrite_result ( context, rewrite_shape)
101108 }
102109}
103110
@@ -134,17 +141,17 @@ pub(crate) fn rewrite_chain(
134141 expr : & ast:: Expr ,
135142 context : & RewriteContext < ' _ > ,
136143 shape : Shape ,
137- ) -> Option < String > {
144+ ) -> RewriteResult {
138145 let chain = Chain :: from_ast ( expr, context) ;
139146 debug ! ( "rewrite_chain {:?} {:?}" , chain, shape) ;
140147
141148 // If this is just an expression with some `?`s, then format it trivially and
142149 // return early.
143150 if chain. children . is_empty ( ) {
144- return chain. parent . rewrite ( context, shape) ;
151+ return chain. parent . rewrite_result ( context, shape) ;
145152 }
146153
147- chain. rewrite ( context, shape)
154+ chain. rewrite_result ( context, shape)
148155}
149156
150157#[ derive( Debug ) ]
@@ -524,6 +531,10 @@ impl Chain {
524531
525532impl Rewrite for Chain {
526533 fn rewrite ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> Option < String > {
534+ self . rewrite_result ( context, shape) . ok ( )
535+ }
536+
537+ fn rewrite_result ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> RewriteResult {
527538 debug ! ( "rewrite chain {:?} {:?}" , self , shape) ;
528539
529540 let mut formatter = match context. config . indent_style ( ) {
@@ -537,17 +548,25 @@ impl Rewrite for Chain {
537548
538549 formatter. format_root ( & self . parent , context, shape) ?;
539550 if let Some ( result) = formatter. pure_root ( ) {
540- return wrap_str ( result, context. config . max_width ( ) , shape) ;
551+ return wrap_str ( result, context. config . max_width ( ) , shape)
552+ . max_width_error ( shape. width , self . parent . span ) ;
541553 }
542554
555+ let first = self . children . first ( ) . unwrap_or ( & self . parent ) ;
556+ let last = self . children . last ( ) . unwrap_or ( & self . parent ) ;
557+ let children_span = mk_sp ( first. span . lo ( ) , last. span . hi ( ) ) ;
558+ let full_span = self . parent . span . with_hi ( children_span. hi ( ) ) ;
559+
543560 // Decide how to layout the rest of the chain.
544- let child_shape = formatter. child_shape ( context, shape) ?;
561+ let child_shape = formatter
562+ . child_shape ( context, shape)
563+ . max_width_error ( shape. width , children_span) ?;
545564
546565 formatter. format_children ( context, child_shape) ?;
547566 formatter. format_last_child ( context, shape, child_shape) ?;
548567
549568 let result = formatter. join_rewrites ( context, child_shape) ?;
550- wrap_str ( result, context. config . max_width ( ) , shape)
569+ wrap_str ( result, context. config . max_width ( ) , shape) . max_width_error ( shape . width , full_span )
551570 }
552571}
553572
@@ -569,16 +588,20 @@ trait ChainFormatter {
569588 parent : & ChainItem ,
570589 context : & RewriteContext < ' _ > ,
571590 shape : Shape ,
572- ) -> Option < ( ) > ;
591+ ) -> Result < ( ) , RewriteError > ;
573592 fn child_shape ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> Option < Shape > ;
574- fn format_children ( & mut self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < ( ) > ;
593+ fn format_children (
594+ & mut self ,
595+ context : & RewriteContext < ' _ > ,
596+ child_shape : Shape ,
597+ ) -> Result < ( ) , RewriteError > ;
575598 fn format_last_child (
576599 & mut self ,
577600 context : & RewriteContext < ' _ > ,
578601 shape : Shape ,
579602 child_shape : Shape ,
580- ) -> Option < ( ) > ;
581- fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < String > ;
603+ ) -> Result < ( ) , RewriteError > ;
604+ fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> RewriteResult ;
582605 // Returns `Some` if the chain is only a root, None otherwise.
583606 fn pure_root ( & mut self ) -> Option < String > ;
584607}
@@ -621,12 +644,16 @@ impl<'a> ChainFormatterShared<'a> {
621644 }
622645 }
623646
624- fn format_children ( & mut self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < ( ) > {
647+ fn format_children (
648+ & mut self ,
649+ context : & RewriteContext < ' _ > ,
650+ child_shape : Shape ,
651+ ) -> Result < ( ) , RewriteError > {
625652 for item in & self . children [ ..self . children . len ( ) - 1 ] {
626653 let rewrite = format_chain_item ( item, context, child_shape, self . allow_overflow ) ?;
627654 self . rewrites . push ( rewrite) ;
628655 }
629- Some ( ( ) )
656+ Ok ( ( ) )
630657 }
631658
632659 // Rewrite the last child. The last child of a chain requires special treatment. We need to
@@ -667,8 +694,8 @@ impl<'a> ChainFormatterShared<'a> {
667694 context : & RewriteContext < ' _ > ,
668695 shape : Shape ,
669696 child_shape : Shape ,
670- ) -> Option < ( ) > {
671- let last = self . children . last ( ) ?;
697+ ) -> Result < ( ) , RewriteError > {
698+ let last = self . children . last ( ) . unknown_error ( ) ?;
672699 let extendable = may_extend && last_line_extendable ( & self . rewrites [ 0 ] ) ;
673700 let prev_last_line_width = last_line_width ( & self . rewrites [ 0 ] ) ;
674701
@@ -692,11 +719,17 @@ impl<'a> ChainFormatterShared<'a> {
692719 && self . rewrites . iter ( ) . all ( |s| !s. contains ( '\n' ) )
693720 && one_line_budget > 0 ;
694721 let last_shape = if all_in_one_line {
695- shape. sub_width ( last. tries ) ?
722+ shape
723+ . sub_width ( last. tries )
724+ . max_width_error ( shape. width , last. span ) ?
696725 } else if extendable {
697- child_shape. sub_width ( last. tries ) ?
726+ child_shape
727+ . sub_width ( last. tries )
728+ . max_width_error ( child_shape. width , last. span ) ?
698729 } else {
699- child_shape. sub_width ( shape. rhs_overhead ( context. config ) + last. tries ) ?
730+ child_shape
731+ . sub_width ( shape. rhs_overhead ( context. config ) + last. tries )
732+ . max_width_error ( child_shape. width , last. span ) ?
700733 } ;
701734
702735 let mut last_subexpr_str = None ;
@@ -712,7 +745,7 @@ impl<'a> ChainFormatterShared<'a> {
712745 } ;
713746
714747 if let Some ( one_line_shape) = one_line_shape {
715- if let Some ( rw) = last. rewrite ( context, one_line_shape) {
748+ if let Ok ( rw) = last. rewrite_result ( context, one_line_shape) {
716749 // We allow overflowing here only if both of the following conditions match:
717750 // 1. The entire chain fits in a single line except the last child.
718751 // 2. `last_child_str.lines().count() >= 5`.
@@ -727,17 +760,18 @@ impl<'a> ChainFormatterShared<'a> {
727760 // last child on its own line, and compare two rewrites to choose which is
728761 // better.
729762 let last_shape = child_shape
730- . sub_width ( shape. rhs_overhead ( context. config ) + last. tries ) ?;
731- match last. rewrite ( context, last_shape) {
732- Some ( ref new_rw) if !could_fit_single_line => {
763+ . sub_width ( shape. rhs_overhead ( context. config ) + last. tries )
764+ . max_width_error ( child_shape. width , last. span ) ?;
765+ match last. rewrite_result ( context, last_shape) {
766+ Ok ( ref new_rw) if !could_fit_single_line => {
733767 last_subexpr_str = Some ( new_rw. clone ( ) ) ;
734768 }
735- Some ( ref new_rw) if new_rw. lines ( ) . count ( ) >= line_count => {
769+ Ok ( ref new_rw) if new_rw. lines ( ) . count ( ) >= line_count => {
736770 last_subexpr_str = Some ( rw) ;
737771 self . fits_single_line = could_fit_single_line && all_in_one_line;
738772 }
739- new_rw @ Some ( .. ) => {
740- last_subexpr_str = new_rw;
773+ Ok ( new_rw ) => {
774+ last_subexpr_str = Some ( new_rw) ;
741775 }
742776 _ => {
743777 last_subexpr_str = Some ( rw) ;
@@ -752,22 +786,28 @@ impl<'a> ChainFormatterShared<'a> {
752786 let last_shape = if context. use_block_indent ( ) {
753787 last_shape
754788 } else {
755- child_shape. sub_width ( shape. rhs_overhead ( context. config ) + last. tries ) ?
789+ child_shape
790+ . sub_width ( shape. rhs_overhead ( context. config ) + last. tries )
791+ . max_width_error ( child_shape. width , last. span ) ?
756792 } ;
757793
758- last_subexpr_str = last_subexpr_str. or_else ( || last. rewrite ( context, last_shape) ) ;
759- self . rewrites . push ( last_subexpr_str?) ;
760- Some ( ( ) )
794+ let last_subexpr_str =
795+ last_subexpr_str. unwrap_or ( last. rewrite_result ( context, last_shape) ?) ;
796+ self . rewrites . push ( last_subexpr_str) ;
797+ Ok ( ( ) )
761798 }
762799
763- fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < String > {
800+ fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> RewriteResult {
764801 let connector = if self . fits_single_line {
765802 // Yay, we can put everything on one line.
766803 Cow :: from ( "" )
767804 } else {
768805 // Use new lines.
769806 if context. force_one_line_chain . get ( ) {
770- return None ;
807+ return Err ( RewriteError :: ExceedsMaxWidth {
808+ configured_width : child_shape. width ,
809+ span : self . children . last ( ) . unknown_error ( ) ?. span ,
810+ } ) ;
771811 }
772812 child_shape. to_string_with_newline ( context. config )
773813 } ;
@@ -786,7 +826,7 @@ impl<'a> ChainFormatterShared<'a> {
786826 result. push_str ( rewrite) ;
787827 }
788828
789- Some ( result)
829+ Ok ( result)
790830 }
791831}
792832
@@ -811,8 +851,8 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
811851 parent : & ChainItem ,
812852 context : & RewriteContext < ' _ > ,
813853 shape : Shape ,
814- ) -> Option < ( ) > {
815- let mut root_rewrite: String = parent. rewrite ( context, shape) ?;
854+ ) -> Result < ( ) , RewriteError > {
855+ let mut root_rewrite: String = parent. rewrite_result ( context, shape) ?;
816856
817857 let mut root_ends_with_block = parent. kind . is_block_like ( context, & root_rewrite) ;
818858 let tab_width = context. config . tab_spaces ( ) . saturating_sub ( shape. offset ) ;
@@ -822,10 +862,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
822862 if let ChainItemKind :: Comment ( ..) = item. kind {
823863 break ;
824864 }
825- let shape = shape. offset_left ( root_rewrite. len ( ) ) ?;
826- match & item. rewrite ( context, shape) {
827- Some ( rewrite) => root_rewrite. push_str ( rewrite) ,
828- None => break ,
865+ let shape = shape
866+ . offset_left ( root_rewrite. len ( ) )
867+ . max_width_error ( shape. width , item. span ) ?;
868+ match & item. rewrite_result ( context, shape) {
869+ Ok ( rewrite) => root_rewrite. push_str ( rewrite) ,
870+ Err ( _) => break ,
829871 }
830872
831873 root_ends_with_block = last_line_extendable ( & root_rewrite) ;
@@ -837,15 +879,19 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
837879 }
838880 self . shared . rewrites . push ( root_rewrite) ;
839881 self . root_ends_with_block = root_ends_with_block;
840- Some ( ( ) )
882+ Ok ( ( ) )
841883 }
842884
843885 fn child_shape ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> Option < Shape > {
844886 let block_end = self . root_ends_with_block ;
845887 Some ( get_block_child_shape ( block_end, context, shape) )
846888 }
847889
848- fn format_children ( & mut self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < ( ) > {
890+ fn format_children (
891+ & mut self ,
892+ context : & RewriteContext < ' _ > ,
893+ child_shape : Shape ,
894+ ) -> Result < ( ) , RewriteError > {
849895 self . shared . format_children ( context, child_shape)
850896 }
851897
@@ -854,12 +900,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
854900 context : & RewriteContext < ' _ > ,
855901 shape : Shape ,
856902 child_shape : Shape ,
857- ) -> Option < ( ) > {
903+ ) -> Result < ( ) , RewriteError > {
858904 self . shared
859905 . format_last_child ( true , context, shape, child_shape)
860906 }
861907
862- fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < String > {
908+ fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> RewriteResult {
863909 self . shared . join_rewrites ( context, child_shape)
864910 }
865911
@@ -890,9 +936,9 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
890936 parent : & ChainItem ,
891937 context : & RewriteContext < ' _ > ,
892938 shape : Shape ,
893- ) -> Option < ( ) > {
939+ ) -> Result < ( ) , RewriteError > {
894940 let parent_shape = shape. visual_indent ( 0 ) ;
895- let mut root_rewrite = parent. rewrite ( context, parent_shape) ?;
941+ let mut root_rewrite = parent. rewrite_result ( context, parent_shape) ?;
896942 let multiline = root_rewrite. contains ( '\n' ) ;
897943 self . offset = if multiline {
898944 last_line_width ( & root_rewrite) . saturating_sub ( shape. used_width ( ) )
@@ -904,18 +950,19 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
904950 let item = & self . shared . children [ 0 ] ;
905951 if let ChainItemKind :: Comment ( ..) = item. kind {
906952 self . shared . rewrites . push ( root_rewrite) ;
907- return Some ( ( ) ) ;
953+ return Ok ( ( ) ) ;
908954 }
909955 let child_shape = parent_shape
910956 . visual_indent ( self . offset )
911- . sub_width ( self . offset ) ?;
912- let rewrite = item. rewrite ( context, child_shape) ?;
957+ . sub_width ( self . offset )
958+ . max_width_error ( parent_shape. width , item. span ) ?;
959+ let rewrite = item. rewrite_result ( context, child_shape) ?;
913960 if filtered_str_fits ( & rewrite, context. config . max_width ( ) , shape) {
914961 root_rewrite. push_str ( & rewrite) ;
915962 } else {
916963 // We couldn't fit in at the visual indent, try the last
917964 // indent.
918- let rewrite = item. rewrite ( context, parent_shape) ?;
965+ let rewrite = item. rewrite_result ( context, parent_shape) ?;
919966 root_rewrite. push_str ( & rewrite) ;
920967 self . offset = 0 ;
921968 }
@@ -924,7 +971,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
924971 }
925972
926973 self . shared . rewrites . push ( root_rewrite) ;
927- Some ( ( ) )
974+ Ok ( ( ) )
928975 }
929976
930977 fn child_shape ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> Option < Shape > {
@@ -937,7 +984,11 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
937984 )
938985 }
939986
940- fn format_children ( & mut self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < ( ) > {
987+ fn format_children (
988+ & mut self ,
989+ context : & RewriteContext < ' _ > ,
990+ child_shape : Shape ,
991+ ) -> Result < ( ) , RewriteError > {
941992 self . shared . format_children ( context, child_shape)
942993 }
943994
@@ -946,12 +997,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
946997 context : & RewriteContext < ' _ > ,
947998 shape : Shape ,
948999 child_shape : Shape ,
949- ) -> Option < ( ) > {
1000+ ) -> Result < ( ) , RewriteError > {
9501001 self . shared
9511002 . format_last_child ( false , context, shape, child_shape)
9521003 }
9531004
954- fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> Option < String > {
1005+ fn join_rewrites ( & self , context : & RewriteContext < ' _ > , child_shape : Shape ) -> RewriteResult {
9551006 self . shared . join_rewrites ( context, child_shape)
9561007 }
9571008
0 commit comments