about summary refs log tree commit diff
path: root/src/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/patterns.rs')
-rw-r--r--src/patterns.rs143
1 files changed, 96 insertions, 47 deletions
diff --git a/src/patterns.rs b/src/patterns.rs
index d8cb26a20f1..6fe2d4a8520 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -2,22 +2,22 @@ use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd,
 use rustc_ast::ptr;
 use rustc_span::{BytePos, Span};
 
-use crate::comment::{combine_strs_with_missing_comments, FindUncommented};
+use crate::comment::{FindUncommented, combine_strs_with_missing_comments};
+use crate::config::StyleEdition;
 use crate::config::lists::*;
-use crate::config::Version;
 use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field};
 use crate::lists::{
-    definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
-    struct_lit_tactic, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, shape_for_tactic,
+    struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list,
 };
-use crate::macros::{rewrite_macro, MacroPosition};
+use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
-use crate::pairs::{rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::pairs::{PairParts, rewrite_pair};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
-use crate::types::{rewrite_path, PathContext};
+use crate::types::{PathContext, rewrite_path};
 use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident};
 
 /// Returns `true` if the given pattern is "short".
@@ -61,25 +61,36 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
     }
 }
 
-struct RangeOperand<'a>(&'a Option<ptr::P<ast::Expr>>);
+pub(crate) struct RangeOperand<'a> {
+    operand: &'a Option<ptr::P<ast::Expr>>,
+    pub(crate) span: Span,
+}
 
 impl<'a> Rewrite for RangeOperand<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        match &self.0 {
-            None => Some("".to_owned()),
-            Some(ref exp) => exp.rewrite(context, shape),
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        match &self.operand {
+            None => Ok("".to_owned()),
+            Some(ref exp) => exp.rewrite_result(context, shape),
         }
     }
 }
 
 impl Rewrite for Pat {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self.kind {
             PatKind::Or(ref pats) => {
                 let pat_strs = pats
                     .iter()
-                    .map(|p| p.rewrite(context, shape))
-                    .collect::<Option<Vec<_>>>()?;
+                    .map(|p| p.rewrite_result(context, shape))
+                    .collect::<Result<Vec<_>, RewriteError>>()?;
 
                 let use_mixed_layout = pats
                     .iter()
@@ -115,14 +126,21 @@ impl Rewrite for Pat {
                 let sub_pat = match *sub_pat {
                     Some(ref p) => {
                         // 2 - `@ `.
-                        let width = shape.width.checked_sub(
-                            mut_prefix.len() + ref_kw.len() + mut_infix.len() + id_str.len() + 2,
-                        )?;
+                        let width = shape
+                            .width
+                            .checked_sub(
+                                mut_prefix.len()
+                                    + ref_kw.len()
+                                    + mut_infix.len()
+                                    + id_str.len()
+                                    + 2,
+                            )
+                            .max_width_error(shape.width, p.span())?;
                         let lo = context.snippet_provider.span_after(self.span, "@");
                         combine_strs_with_missing_comments(
                             context,
                             "@",
-                            &p.rewrite(context, Shape::legacy(width, shape.indent))?,
+                            &p.rewrite_result(context, Shape::legacy(width, shape.indent))?,
                             mk_sp(lo, p.span.lo()),
                             shape,
                             true,
@@ -207,19 +225,25 @@ impl Rewrite for Pat {
             }
             PatKind::Wild => {
                 if 1 <= shape.width {
-                    Some("_".to_owned())
+                    Ok("_".to_owned())
                 } else {
-                    None
+                    Err(RewriteError::ExceedsMaxWidth {
+                        configured_width: 1,
+                        span: self.span,
+                    })
                 }
             }
             PatKind::Rest => {
                 if 1 <= shape.width {
-                    Some("..".to_owned())
+                    Ok("..".to_owned())
                 } else {
-                    None
+                    Err(RewriteError::ExceedsMaxWidth {
+                        configured_width: 1,
+                        span: self.span,
+                    })
                 }
             }
-            PatKind::Never => None,
+            PatKind::Never => Err(RewriteError::Unknown),
             PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
                 let infix = match end_kind.node {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
@@ -239,9 +263,17 @@ impl Rewrite for Pat {
                 } else {
                     infix.to_owned()
                 };
+                let lspan = self.span.with_hi(end_kind.span.lo());
+                let rspan = self.span.with_lo(end_kind.span.hi());
                 rewrite_pair(
-                    &RangeOperand(lhs),
-                    &RangeOperand(rhs),
+                    &RangeOperand {
+                        operand: lhs,
+                        span: lspan,
+                    },
+                    &RangeOperand {
+                        operand: rhs,
+                        span: rspan,
+                    },
                     PairParts::infix(&infix),
                     context,
                     shape,
@@ -260,19 +292,21 @@ impl Rewrite for Pat {
                 let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?;
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
-            PatKind::Lit(ref expr) => expr.rewrite(context, shape),
-            PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => {
+            PatKind::Lit(ref expr) => expr.rewrite_result(context, shape),
+            PatKind::Slice(ref slice_pat)
+                if context.config.style_edition() <= StyleEdition::Edition2021 =>
+            {
                 let rw: Vec<String> = slice_pat
                     .iter()
                     .map(|p| {
-                        if let Some(rw) = p.rewrite(context, shape) {
+                        if let Ok(rw) = p.rewrite_result(context, shape) {
                             rw
                         } else {
                             context.snippet(p.span).to_string()
                         }
                     })
                     .collect();
-                Some(format!("[{}]", rw.join(", ")))
+                Ok(format!("[{}]", rw.join(", ")))
             }
             PatKind::Slice(ref slice_pat) => overflow::rewrite_with_square_brackets(
                 context,
@@ -296,10 +330,16 @@ impl Rewrite for Pat {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
             }
             PatKind::Paren(ref pat) => pat
-                .rewrite(context, shape.offset_left(1)?.sub_width(1)?)
+                .rewrite_result(
+                    context,
+                    shape
+                        .offset_left(1)
+                        .and_then(|s| s.sub_width(1))
+                        .max_width_error(shape.width, self.span)?,
+                )
                 .map(|inner_pat| format!("({})", inner_pat)),
-            PatKind::Err(_) => None,
-            PatKind::Deref(_) => None,
+            PatKind::Err(_) => Err(RewriteError::Unknown),
+            PatKind::Deref(_) => Err(RewriteError::Unknown),
         }
     }
 }
@@ -312,20 +352,21 @@ fn rewrite_struct_pat(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     // 2 =  ` {`
-    let path_shape = shape.sub_width(2)?;
+    let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?;
     let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
 
     if fields.is_empty() && !ellipsis {
-        return Some(format!("{path_str} {{}}"));
+        return Ok(format!("{path_str} {{}}"));
     }
 
     let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };
 
     // 3 = ` { `, 2 = ` }`.
     let (h_shape, v_shape) =
-        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;
+        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)
+            .max_width_error(shape.width, span)?;
 
     let items = itemize_list(
         context.snippet_provider,
@@ -340,7 +381,7 @@ fn rewrite_struct_pat(
             }
         },
         |f| f.span.hi(),
-        |f| f.rewrite(context, v_shape),
+        |f| f.rewrite_result(context, v_shape),
         context.snippet_provider.span_after(span, "{"),
         span.hi(),
         false,
@@ -379,11 +420,15 @@ fn rewrite_struct_pat(
 
     // ast::Pat doesn't have attrs so use &[]
     let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?;
-    Some(format!("{path_str} {{{fields_str}}}"))
+    Ok(format!("{path_str} {{{fields_str}}}"))
 }
 
 impl Rewrite for PatField {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         let hi_pos = if let Some(last) = self.attrs.last() {
             last.span.hi()
         } else {
@@ -393,10 +438,10 @@ impl Rewrite for PatField {
         let attrs_str = if self.attrs.is_empty() {
             String::from("")
         } else {
-            self.attrs.rewrite(context, shape)?
+            self.attrs.rewrite_result(context, shape)?
         };
 
-        let pat_str = self.pat.rewrite(context, shape)?;
+        let pat_str = self.pat.rewrite_result(context, shape)?;
         if self.is_shorthand {
             combine_strs_with_missing_comments(
                 context,
@@ -417,7 +462,7 @@ impl Rewrite for PatField {
                     "{}:\n{}{}",
                     id_str,
                     nested_shape.indent.to_string(context.config),
-                    self.pat.rewrite(context, nested_shape)?
+                    self.pat.rewrite_result(context, nested_shape)?
                 )
             };
             combine_strs_with_missing_comments(
@@ -440,9 +485,13 @@ pub(crate) enum TuplePatField<'a> {
 
 impl<'a> Rewrite for TuplePatField<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            TuplePatField::Pat(p) => p.rewrite(context, shape),
-            TuplePatField::Dotdot(_) => Some("..".to_string()),
+            TuplePatField::Pat(p) => p.rewrite_result(context, shape),
+            TuplePatField::Dotdot(_) => Ok("..".to_string()),
         }
     }
 }
@@ -492,9 +541,9 @@ fn rewrite_tuple_pat(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     if pats.is_empty() {
-        return Some(format!("{}()", path_str.unwrap_or_default()));
+        return Ok(format!("{}()", path_str.unwrap_or_default()));
     }
     let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
 
@@ -548,7 +597,7 @@ fn count_wildcard_suffix_len(
         ",",
         |item| item.span().lo(),
         |item| item.span().hi(),
-        |item| item.rewrite(context, shape),
+        |item| item.rewrite_result(context, shape),
         context.snippet_provider.span_after(span, "("),
         span.hi() - BytePos(1),
         false,
@@ -558,7 +607,7 @@ fn count_wildcard_suffix_len(
     for item in items
         .iter()
         .rev()
-        .take_while(|i| matches!(i.item, Some(ref internal_string) if internal_string == "_"))
+        .take_while(|i| matches!(i.item, Ok(ref internal_string) if internal_string == "_"))
     {
         suffix_len += 1;