From 2a64f212534481825be09c6cef8358ed2f881179 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 17 Nov 2024 20:55:48 -0600 Subject: [PATCH] Return Result from Shape methods --- src/attr.rs | 33 ++++++-------- src/chains.rs | 77 ++++++++++++++++--------------- src/closures.rs | 23 +++------- src/expr.rs | 118 +++++++++++++++++------------------------------- src/imports.rs | 17 ++----- src/items.rs | 83 +++++++++++++--------------------- src/lists.rs | 26 ++++++----- src/macros.rs | 12 ++--- src/matches.rs | 33 ++++++-------- src/overflow.rs | 6 +-- src/pairs.rs | 37 ++++++--------- src/patterns.rs | 17 +++---- src/reorder.rs | 2 +- src/rewrite.rs | 14 ++++++ src/shape.rs | 69 ++++++++++++++++++++++------ src/stmt.rs | 6 +-- src/types.rs | 47 +++++++------------ src/vertical.rs | 2 +- src/visitor.rs | 2 +- 19 files changed, 284 insertions(+), 340 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 5c2068b6a22..f29d6eab0e2 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -56,23 +56,22 @@ fn argument_shape( shape: Shape, context: &RewriteContext<'_>, ) -> Option { - match context.config.indent_style() { + let shape = match context.config.indent_style() { IndentStyle::Block => { if combine { - shape.offset_left(left) + shape.offset_left_opt(left)? } else { - Some( - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - ) + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) } } IndentStyle::Visual => shape .visual_indent(0) - .shrink_left(left) - .and_then(|s| s.sub_width(right)), - } + .shrink_left_opt(left)? + .sub_width_opt(right)?, + }; + Some(shape) } fn format_derive( @@ -127,8 +126,8 @@ fn format_derive( context, )?; let one_line_shape = shape - .offset_left("[derive()]".len() + prefix.len())? - .sub_width("()]".len())?; + .offset_left_opt("[derive()]".len() + prefix.len())? + .sub_width_opt("()]".len())?; let one_line_budget = one_line_shape.width; let tactic = definitive_tactic( @@ -297,7 +296,7 @@ impl Rewrite for ast::MetaItem { &path, list.iter(), // 1 = "]" - shape.sub_width(1).max_width_error(shape.width, self.span)?, + shape.sub_width(1, self.span)?, self.span, context.config.attr_fn_like_width(), Some(if has_trailing_comma { @@ -310,9 +309,7 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::NameValue(ref lit) => { let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?; // 3 = ` = ` - let lit_shape = shape - .shrink_left(path.len() + 3) - .max_width_error(shape.width, self.span)?; + let lit_shape = shape.shrink_left(path.len() + 3, self.span)?; // `rewrite_literal` returns `None` when `lit` exceeds max // width. Since a literal is basically unformattable unless it // is a string literal (and only if `format_strings` is set), @@ -369,9 +366,7 @@ impl Rewrite for ast::Attribute { } // 1 = `[` - let shape = shape - .offset_left(prefix.len() + 1) - .max_width_error(shape.width, self.span)?; + let shape = shape.offset_left(prefix.len() + 1, self.span)?; Ok(meta.rewrite_result(context, shape).map_or_else( |_| snippet.to_owned(), |rw| match &self.kind { diff --git a/src/chains.rs b/src/chains.rs index fd2ef9cb1db..acd0c2961b1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -67,7 +67,9 @@ use crate::config::{IndentStyle, StyleEdition}; use crate::expr::rewrite_call; use crate::lists::extract_pre_comment; use crate::macros::convert_try_mac; -use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; +use crate::rewrite::{ + ExceedsMaxWidthError, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult, +}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::utils::{ @@ -127,14 +129,15 @@ fn get_visual_style_child_shape( shape: Shape, offset: usize, parent_overflowing: bool, -) -> Option { + span: Span, +) -> Result { if !parent_overflowing { shape .with_max_width(context.config) - .offset_left(offset) + .offset_left(offset, span) .map(|s| s.visual_indent(0)) } else { - Some(shape.visual_indent(offset)) + Ok(shape.visual_indent(offset)) } } @@ -280,9 +283,7 @@ impl Rewrite for ChainItem { } fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { - let shape = shape - .sub_width(self.tries) - .max_width_error(shape.width, self.span)?; + let shape = shape.sub_width(self.tries, self.span)?; let rewrite = match self.kind { ChainItemKind::Parent { ref expr, @@ -559,9 +560,7 @@ impl Rewrite for Chain { let full_span = self.parent.span.with_hi(children_span.hi()); // Decide how to layout the rest of the chain. - let child_shape = formatter - .child_shape(context, shape) - .max_width_error(shape.width, children_span)?; + let child_shape = formatter.child_shape(context, shape, children_span)?; formatter.format_children(context, child_shape)?; formatter.format_last_child(context, shape, child_shape)?; @@ -590,7 +589,12 @@ trait ChainFormatter { context: &RewriteContext<'_>, shape: Shape, ) -> Result<(), RewriteError>; - fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; + fn child_shape( + &self, + context: &RewriteContext<'_>, + shape: Shape, + span: Span, + ) -> Result; fn format_children( &mut self, context: &RewriteContext<'_>, @@ -720,17 +724,11 @@ impl<'a> ChainFormatterShared<'a> { && self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; let last_shape = if all_in_one_line { - shape - .sub_width(last.tries) - .max_width_error(shape.width, last.span)? + shape.sub_width(last.tries, last.span)? } else if extendable { - child_shape - .sub_width(last.tries) - .max_width_error(child_shape.width, last.span)? + child_shape.sub_width(last.tries, last.span)? } else { - child_shape - .sub_width(shape.rhs_overhead(context.config) + last.tries) - .max_width_error(child_shape.width, last.span)? + child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries, last.span)? }; let mut last_subexpr_str = None; @@ -738,11 +736,11 @@ impl<'a> ChainFormatterShared<'a> { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. let one_line_shape = if context.use_block_indent() { - last_shape.offset_left(almost_total) + last_shape.offset_left_opt(almost_total) } else { last_shape .visual_indent(almost_total) - .sub_width(almost_total) + .sub_width_opt(almost_total) }; if let Some(one_line_shape) = one_line_shape { @@ -760,9 +758,10 @@ impl<'a> ChainFormatterShared<'a> { // layout, just by looking at the overflowed rewrite. Now we rewrite the // last child on its own line, and compare two rewrites to choose which is // better. - let last_shape = child_shape - .sub_width(shape.rhs_overhead(context.config) + last.tries) - .max_width_error(child_shape.width, last.span)?; + let last_shape = child_shape.sub_width( + shape.rhs_overhead(context.config) + last.tries, + last.span, + )?; match last.rewrite_result(context, last_shape) { Ok(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); @@ -787,9 +786,7 @@ impl<'a> ChainFormatterShared<'a> { let last_shape = if context.use_block_indent() { last_shape } else { - child_shape - .sub_width(shape.rhs_overhead(context.config) + last.tries) - .max_width_error(child_shape.width, last.span)? + child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries, last.span)? }; let last_subexpr_str = @@ -863,9 +860,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { if let ChainItemKind::Comment(..) = item.kind { break; } - let shape = shape - .offset_left(root_rewrite.len()) - .max_width_error(shape.width, item.span)?; + let shape = shape.offset_left(root_rewrite.len(), item.span)?; match &item.rewrite_result(context, shape) { Ok(rewrite) => root_rewrite.push_str(rewrite), Err(_) => break, @@ -883,9 +878,14 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { Ok(()) } - fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + fn child_shape( + &self, + context: &RewriteContext<'_>, + shape: Shape, + _span: Span, + ) -> Result { let block_end = self.root_ends_with_block; - Some(get_block_child_shape(block_end, context, shape)) + Ok(get_block_child_shape(block_end, context, shape)) } fn format_children( @@ -955,8 +955,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } let child_shape = parent_shape .visual_indent(self.offset) - .sub_width(self.offset) - .max_width_error(parent_shape.width, item.span)?; + .sub_width(self.offset, item.span)?; let rewrite = item.rewrite_result(context, child_shape)?; if filtered_str_fits(&rewrite, context.config.max_width(), shape) { root_rewrite.push_str(&rewrite); @@ -975,13 +974,19 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { Ok(()) } - fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + fn child_shape( + &self, + context: &RewriteContext<'_>, + shape: Shape, + span: Span, + ) -> Result { get_visual_style_child_shape( context, shape, self.offset, // TODO(calebcartwright): self.shared.permissibly_overflowing_parent, false, + span, ) } diff --git a/src/closures.rs b/src/closures.rs index a37b47e3bc9..1f59fbc2960 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -53,9 +53,7 @@ pub(crate) fn rewrite_closure( shape, )?; // 1 = space between `|...|` and body. - let body_shape = shape - .offset_left(extra_offset) - .max_width_error(shape.width, span)?; + let body_shape = shape.offset_left(extra_offset, span)?; if let ast::ExprKind::Block(ref block, _) = body.kind { // The body of the closure is an empty block. @@ -293,17 +291,12 @@ fn rewrite_closure_fn_decl( }; // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let nested_shape = shape - .shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len()) - .and_then(|shape| shape.sub_width(4)) - .max_width_error(shape.width, span)?; + let offset = binder.len() + const_.len() + immovable.len() + coro.len() + mover.len(); + let nested_shape = shape.shrink_left(offset, span)?.sub_width(4, span)?; // 1 = | let param_offset = nested_shape.indent + 1; - let param_shape = nested_shape - .offset_left(1) - .max_width_error(nested_shape.width, span)? - .visual_indent(0); + let param_shape = nested_shape.offset_left(1, span)?.visual_indent(0); let ret_str = fn_decl.output.rewrite_result(context, param_shape)?; let param_items = itemize_list( @@ -328,9 +321,7 @@ fn rewrite_closure_fn_decl( horizontal_budget, ); let param_shape = match tactic { - DefinitiveListTactic::Horizontal => param_shape - .sub_width(ret_str.len() + 1) - .max_width_error(param_shape.width, span)?, + DefinitiveListTactic::Horizontal => param_shape.sub_width(ret_str.len() + 1, span)?, _ => param_shape, }; @@ -401,9 +392,7 @@ pub(crate) fn rewrite_last_closure( return Err(RewriteError::Unknown); } - let body_shape = shape - .offset_left(extra_offset) - .max_width_error(shape.width, expr.span)?; + let body_shape = shape.offset_left(extra_offset, expr.span)?; // We force to use block for the body of the closure for certain kinds of expressions. if is_block_closure_forced(context, body) { diff --git a/src/expr.rs b/src/expr.rs index 77c9818b66b..068af184e3c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -70,7 +70,7 @@ pub(crate) fn format_expr( return Ok(context.snippet(expr.span()).to_owned()); } let shape = if expr_type == ExprType::Statement && semicolon_for_expr(context, expr) { - shape.sub_width(1).max_width_error(shape.width, expr.span)? + shape.sub_width(1, expr.span)? } else { shape }; @@ -534,9 +534,7 @@ fn rewrite_single_line_block( shape: Shape, ) -> RewriteResult { if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) { - let expr_shape = shape - .offset_left(last_line_width(prefix)) - .max_width_error(shape.width, block_expr.span())?; + let expr_shape = shape.offset_left(last_line_width(prefix), block_expr.span())?; let expr_str = block_expr.rewrite_result(context, expr_shape)?; let label_str = rewrite_label(context, label); let result = format!("{prefix}{label_str}{{ {expr_str} }}"); @@ -650,8 +648,8 @@ pub(crate) fn rewrite_cond( ast::ExprKind::Match(ref cond, _, MatchKind::Prefix) => { // `match `cond` {` let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, - IndentStyle::Block => shape.offset_left(8)?, + IndentStyle::Visual => shape.shrink_left_opt(6).and_then(|s| s.sub_width_opt(2))?, + IndentStyle::Block => shape.offset_left_opt(8)?, }; cond.rewrite(context, cond_shape) } @@ -888,9 +886,7 @@ impl<'a> ControlFlow<'a> { ) -> RewriteResult { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr); - let cond_shape = shape - .offset_left(offset) - .max_width_error(shape.width, expr.span)?; + let cond_shape = shape.offset_left(offset, expr.span)?; if let Some(pat) = self.pat { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() @@ -898,9 +894,8 @@ impl<'a> ControlFlow<'a> { format!("{} ", self.matcher) }; let pat_shape = cond_shape - .offset_left(matcher.len()) - .and_then(|s| s.sub_width(self.connector.len())) - .max_width_error(cond_shape.width, pat.span)?; + .offset_left(matcher.len(), pat.span)? + .sub_width(self.connector.len(), pat.span)?; let pat_string = pat.rewrite_result(context, pat_shape)?; let comments_lo = context .snippet_provider @@ -950,9 +945,7 @@ impl<'a> ControlFlow<'a> { let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - fresh_shape - .offset_left(7) - .max_width_error(fresh_shape.width, self.span)? + fresh_shape.offset_left(7, self.span)? } else { fresh_shape }; @@ -1514,10 +1507,7 @@ pub(crate) fn rewrite_paren( } // 1 = `(` and `)` - let sub_shape = shape - .offset_left(1) - .and_then(|s| s.sub_width(1)) - .max_width_error(shape.width, span)?; + let sub_shape = shape.offset_left(1, span)?.sub_width(1, span)?; let subexpr_str = subexpr.rewrite_result(context, sub_shape)?; let fits_single_line = !pre_comment.contains("//") && !post_comment.contains("//"); if fits_single_line { @@ -1570,18 +1560,21 @@ fn rewrite_index( let rhs_overhead = shape.rhs_overhead(context.config); let index_shape = if expr_str.contains('\n') { Shape::legacy(context.config.max_width(), shape.indent) - .offset_left(offset) - .and_then(|shape| shape.sub_width(1 + rhs_overhead)) + .offset_left(offset, index.span()) + .and_then(|shape| shape.sub_width(1 + rhs_overhead, index.span())) } else { match context.config.indent_style() { IndentStyle::Block => shape - .offset_left(offset) - .and_then(|shape| shape.sub_width(1)), - IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1), + .offset_left(offset, index.span()) + .and_then(|shape| shape.sub_width(1, index.span())), + IndentStyle::Visual => shape + .visual_indent(offset) + .sub_width(offset + 1, index.span()), } - } - .max_width_error(shape.width, index.span()); - let orig_index_rw = index_shape.and_then(|s| index.rewrite_result(context, s)); + }; + let orig_index_rw = index_shape + .map_err(RewriteError::from) + .and_then(|s| index.rewrite_result(context, s)); // Return if index fits in a single line. match orig_index_rw { @@ -1594,11 +1587,8 @@ fn rewrite_index( // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(context.config); let index_shape = Shape::indented(indent, context.config) - .offset_left(1) - .max_width_error(shape.width, index.span())?; - let index_shape = index_shape - .sub_width(1 + rhs_overhead) - .max_width_error(index_shape.width, index.span())?; + .offset_left(1, index.span())? + .sub_width(1 + rhs_overhead, index.span())?; let new_index_rw = index.rewrite_result(context, index_shape); match (orig_index_rw, new_index_rw) { (_, Ok(ref new_index_str)) if !new_index_str.contains('\n') => Ok(format!( @@ -1644,7 +1634,7 @@ fn rewrite_struct_lit<'a>( } // 2 = " {".len() - let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?; + let path_shape = shape.sub_width(2, span)?; let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?; let has_base_or_rest = match struct_rest { @@ -1657,8 +1647,7 @@ fn rewrite_struct_lit<'a>( }; // Foo { a: Foo } - indent is +3, width is -5. - let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2) - .max_width_error(shape.width, span)?; + let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2, span)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); @@ -1701,22 +1690,12 @@ fn rewrite_struct_lit<'a>( let rewrite = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => { // The 1 taken from the v_budget is for the comma. - rewrite_field( - context, - field, - v_shape.sub_width(1).max_width_error(v_shape.width, span)?, - 0, - ) + rewrite_field(context, field, v_shape.sub_width(1, span)?, 0) } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite_result( - context, - v_shape - .offset_left(2) - .max_width_error(v_shape.width, span)?, - ) - .map(|s| format!("..{}", s)) + expr.rewrite_result(context, v_shape.offset_left(2, span)?) + .map(|s| format!("..{}", s)) } StructLitField::Rest(_) => Ok("..".to_owned()), }; @@ -1823,9 +1802,7 @@ pub(crate) fn rewrite_field( separator.push(' '); } let overhead = name.len() + separator.len(); - let expr_shape = shape - .offset_left(overhead) - .max_width_error(shape.width, field.span)?; + let expr_shape = shape.offset_left(overhead, field.span)?; let expr = field.expr.rewrite_result(context, expr_shape); let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_)); match expr { @@ -1865,10 +1842,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); if is_singleton_tuple { // 3 = "(" + ",)" - let nested_shape = shape - .sub_width(3) - .max_width_error(shape.width, span)? - .visual_indent(1); + let nested_shape = shape.sub_width(3, span)?.visual_indent(1); return items .next() .unwrap() @@ -1877,10 +1851,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( } let list_lo = context.snippet_provider.span_after(span, "("); - let nested_shape = shape - .sub_width(2) - .max_width_error(shape.width, span)? - .visual_indent(1); + let nested_shape = shape.sub_width(2, span)?.visual_indent(1); let items = itemize_list( context.snippet_provider, items, @@ -1919,9 +1890,7 @@ fn rewrite_let( // TODO(ytmimi) comments could appear between `let` and the `pat` // 4 = "let ".len() - let pat_shape = shape - .offset_left(4) - .max_width_error(shape.width, pat.span)?; + let pat_shape = shape.offset_left(4, pat.span)?; let pat_str = pat.rewrite_result(context, pat_shape)?; result.push_str(&pat_str); @@ -1985,9 +1954,7 @@ pub(crate) fn rewrite_unary_prefix( rewrite: &R, shape: Shape, ) -> RewriteResult { - let shape = shape - .offset_left(prefix.len()) - .max_width_error(shape.width, rewrite.span())?; + let shape = shape.offset_left(prefix.len(), rewrite.span())?; rewrite .rewrite_result(context, shape) .map(|r| format!("{}{}", prefix, r)) @@ -2001,9 +1968,7 @@ pub(crate) fn rewrite_unary_suffix( rewrite: &R, shape: Shape, ) -> RewriteResult { - let shape = shape - .sub_width(suffix.len()) - .max_width_error(shape.width, rewrite.span())?; + let shape = shape.sub_width(suffix.len(), rewrite.span())?; rewrite.rewrite_result(context, shape).map(|mut r| { r.push_str(suffix); r @@ -2061,9 +2026,7 @@ fn rewrite_assignment( }; // 1 = space between lhs and operator. - let lhs_shape = shape - .sub_width(operator_str.len() + 1) - .max_width_error(shape.width, lhs.span())?; + let lhs_shape = shape.sub_width(operator_str.len() + 1, lhs.span())?; let lhs_str = format!( "{} {}", lhs.rewrite_result(context, lhs_shape)?, @@ -2117,7 +2080,7 @@ pub(crate) fn rewrite_assign_rhs_expr( 0 }); // 1 = space between operator and rhs. - let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { + let orig_shape = shape.offset_left_opt(last_line_width + 1).unwrap_or(Shape { width: 0, offset: shape.offset + last_line_width + 1, ..shape @@ -2165,9 +2128,10 @@ pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite + Spa let lhs = lhs.into(); let contains_comment = contains_comment(context.snippet(between_span)); let shape = if contains_comment { - shape - .block_left(context.config.tab_spaces()) - .max_width_error(shape.width, between_span.with_hi(ex.span().hi()))? + shape.block_left( + context.config.tab_spaces(), + between_span.with_hi(ex.span().hi()), + )? } else { shape }; @@ -2244,10 +2208,10 @@ fn shape_from_rhs_tactic( match rhs_tactic { RhsTactics::ForceNextLineWithoutIndent => shape .with_max_width(context.config) - .sub_width(shape.indent.width()), + .sub_width_opt(shape.indent.width()), RhsTactics::Default | RhsTactics::AllowOverflow => { Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(shape.rhs_overhead(context.config)) + .sub_width_opt(shape.rhs_overhead(context.config)) } } } diff --git a/src/imports.rs b/src/imports.rs index 52b6e057a83..cfc2f3bda19 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -338,12 +338,7 @@ impl UseTree { crate::utils::format_visibility(context, vis) }); let use_str = self - .rewrite_result( - context, - shape - .offset_left(vis.len()) - .max_width_error(shape.width, self.span())?, - ) + .rewrite_result(context, shape.offset_left(vis.len(), self.span())?) .map(|s| { if s.is_empty() { s @@ -1024,7 +1019,7 @@ fn rewrite_nested_use_tree( IndentStyle::Block => shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config) - .sub_width(1) + .sub_width_opt(1) .unknown_error()?, IndentStyle::Visual => shape.visual_indent(0), }; @@ -1115,8 +1110,8 @@ impl Rewrite for UseSegment { use_tree_list, // 1 = "{" and "}" shape - .offset_left(1) - .and_then(|s| s.sub_width(1)) + .offset_left_opt(1) + .and_then(|s| s.sub_width_opt(1)) .unknown_error()?, )? } @@ -1139,9 +1134,7 @@ impl Rewrite for UseTree { if iter.peek().is_some() { result.push_str("::"); // 2 = "::" - shape = shape - .offset_left(2 + segment_str.len()) - .max_width_error(shape.width, self.span())?; + shape = shape.offset_left(2 + segment_str.len(), self.span())?; } } Ok(result) diff --git a/src/items.rs b/src/items.rs index cf4c40c3c7a..28dfb718af6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -82,13 +82,9 @@ impl Rewrite for ast::Local { let let_kw_offset = result.len() - "let ".len(); // 4 = "let ".len() - let pat_shape = shape - .offset_left(4) - .max_width_error(shape.width, self.span())?; + let pat_shape = shape.offset_left(4, self.span())?; // 1 = ; - let pat_shape = pat_shape - .sub_width(1) - .max_width_error(shape.width, self.span())?; + let pat_shape = pat_shape.sub_width(1, self.span())?; let pat_str = self.pat.rewrite_result(context, pat_shape)?; result.push_str(&pat_str); @@ -104,11 +100,9 @@ impl Rewrite for ast::Local { } else { shape } - .offset_left(last_line_width(&result) + separator.len()) - .max_width_error(shape.width, self.span())? + .offset_left(last_line_width(&result) + separator.len(), self.span())? // 2 = ` =` - .sub_width(2) - .max_width_error(shape.width, self.span())?; + .sub_width(2, self.span())?; let rewrite = ty.rewrite_result(context, ty_shape)?; @@ -127,9 +121,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) - .max_width_error(shape.width, self.span())?; + let nested_shape = shape.sub_width(1, self.span())?; result = rewrite_assign_rhs( context, @@ -648,7 +640,7 @@ impl<'a> FmtVisitor<'a> { items = itemize_list_with(0); } - let shape = self.shape().sub_width(2)?; + let shape = self.shape().sub_width_opt(2)?; let fmt = ListFormatting::new(shape, self.config) .trailing_separator(self.config.trailing_comma()) .preserve_newline(true); @@ -679,10 +671,10 @@ impl<'a> FmtVisitor<'a> { field.attrs.rewrite(&context, shape)? } else { // StyleEdition::Edition20{15|18|21} formatting that was off by 1. See issue #5801 - field.attrs.rewrite(&context, shape.sub_width(1)?)? + field.attrs.rewrite(&context, shape.sub_width_opt(1)?)? }; // sub_width(1) to take the trailing comma into account - let shape = shape.sub_width(1)?; + let shape = shape.sub_width_opt(1)?; let lo = field .attrs @@ -1184,7 +1176,7 @@ pub(crate) fn format_trait( let body_lo = context.snippet_provider.span_after(item.span, "{"); - let shape = Shape::indented(offset, context.config).offset_left(result.len())?; + let shape = Shape::indented(offset, context.config).offset_left_opt(result.len())?; let generics_str = rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?; result.push_str(&generics_str); @@ -1386,7 +1378,7 @@ pub(crate) fn format_trait_alias( ) -> Option { let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" - let g_shape = shape.offset_left(6)?.sub_width(2)?; + let g_shape = shape.offset_left_opt(6)?.sub_width_opt(2)?; let generics_str = rewrite_generics(context, alias, generics, g_shape).ok()?; let vis_str = format_visibility(context, vis); let lhs = format!("{vis_str}trait {generics_str} ="); @@ -1400,7 +1392,7 @@ pub(crate) fn format_trait_alias( lhs, &trait_alias_bounds, &RhsAssignKind::Bounds, - shape.sub_width(1)?, + shape.sub_width_opt(1)?, ) .map(|s| s + ";") .ok() @@ -1507,7 +1499,7 @@ pub(crate) fn format_struct_struct( let items_str = rewrite_with_alignment( fields, context, - Shape::indented(offset.block_indent(context.config), context.config).sub_width(1)?, + Shape::indented(offset.block_indent(context.config), context.config).sub_width_opt(1)?, mk_sp(body_lo, span.hi()), one_line_budget, )?; @@ -1643,12 +1635,12 @@ fn format_tuple_struct( let inner_span = mk_sp(body_lo, body_hi); format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")"); } else { - let shape = Shape::indented(offset, context.config).sub_width(1)?; let lo = if let Some(generics) = struct_parts.generics { generics.span.hi() } else { struct_parts.ident.span.hi() }; + let shape = Shape::indented(offset, context.config).sub_width_opt(1)?; result = overflow::rewrite_with_parens( context, &result, @@ -1778,9 +1770,8 @@ fn rewrite_ty( // 2 = `= ` let g_shape = Shape::indented(indent, context.config); let g_shape = g_shape - .offset_left(result.len()) - .and_then(|s| s.sub_width(2)) - .max_width_error(g_shape.width, span)?; + .offset_left(result.len(), span)? + .sub_width(2, span)?; let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?; result.push_str(&generics_str); } @@ -1789,9 +1780,7 @@ fn rewrite_ty( if !bounds.is_empty() { // 2 = `: ` let shape = Shape::indented(indent, context.config); - let shape = shape - .offset_left(result.len() + 2) - .max_width_error(shape.width, span)?; + let shape = shape.offset_left(result.len() + 2, span)?; let type_bounds = bounds .rewrite_result(context, shape) .map(|s| format!(": {}", s))?; @@ -1852,9 +1841,7 @@ fn rewrite_ty( Shape::indented(indent, context.config) } else { let shape = Shape::indented(indent, context.config); - shape - .block_left(context.config.tab_spaces()) - .max_width_error(shape.width, span)? + shape.block_left(context.config.tab_spaces(), span)? }; combine_strs_with_missing_comments( @@ -1872,9 +1859,7 @@ fn rewrite_ty( // 1 = `;` unless there's a trailing where clause let shape = Shape::indented(indent, context.config); let shape = if after_where_predicates.is_empty() { - Shape::indented(indent, context.config) - .sub_width(1) - .max_width_error(shape.width, span)? + Shape::indented(indent, context.config).sub_width(1, span)? } else { shape }; @@ -1983,7 +1968,7 @@ pub(crate) fn rewrite_struct_field( } let orig_ty = shape - .offset_left(overhead + spacing.len()) + .offset_left_opt(overhead + spacing.len()) .and_then(|ty_shape| field.ty.rewrite_result(context, ty_shape).ok()); if let Some(ref ty) = orig_ty { @@ -2098,7 +2083,7 @@ fn rewrite_static( ); // 2 = " =".len() let ty_shape = - Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; + Shape::indented(offset.block_only(), context.config).offset_left_opt(prefix.len() + 2)?; let ty_str = match static_parts.ty.rewrite(context, ty_shape) { Some(ty_str) => ty_str, None => { @@ -2154,7 +2139,7 @@ struct OpaqueType<'a> { impl<'a> Rewrite for OpaqueType<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let shape = shape.offset_left(5)?; // `impl ` + let shape = shape.offset_left_opt(5)?; // `impl ` self.bounds .rewrite(context, shape) .map(|s| format!("impl {}", s)) @@ -2186,9 +2171,7 @@ impl Rewrite for ast::FnRetTy { .map(|r| format!("-> {}", r)); } - let shape = shape - .offset_left(arrow_width) - .max_width_error(shape.width, self.span())?; + let shape = shape.offset_left(arrow_width, self.span())?; ty.rewrite_result(context, shape) .map(|s| format!("-> {}", s)) @@ -2635,7 +2618,7 @@ fn rewrite_fn_base( // Aligning with nonexistent params looks silly. force_new_line_for_brace = true; ret_shape = if context.use_block_indent() { - ret_shape.offset_left(4).unwrap_or(ret_shape) + ret_shape.offset_left_opt(4).unwrap_or(ret_shape) } else { ret_shape.indent = ret_shape.indent + 4; ret_shape @@ -2656,7 +2639,7 @@ fn rewrite_fn_base( let ret_shape = Shape::indented(indent, context.config); ret_shape - .offset_left(last_line_width(&result)) + .offset_left_opt(last_line_width(&result)) .unwrap_or(ret_shape) }; @@ -2978,14 +2961,14 @@ fn rewrite_generics( fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { match config.indent_style() { - IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), + IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width_opt(offset + 2), IndentStyle::Block => { // 1 = "," shape .block() .block_indent(config.tab_spaces()) .with_max_width(config) - .sub_width(1) + .sub_width_opt(1) } } } @@ -3013,9 +2996,8 @@ fn rewrite_where_clause_rfc_style( let clause_shape = shape .block() .with_max_width(context.config) - .block_left(context.config.tab_spaces()) - .and_then(|s| s.sub_width(1)) - .max_width_error(shape.width, where_span)?; + .block_left(context.config.tab_spaces(), where_span)? + .sub_width(1, where_span)?; let force_single_line = context.config.where_single_line() && predicates.len() == 1 && !where_clause_option.veto_single_line; @@ -3055,9 +3037,8 @@ fn rewrite_where_keyword( let block_shape = shape.block().with_max_width(context.config); // 1 = `,` let clause_shape = block_shape - .block_left(context.config.tab_spaces()) - .and_then(|s| s.sub_width(1)) - .max_width_error(block_shape.width, where_span)?; + .block_left(context.config.tab_spaces(), where_span)? + .sub_width(1, where_span)?; let comment_separator = |comment: &str, shape: Shape| { if comment.is_empty() { @@ -3486,9 +3467,7 @@ impl Rewrite for ast::ForeignItem { prefix, &static_foreign_item.ty, &RhsAssignKind::Ty, - shape - .sub_width(1) - .max_width_error(shape.width, static_foreign_item.ty.span)?, + shape.sub_width(1, static_foreign_item.ty.span)?, ) .map(|s| s + ";") } diff --git a/src/lists.rs b/src/lists.rs index 415144a8abc..9d811e5d9b5 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -3,12 +3,12 @@ use std::cmp; use std::iter::Peekable; -use rustc_span::BytePos; +use rustc_span::{BytePos, Span}; use crate::comment::{FindUncommented, find_comment_end, rewrite_comment}; use crate::config::lists::*; use crate::config::{Config, IndentStyle}; -use crate::rewrite::{RewriteContext, RewriteError, RewriteResult}; +use crate::rewrite::{ExceedsMaxWidthError, RewriteContext, RewriteError, RewriteResult}; use crate::shape::{Indent, Shape}; use crate::utils::{ count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline, @@ -865,12 +865,13 @@ pub(crate) fn struct_lit_shape( context: &RewriteContext<'_>, prefix_width: usize, suffix_width: usize, -) -> Option<(Option, Shape)> { + span: Span, +) -> Result<(Option, Shape), ExceedsMaxWidthError> { let v_shape = match context.config.indent_style() { IndentStyle::Visual => shape .visual_indent(0) - .shrink_left(prefix_width)? - .sub_width(suffix_width)?, + .shrink_left(prefix_width, span)? + .sub_width(suffix_width, span)?, IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); Shape { @@ -879,13 +880,14 @@ pub(crate) fn struct_lit_shape( } } }; - let shape_width = shape.width.checked_sub(prefix_width + suffix_width); - if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.struct_lit_width()); - Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) - } else { - Some((None, v_shape)) - } + let h_shape = shape + .width + .checked_sub(prefix_width + suffix_width) + .map(|w| { + let shape_width = cmp::min(w, context.config.struct_lit_width()); + Shape::legacy(shape_width, shape.indent) + }); + Ok((h_shape, v_shape)) } // Compute the tactic for the internals of a struct-lit-like thing. diff --git a/src/macros.rs b/src/macros.rs index 5a35e115d8f..c37273eb0f3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -381,9 +381,7 @@ fn handle_vec_semi( }; // Should we return MaxWidthError, Or Macro failure - let mac_shape = shape - .offset_left(macro_name.len()) - .max_width_error(shape.width, span)?; + let mac_shape = shape.offset_left(macro_name.len(), span)?; // 8 = `vec![]` + `; ` or `vec!()` + `; ` let total_overhead = 8; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); @@ -1294,9 +1292,7 @@ impl MacroBranch { let mut result = format_macro_args( context, self.args.clone(), - shape - .sub_width(prefix_width) - .max_width_error(shape.width, self.span)?, + shape.sub_width(prefix_width, self.span)?, )?; if multi_branch_style { @@ -1445,9 +1441,7 @@ fn format_lazy_static( stmt, &*expr, &RhsAssignKind::Expr(&expr.kind, expr.span), - nested_shape - .sub_width(1) - .max_width_error(nested_shape.width, expr.span)?, + nested_shape.sub_width(1, expr.span)?, )?); result.push(';'); if i != last { diff --git a/src/matches.rs b/src/matches.rs index 8f62648e576..2955f5d119a 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -87,12 +87,8 @@ pub(crate) fn rewrite_match( }; // 6 = `match ` let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => cond_shape - .shrink_left(6) - .max_width_error(shape.width, span)?, - IndentStyle::Block => cond_shape - .offset_left(6) - .max_width_error(shape.width, span)?, + IndentStyle::Visual => cond_shape.shrink_left(6, span)?, + IndentStyle::Block => cond_shape.offset_left(6, span)?, }; let cond_str = cond.rewrite_result(context, cond_shape)?; let alt_block_sep = &shape.indent.to_string_with_newline(context.config); @@ -279,16 +275,14 @@ fn rewrite_match_arm( // 7 = ` => : {` let label_len = label.ident.as_str().len(); shape - .sub_width(7 + label_len) - .and_then(|s| s.offset_left(pipe_offset)) - .max_width_error(shape.width, arm.span)? + .sub_width(7 + label_len, arm.span)? + .offset_left(pipe_offset, arm.span)? } _ => { // 5 = ` => {` shape - .sub_width(5) - .and_then(|s| s.offset_left(pipe_offset)) - .max_width_error(shape.width, arm.span)? + .sub_width(5, arm.span)? + .offset_left(pipe_offset, arm.span)? } }; let pats_str = arm.pat.rewrite_result(context, pat_shape)?; @@ -404,7 +398,7 @@ fn rewrite_match_body( let (extend, body) = flatten_arm_body( context, body, - shape.offset_left(extra_offset(pats_str, shape) + 4), + shape.offset_left_opt(extra_offset(pats_str, shape) + 4), ); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.kind { (true, is_empty_block(context, block, Some(&body.attrs))) @@ -514,8 +508,8 @@ fn rewrite_match_body( // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() let orig_body_shape = shape - .offset_left(extra_offset(pats_str, shape) + 4) - .and_then(|shape| shape.sub_width(comma.len())); + .offset_left_opt(extra_offset(pats_str, shape) + 4) + .and_then(|shape| shape.sub_width_opt(comma.len())); let orig_body = if forbid_same_line || !arrow_comment.is_empty() { Err(RewriteError::Unknown) } else if let Some(body_shape) = orig_body_shape { @@ -580,8 +574,8 @@ fn rewrite_guard( // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` let cond_shape = shape - .offset_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)); + .offset_left_opt(pattern_width + 4) + .and_then(|s| s.sub_width_opt(5)); if !multiline_pattern { if let Some(cond_shape) = cond_shape { if let Ok(cond_str) = guard.rewrite_result(context, cond_shape) { @@ -595,9 +589,8 @@ fn rewrite_guard( // Not enough space to put the guard after the pattern, try a newline. // 3 = `if `, 5 = ` => {` let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) - .offset_left(3) - .and_then(|s| s.sub_width(5)) - .max_width_error(shape.width, guard.span)?; + .offset_left(3, guard.span)? + .sub_width(5, guard.span)?; let cond_str = guard.rewrite_result(context, cond_shape)?; Ok(format!( "{}if {}", diff --git a/src/overflow.rs b/src/overflow.rs index fdc8e23e72b..4c51b853b9f 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -387,8 +387,8 @@ impl<'a> Context<'a> { // 1 = "(" or ")" let one_line_shape = shape - .offset_left(last_line_width(ident) + 1) - .and_then(|shape| shape.sub_width(1)) + .offset_left_opt(last_line_width(ident) + 1) + .and_then(|shape| shape.sub_width_opt(1)) .unwrap_or(Shape { width: 0, ..shape }); let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1); Context { @@ -774,7 +774,7 @@ fn last_item_shape( width: min(args_max_width, shape.width), ..shape } - .offset_left(offset) + .offset_left_opt(offset) } fn shape_from_indent_style( diff --git a/src/pairs.rs b/src/pairs.rs index 9c51298416b..c50b44755b2 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -86,7 +86,7 @@ fn rewrite_pairs_one_line( let prefix_len = result.len(); let last = list.list.last()?.0; - let cur_shape = base_shape.offset_left(last_line_width(&result))?; + let cur_shape = base_shape.offset_left_opt(last_line_width(&result))?; let last_rewrite = last.rewrite(context, cur_shape)?; result.push_str(&last_rewrite); @@ -116,8 +116,7 @@ fn rewrite_pairs_multiline( IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), }) .with_max_width(context.config) - .sub_width(rhs_offset) - .max_width_error(shape.width, list.span)?; + .sub_width(rhs_offset, list.span)?; let indent_str = nested_shape.indent.to_string_with_newline(context.config); let mut result = String::new(); @@ -136,7 +135,7 @@ fn rewrite_pairs_multiline( if last_line_width(&result) + offset <= nested_shape.used_width() { // We must snuggle the next line onto the previous line to avoid an orphan. if let Some(line_shape) = - shape.offset_left(s.len() + 2 + trimmed_last_line_width(&result)) + shape.offset_left_opt(s.len() + 2 + trimmed_last_line_width(&result)) { if let Ok(rewrite) = e.rewrite_result(context, line_shape) { result.push(' '); @@ -194,12 +193,11 @@ where // Try to put both lhs and rhs on the same line. let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .max_width_error(shape.width, rhs.span()) - .and_then(|rhs_shape| rhs.rewrite_result(context, rhs_shape)); + .offset_left_opt(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width_opt(pp.suffix.len())) + .and_then(|rhs_shape| rhs.rewrite_result(context, rhs_shape).ok()); - if let Ok(ref rhs_result) = rhs_orig_result { + if let Some(ref rhs_result) = rhs_orig_result { // If the length of the lhs is equal to or shorter than the tab width or // the rhs looks like block expression, we put the rhs on the same // line with the lhs even if the rhs is multi-lined. @@ -227,15 +225,13 @@ where // Re-evaluate the rhs because we have more space now: let mut rhs_shape = match context.config.indent_style() { IndentStyle::Visual => shape - .sub_width(pp.suffix.len() + pp.prefix.len()) - .max_width_error(shape.width, rhs.span())? + .sub_width(pp.suffix.len() + pp.prefix.len(), rhs.span())? .visual_indent(pp.prefix.len()), IndentStyle::Block => { // Try to calculate the initial constraint on the right hand side. let rhs_overhead = shape.rhs_overhead(context.config); Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead) - .max_width_error(shape.width, rhs.span())? + .sub_width(rhs_overhead, rhs.span())? } }; let infix = match separator_place { @@ -243,9 +239,7 @@ where SeparatorPlace::Front => pp.infix.trim_start(), }; if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape - .offset_left(infix.len()) - .max_width_error(rhs_shape.width, rhs.span())?; + rhs_shape = rhs_shape.offset_left(infix.len(), rhs.span())?; } let rhs_result = rhs.rewrite_result(context, rhs_shape)?; let indent_str = rhs_shape.indent.to_string_with_newline(context.config); @@ -325,15 +319,10 @@ impl FlattenPair for ast::Expr { IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), }) .with_max_width(context.config) - .sub_width(rhs_offset) - .max_width_error(shape.width, node.span)?; + .sub_width(rhs_offset, node.span)?; let default_shape = match context.config.binop_separator() { - SeparatorPlace::Back => nested_shape - .sub_width(nested_overhead) - .max_width_error(nested_shape.width, node.span)?, - SeparatorPlace::Front => nested_shape - .offset_left(nested_overhead) - .max_width_error(nested_shape.width, node.span)?, + SeparatorPlace::Back => nested_shape.sub_width(nested_overhead, node.span)?, + SeparatorPlace::Front => nested_shape.offset_left(nested_overhead, node.span)?, }; node.rewrite_result(context, default_shape) }; diff --git a/src/patterns.rs b/src/patterns.rs index 6fe2d4a8520..7e7b2908c6c 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -332,10 +332,7 @@ impl Rewrite for Pat { PatKind::Paren(ref pat) => pat .rewrite_result( context, - shape - .offset_left(1) - .and_then(|s| s.sub_width(1)) - .max_width_error(shape.width, self.span)?, + shape.offset_left(1, self.span)?.sub_width(1, self.span)?, ) .map(|inner_pat| format!("({})", inner_pat)), PatKind::Err(_) => Err(RewriteError::Unknown), @@ -354,7 +351,7 @@ fn rewrite_struct_pat( shape: Shape, ) -> RewriteResult { // 2 = ` {` - let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?; + let path_shape = shape.sub_width(2, span)?; let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?; if fields.is_empty() && !ellipsis { @@ -364,9 +361,13 @@ fn rewrite_struct_pat( 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) - .max_width_error(shape.width, span)?; + let (h_shape, v_shape) = struct_lit_shape( + shape, + context, + path_str.len() + 3, + ellipsis_str.len() + 2, + span, + )?; let items = itemize_list( context.snippet_provider, diff --git a/src/reorder.rs b/src/reorder.rs index 3df05b885e3..012e3c67021 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -138,7 +138,7 @@ fn rewrite_reorderable_or_regroupable_items( } // 4 = "use ", 1 = ";" - let nested_shape = shape.offset_left(4)?.sub_width(1)?; + let nested_shape = shape.offset_left_opt(4)?.sub_width_opt(1)?; let item_vec: Vec<_> = regrouped_items .into_iter() .filter(|use_group| !use_group.is_empty()) diff --git a/src/rewrite.rs b/src/rewrite.rs index 83020709797..7ca1ca522ff 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -63,6 +63,20 @@ pub(crate) enum RewriteError { Unknown, } +pub(crate) struct ExceedsMaxWidthError { + pub configured_width: usize, + pub span: Span, +} + +impl From for RewriteError { + fn from(error: ExceedsMaxWidthError) -> Self { + RewriteError::ExceedsMaxWidth { + configured_width: error.configured_width, + span: error.span, + } + } +} + /// Extension trait used to conveniently convert to RewriteError pub(crate) trait RewriteErrorExt { fn max_width_error(self, width: usize, span: Span) -> Result; diff --git a/src/shape.rs b/src/shape.rs index 40704bce307..c1c040f1f63 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use std::cmp::min; use std::ops::{Add, Sub}; +use rustc_span::Span; + use crate::Config; +use crate::rewrite::ExceedsMaxWidthError; #[derive(Copy, Clone, Debug)] pub(crate) struct Indent { @@ -213,8 +216,12 @@ impl Shape { } } - pub(crate) fn block_left(&self, delta: usize) -> Option { - self.block_indent(delta).sub_width(delta) + pub(crate) fn block_left( + &self, + delta: usize, + span: Span, + ) -> Result { + self.block_indent(delta).sub_width(delta, span) } pub(crate) fn add_offset(&self, delta: usize) -> Shape { @@ -232,26 +239,55 @@ impl Shape { } pub(crate) fn saturating_sub_width(&self, delta: usize) -> Shape { - self.sub_width(delta).unwrap_or(Shape { width: 0, ..*self }) + Shape { + width: self.width.saturating_sub(delta), + ..*self + } } - pub(crate) fn sub_width(&self, n: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(n)?, - ..*self - }) + pub(crate) fn sub_width( + &self, + delta: usize, + span: Span, + ) -> Result { + self.sub_width_opt(delta) + .ok_or_else(|| self.exceeds_max_width_error(span)) + } + + pub(crate) fn sub_width_opt(&self, delta: usize) -> Option { + self.width + .checked_sub(delta) + .map(|width| Shape { width, ..*self }) } - pub(crate) fn shrink_left(&self, delta: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(delta)?, + pub(crate) fn shrink_left( + &self, + delta: usize, + span: Span, + ) -> Result { + self.shrink_left_opt(delta) + .ok_or_else(|| self.exceeds_max_width_error(span)) + } + + pub(crate) fn shrink_left_opt(&self, delta: usize) -> Option { + self.width.checked_sub(delta).map(|width| Shape { + width, indent: self.indent + delta, offset: self.offset + delta, }) } - pub(crate) fn offset_left(&self, delta: usize) -> Option { - self.add_offset(delta).sub_width(delta) + pub(crate) fn offset_left( + &self, + delta: usize, + span: Span, + ) -> Result { + self.offset_left_opt(delta) + .ok_or_else(|| self.exceeds_max_width_error(span)) + } + + pub(crate) fn offset_left_opt(&self, delta: usize) -> Option { + self.add_offset(delta).sub_width_opt(delta) } pub(crate) fn used_width(&self) -> usize { @@ -285,6 +321,13 @@ impl Shape { ..*self } } + + fn exceeds_max_width_error(&self, span: Span) -> ExceedsMaxWidthError { + ExceedsMaxWidthError { + configured_width: self.width, + span, + } + } } #[cfg(test)] diff --git a/src/stmt.rs b/src/stmt.rs index 2788159018d..76194421c84 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -4,7 +4,7 @@ use rustc_span::Span; use crate::comment::recover_comment_removed; use crate::config::StyleEdition; use crate::expr::{ExprType, format_expr, is_simple_block}; -use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteResult}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; use crate::spanned::Spanned; @@ -132,9 +132,7 @@ fn format_stmt( "" }; - let shape = shape - .sub_width(suffix.len()) - .max_width_error(shape.width, ex.span())?; + let shape = shape.sub_width(suffix.len(), ex.span())?; format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => { diff --git a/src/types.rs b/src/types.rs index 07b483b2b37..6955415d5cd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -67,7 +67,7 @@ pub(crate) fn rewrite_path( } // 3 = ">::".len() - let shape = shape.sub_width(3).max_width_error(shape.width, path.span)?; + let shape = shape.sub_width(3, path.span)?; result = rewrite_path_segments( PathContext::Type, @@ -122,9 +122,7 @@ where } let extra_offset = extra_offset(&buffer, shape); - let new_shape = shape - .shrink_left(extra_offset) - .max_width_error(shape.width, mk_sp(span_lo, span_hi))?; + let new_shape = shape.shrink_left(extra_offset, mk_sp(span_lo, span_hi))?; let segment_string = rewrite_segment( path_context, segment, @@ -277,12 +275,12 @@ fn rewrite_segment( result.push_str(rewrite_ident(context, segment.ident)); let ident_len = result.len(); + let span = mk_sp(*span_lo, span_hi); let shape = if context.use_block_indent() { - shape.offset_left(ident_len) + shape.offset_left(ident_len, span)? } else { - shape.shrink_left(ident_len) - } - .max_width_error(shape.width, mk_sp(*span_lo, span_hi))?; + shape.shrink_left(ident_len, span)? + }; if let Some(ref args) = segment.args { let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?; @@ -333,8 +331,8 @@ where let ty_shape = match context.config.indent_style() { // 4 = " -> " - IndentStyle::Block => shape.offset_left(4).max_width_error(shape.width, span)?, - IndentStyle::Visual => shape.block_left(4).max_width_error(shape.width, span)?, + IndentStyle::Block => shape.offset_left(4, span)?, + IndentStyle::Visual => shape.block_left(4, span)?, }; let output = match *output { FnRetTy::Ty(ref ty) => { @@ -570,9 +568,7 @@ fn rewrite_bounded_lifetime( } else { let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); - let shape = shape - .sub_width(overhead) - .max_width_error(shape.width, span)?; + let shape = shape.sub_width(overhead, span)?; let result = format!( "{}{}{}", result, @@ -629,9 +625,7 @@ impl Rewrite for ast::GenericBound { asyncness.push(' '); } let polarity = polarity.as_str(); - let shape = shape - .offset_left(constness.len() + polarity.len()) - .max_width_error(shape.width, self.span())?; + let shape = shape.offset_left(constness.len() + polarity.len(), self.span())?; poly_trait_ref .rewrite_result(context, shape) .map(|s| format!("{constness}{asyncness}{polarity}{s}")) @@ -762,9 +756,7 @@ impl Rewrite for ast::PolyTraitRef { { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let shape = shape - .offset_left(extra_offset) - .max_width_error(shape.width, self.span)?; + let shape = shape.offset_left(extra_offset, self.span)?; let path_str = self.trait_ref.rewrite_result(context, shape)?; Ok(format!("for<{lifetime_str}> {path_str}")) @@ -795,15 +787,11 @@ impl Rewrite for ast::Ty { // we have to consider 'dyn' keyword is used or not!!! let (shape, prefix) = match tobj_syntax { ast::TraitObjectSyntax::Dyn => { - let shape = shape - .offset_left(4) - .max_width_error(shape.width, self.span())?; + let shape = shape.offset_left(4, self.span())?; (shape, "dyn ") } ast::TraitObjectSyntax::DynStar => { - let shape = shape - .offset_left(5) - .max_width_error(shape.width, self.span())?; + let shape = shape.offset_left(5, self.span())?; (shape, "dyn* ") } ast::TraitObjectSyntax::None => (shape, ""), @@ -920,7 +908,7 @@ impl Rewrite for ast::Ty { } // 2 = () - if let Some(sh) = shape.sub_width(2) { + if let Some(sh) = shape.sub_width_opt(2) { if let Ok(ref s) = ty.rewrite_result(context, sh) { if !s.contains('\n') { return Ok(format!("({s})")); @@ -1042,14 +1030,11 @@ fn rewrite_bare_fn( result.push_str("fn"); let func_ty_shape = if context.use_block_indent() { - shape - .offset_left(result.len()) - .max_width_error(shape.width, span)? + shape.offset_left(result.len(), span)? } else { shape .visual_indent(result.len()) - .sub_width(result.len()) - .max_width_error(shape.width, span)? + .sub_width(result.len(), span)? }; let rewrite = format_function_type( diff --git a/src/vertical.rs b/src/vertical.rs index 1ec239c3821..21e34d29710 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -213,7 +213,7 @@ fn rewrite_aligned_items_inner( force_trailing_separator: bool, ) -> Option { // 1 = "," - let item_shape = Shape::indented(offset, context.config).sub_width(1)?; + let item_shape = Shape::indented(offset, context.config).sub_width_opt(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = struct_field_prefix_max_min_width(context, fields, item_shape); let max_diff = field_prefix_max_width.saturating_sub(field_prefix_min_width); diff --git a/src/visitor.rs b/src/visitor.rs index 8102fe7ad8f..fb94819c56f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -325,7 +325,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .saturating_sub(self.block_indent.width()); match comment_shape .visual_indent(offset_len) - .sub_width(offset_len) + .sub_width_opt(offset_len) { Some(shp) => comment_shape = shp, None => comment_on_same_line = false,