about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/items.rs146
-rw-r--r--src/rewrite.rs22
-rw-r--r--src/utils.rs8
3 files changed, 142 insertions, 34 deletions
diff --git a/src/items.rs b/src/items.rs
index eb11604b277..eb808678403 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -24,7 +24,7 @@ use crate::expr::{
 use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
 use crate::macros::{rewrite_macro, MacroPosition};
 use crate::overflow;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError};
 use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
@@ -48,18 +48,26 @@ fn type_annotation_separator(config: &Config) -> &str {
 // let pat: ty = init; or let pat: ty = init else { .. };
 impl Rewrite for ast::Local {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Result<String, RewriteError> {
         debug!(
             "Local::rewrite {:?} {} {:?}",
             self, shape.width, shape.indent
         );
 
-        skip_out_of_file_lines_range!(context, self.span);
+        skip_out_of_file_lines_range_err!(context, self.span);
 
         if contains_skip(&self.attrs) {
-            return None;
+            return Err(RewriteError::SkipFormatting);
         }
 
-        let attrs_str = self.attrs.rewrite(context, shape)?;
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         let mut result = if attrs_str.is_empty() {
             "let ".to_owned()
         } else {
@@ -73,15 +81,27 @@ impl Rewrite for ast::Local {
                 ),
                 shape,
                 false,
-            )?
+            )
+            .ok_or_else(|| RewriteError::Unknown)?
         };
         let let_kw_offset = result.len() - "let ".len();
 
         // 4 = "let ".len()
-        let pat_shape = shape.offset_left(4)?;
+        let pat_shape = shape.offset_left(4).ok_or_else(|| RewriteError::Unknown)?;
         // 1 = ;
-        let pat_shape = pat_shape.sub_width(1)?;
-        let pat_str = self.pat.rewrite(context, pat_shape)?;
+        let pat_shape = pat_shape
+            .sub_width(1)
+            .ok_or_else(|| RewriteError::ExceedsMaxWidth {
+                configured_width: shape.width,
+                span: self.span(),
+            })?;
+        let pat_str =
+            self.pat
+                .rewrite(context, pat_shape)
+                .ok_or_else(|| RewriteError::ExceedsMaxWidth {
+                    configured_width: shape.width,
+                    span: self.span(),
+                })?;
         result.push_str(&pat_str);
 
         // String that is placed within the assignment pattern and expression.
@@ -95,11 +115,19 @@ impl Rewrite for ast::Local {
                 } else {
                     shape
                 }
-                .offset_left(last_line_width(&result) + separator.len())?
+                .offset_left(last_line_width(&result) + separator.len())
+                .ok_or_else(|| RewriteError::ExceedsMaxWidth {
+                    configured_width: shape.width,
+                    span: self.span(),
+                })?
                 // 2 = ` =`
-                .sub_width(2)?;
+                .sub_width(2)
+                .ok_or_else(|| RewriteError::ExceedsMaxWidth {
+                    configured_width: shape.width,
+                    span: self.span(),
+                })?;
 
-                let rewrite = ty.rewrite(context, ty_shape)?;
+                let rewrite = ty.rewrite_result(context, ty_shape)?;
 
                 infix.push_str(separator);
                 infix.push_str(&rewrite);
@@ -116,7 +144,7 @@ impl Rewrite for ast::Local {
 
         if let Some((init, else_block)) = self.kind.init_else_opt() {
             // 1 = trailing semicolon;
-            let nested_shape = shape.sub_width(1)?;
+            let nested_shape = shape.sub_width(1).ok_or_else(|| RewriteError::Unknown)?;
 
             result = rewrite_assign_rhs(
                 context,
@@ -124,7 +152,8 @@ impl Rewrite for ast::Local {
                 init,
                 &RhsAssignKind::Expr(&init.kind, init.span),
                 nested_shape,
-            )?;
+            )
+            .ok_or_else(|| RewriteError::Unknown)?;
 
             if let Some(block) = else_block {
                 let else_kw_span = init.span.between(block.span);
@@ -166,7 +195,8 @@ impl Rewrite for ast::Local {
                     && allow_single_line_let_else_block(assign_str_with_else_kw, block);
 
                 let mut rw_else_block =
-                    rewrite_let_else_block(block, allow_single_line, context, shape)?;
+                    rewrite_let_else_block(block, allow_single_line, context, shape)
+                        .ok_or_else(|| RewriteError::Unknown)?;
 
                 let single_line_else = !rw_else_block.contains('\n');
                 // +1 for the trailing `;`
@@ -175,7 +205,8 @@ impl Rewrite for ast::Local {
                 if allow_single_line && single_line_else && else_block_exceeds_width {
                     // writing this on one line would exceed the available width
                     // so rewrite the else block over multiple lines.
-                    rw_else_block = rewrite_let_else_block(block, false, context, shape)?;
+                    rw_else_block = rewrite_let_else_block(block, false, context, shape)
+                        .ok_or_else(|| RewriteError::Unknown)?;
                 }
 
                 result.push_str(&rw_else_block);
@@ -183,7 +214,7 @@ impl Rewrite for ast::Local {
         }
 
         result.push(';');
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -1845,7 +1876,15 @@ pub(crate) fn rewrite_struct_field_prefix(
 
 impl Rewrite for ast::FieldDef {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        rewrite_struct_field(context, self, shape, 0)
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Result<String, RewriteError> {
+        rewrite_struct_field(context, self, shape, 0).ok_or_else(|| RewriteError::Unknown)
     }
 }
 
@@ -2071,20 +2110,40 @@ impl<'a> Rewrite for OpaqueType<'a> {
 
 impl Rewrite for ast::FnRetTy {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Result<String, RewriteError> {
         match *self {
-            ast::FnRetTy::Default(_) => Some(String::new()),
+            ast::FnRetTy::Default(_) => Ok(String::new()),
             ast::FnRetTy::Ty(ref ty) => {
                 if context.config.version() == Version::One
                     || context.config.indent_style() == IndentStyle::Visual
                 {
-                    let inner_width = shape.width.checked_sub(3)?;
+                    let inner_width = shape.width.checked_sub(3).ok_or_else(|| {
+                        RewriteError::ExceedsMaxWidth {
+                            configured_width: shape.width,
+                            span: self.span(),
+                        }
+                    })?;
                     return ty
-                        .rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
+                        .rewrite_result(context, Shape::legacy(inner_width, shape.indent + 3))
                         .map(|r| format!("-> {}", r));
                 }
 
-                ty.rewrite(context, shape.offset_left(3)?)
-                    .map(|s| format!("-> {}", s))
+                ty.rewrite_result(
+                    context,
+                    shape
+                        .offset_left(3)
+                        .ok_or_else(|| RewriteError::ExceedsMaxWidth {
+                            configured_width: shape.width,
+                            span: self.span(),
+                        })?,
+                )
+                .map(|s| format!("-> {}", s))
             }
         }
     }
@@ -2135,9 +2194,17 @@ fn get_missing_param_comments(
 
 impl Rewrite for ast::Param {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Result<String, RewriteError> {
         let param_attrs_result = self
             .attrs
-            .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
+            .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?;
         // N.B. Doc comments aren't typically valid syntax, but could appear
         // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936
         let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() {
@@ -2160,10 +2227,11 @@ impl Rewrite for ast::Param {
                 shape,
                 has_multiple_attr_lines,
             )
+            .ok_or_else(|| RewriteError::Unknown)
         } else if is_named_param(self) {
             let param_name = &self
                 .pat
-                .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
+                .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?;
             let mut result = combine_strs_with_missing_comments(
                 context,
                 &param_attrs_result,
@@ -2171,7 +2239,8 @@ impl Rewrite for ast::Param {
                 span,
                 shape,
                 !has_multiple_attr_lines && !has_doc_comments,
-            )?;
+            )
+            .ok_or_else(|| RewriteError::Unknown)?;
 
             if !is_empty_infer(&*self.ty, self.pat.span) {
                 let (before_comment, after_comment) =
@@ -2180,10 +2249,15 @@ impl Rewrite for ast::Param {
                 result.push_str(colon_spaces(context.config));
                 result.push_str(&after_comment);
                 let overhead = last_line_width(&result);
-                let max_width = shape.width.checked_sub(overhead)?;
-                if let Some(ty_str) = self
+                let max_width = shape.width.checked_sub(overhead).ok_or_else(|| {
+                    RewriteError::ExceedsMaxWidth {
+                        configured_width: shape.width,
+                        span: self.span(),
+                    }
+                })?;
+                if let Ok(ty_str) = self
                     .ty
-                    .rewrite(context, Shape::legacy(max_width, shape.indent))
+                    .rewrite_result(context, Shape::legacy(max_width, shape.indent))
                 {
                     result.push_str(&ty_str);
                 } else {
@@ -2200,22 +2274,28 @@ impl Rewrite for ast::Param {
                         span,
                         shape,
                         !has_multiple_attr_lines,
-                    )?;
+                    )
+                    .ok_or_else(|| RewriteError::Unknown)?;
                     result.push_str(&before_comment);
                     result.push_str(colon_spaces(context.config));
                     result.push_str(&after_comment);
                     let overhead = last_line_width(&result);
-                    let max_width = shape.width.checked_sub(overhead)?;
+                    let max_width = shape.width.checked_sub(overhead).ok_or_else(|| {
+                        RewriteError::ExceedsMaxWidth {
+                            configured_width: shape.width,
+                            span: self.span(),
+                        }
+                    })?;
                     let ty_str = self
                         .ty
-                        .rewrite(context, Shape::legacy(max_width, shape.indent))?;
+                        .rewrite_result(context, Shape::legacy(max_width, shape.indent))?;
                     result.push_str(&ty_str);
                 }
             }
 
-            Some(result)
+            Ok(result)
         } else {
-            self.ty.rewrite(context, shape)
+            self.ty.rewrite_result(context, shape)
         }
     }
 }
diff --git a/src/rewrite.rs b/src/rewrite.rs
index e2498a3500a..5467bf9d1f4 100644
--- a/src/rewrite.rs
+++ b/src/rewrite.rs
@@ -5,6 +5,7 @@ use std::rc::Rc;
 
 use rustc_ast::ptr;
 use rustc_span::Span;
+use thiserror::Error;
 
 use crate::config::{Config, IndentStyle};
 use crate::parse::session::ParseSess;
@@ -16,6 +17,13 @@ use crate::FormatReport;
 pub(crate) trait Rewrite {
     /// Rewrite self into shape.
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>;
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> Result<String, RewriteError> {
+        self.rewrite(context, shape).ok_or(RewriteError::Unknown)
+    }
 }
 
 impl<T: Rewrite> Rewrite for ptr::P<T> {
@@ -24,6 +32,19 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
     }
 }
 
+#[derive(Error, Debug)]
+pub(crate) enum RewriteError {
+    #[error("Formatting was skipped due to skip attribute or out of file range.")]
+    SkipFormatting,
+
+    #[error("It exceeds the required width of {configured_width} for the span: {span:?}")]
+    ExceedsMaxWidth { configured_width: usize, span: Span },
+
+    /// Format failure that does not fit to above categories.
+    #[error("An unknown error occurred during formatting.")]
+    Unknown,
+}
+
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
     pub(crate) psess: &'a ParseSess,
@@ -44,7 +65,6 @@ pub(crate) struct RewriteContext<'a> {
     pub(crate) skip_context: SkipContext,
     pub(crate) skipped_range: Rc<RefCell<Vec<(usize, usize)>>>,
 }
-
 pub(crate) struct InsideMacroGuard {
     is_nested_macro_context: bool,
     inside_macro_ref: Rc<Cell<bool>>,
diff --git a/src/utils.rs b/src/utils.rs
index fd59aedadfe..eaf24f3f204 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -375,6 +375,14 @@ macro_rules! skip_out_of_file_lines_range {
     };
 }
 
+macro_rules! skip_out_of_file_lines_range_err {
+    ($self:ident, $span:expr) => {
+        if out_of_file_lines_range!($self, $span) {
+            return Err(RewriteError::SkipFormatting);
+        }
+    };
+}
+
 macro_rules! skip_out_of_file_lines_range_visitor {
     ($self:ident, $span:expr) => {
         if out_of_file_lines_range!($self, $span) {