diff --git a/src/attr.rs b/src/attr.rs index 433b9256202..a263e253dd9 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -276,10 +276,11 @@ impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { Some(match self.kind { ast::MetaItemKind::Word => { - rewrite_path(context, PathContext::Type, &None, &self.path, shape)? + rewrite_path(context, PathContext::Type, &None, &self.path, shape).ok()? } ast::MetaItemKind::List(ref list) => { - let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?; + let path = + rewrite_path(context, PathContext::Type, &None, &self.path, shape).ok()?; let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span); overflow::rewrite_with_parens( context, @@ -297,7 +298,8 @@ impl Rewrite for ast::MetaItem { )? } ast::MetaItemKind::NameValue(ref lit) => { - let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?; + let path = + rewrite_path(context, PathContext::Type, &None, &self.path, shape).ok()?; // 3 = ` = ` let lit_shape = shape.shrink_left(path.len() + 3)?; // `rewrite_literal` returns `None` when `lit` exceeds max diff --git a/src/expr.rs b/src/expr.rs index 629d3c4f0eb..d75398ca1b6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -128,6 +128,7 @@ pub(crate) fn format_expr( expr.span, shape, ) + .ok() } ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) @@ -185,7 +186,7 @@ pub(crate) fn format_expr( rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind) } ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, PathContext::Expr, qself, path, shape) + rewrite_path(context, PathContext::Expr, qself, path, shape).ok() } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { rewrite_assignment(context, lhs, rhs, None, shape) @@ -1603,7 +1604,7 @@ fn rewrite_struct_lit<'a>( attrs: &[ast::Attribute], span: Span, shape: Shape, -) -> Option { +) -> RewriteResult { debug!("rewrite_struct_lit: shape {:?}", shape); enum StructLitField<'a> { @@ -1613,20 +1614,21 @@ fn rewrite_struct_lit<'a>( } // 2 = " {".len() - 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)?; let has_base_or_rest = match struct_rest { - ast::StructRest::None if fields.is_empty() => return Some(format!("{path_str} {{}}")), + ast::StructRest::None if fields.is_empty() => return Ok(format!("{path_str} {{}}")), ast::StructRest::Rest(_) if fields.is_empty() => { - return Some(format!("{path_str} {{ .. }}")); + return Ok(format!("{path_str} {{ .. }}")); } ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true, _ => false, }; // Foo { a: Foo } - indent is +3, width is -5. - let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; + let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2) + .max_width_error(shape.width, span)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); @@ -1639,7 +1641,8 @@ fn rewrite_struct_lit<'a>( v_shape, mk_sp(body_lo, span.hi()), one_line_width, - )? + ) + .unknown_error()? } else { let field_iter = fields.iter().map(StructLitField::Regular).chain( match struct_rest { @@ -1668,12 +1671,13 @@ 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)?, 0) + let v_shape = v_shape.sub_width(1)?; + rewrite_field(context, field, v_shape, 0).ok() } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, v_shape.offset_left(2)?) - .map(|s| format!("..{}", s)) + let v_shape = v_shape.sub_width(2)?; + expr.rewrite(context, v_shape).map(|s| format!("..{}", s)) } StructLitField::Rest(_) => Some("..".to_owned()), }; @@ -1705,12 +1709,12 @@ fn rewrite_struct_lit<'a>( force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(), ); - write_list(&item_vec, &fmt)? + write_list(&item_vec, &fmt).unknown_error()? }; let fields_str = wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?; - Some(format!("{path_str} {{{fields_str}}}")) + Ok(format!("{path_str} {{{fields_str}}}")) // FIXME if context.config.indent_style() == Visual, but we run out // of space, we should fall back to BlockIndent. @@ -1723,7 +1727,7 @@ pub(crate) fn wrap_struct_field( shape: Shape, nested_shape: Shape, one_line_width: usize, -) -> Option { +) -> RewriteResult { let should_vertical = context.config.indent_style() == IndentStyle::Block && (fields_str.contains('\n') || !context.config.struct_lit_single_line() @@ -1732,7 +1736,7 @@ pub(crate) fn wrap_struct_field( let inner_attrs = &inner_attributes(attrs); if inner_attrs.is_empty() { if should_vertical { - Some(format!( + Ok(format!( "{}{}{}", nested_shape.indent.to_string_with_newline(context.config), fields_str, @@ -1740,13 +1744,13 @@ pub(crate) fn wrap_struct_field( )) } else { // One liner or visual indent. - Some(format!(" {fields_str} ")) + Ok(format!(" {fields_str} ")) } } else { - Some(format!( + Ok(format!( "{}{}{}{}{}", nested_shape.indent.to_string_with_newline(context.config), - inner_attrs.rewrite(context, shape)?, + inner_attrs.rewrite_result(context, shape)?, nested_shape.indent.to_string_with_newline(context.config), fields_str, shape.indent.to_string_with_newline(context.config) @@ -1763,38 +1767,40 @@ pub(crate) fn rewrite_field( field: &ast::ExprField, shape: Shape, prefix_max_width: usize, -) -> Option { +) -> RewriteResult { if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).to_owned()); + return Ok(context.snippet(field.span()).to_owned()); } - let mut attrs_str = field.attrs.rewrite(context, shape)?; + let mut attrs_str = field.attrs.rewrite_result(context, shape)?; if !attrs_str.is_empty() { attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); }; let name = context.snippet(field.ident.span); if field.is_shorthand { - Some(attrs_str + name) + Ok(attrs_str + name) } else { let mut separator = String::from(struct_lit_field_separator(context.config)); for _ in 0..prefix_max_width.saturating_sub(name.len()) { separator.push(' '); } let overhead = name.len() + separator.len(); - let expr_shape = shape.offset_left(overhead)?; - let expr = field.expr.rewrite(context, expr_shape); + let expr_shape = shape + .offset_left(overhead) + .max_width_error(shape.width, field.span)?; + let expr = field.expr.rewrite_result(context, expr_shape); let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_)); match expr { - Some(ref e) + Ok(ref e) if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() => { - Some(attrs_str + name) + Ok(attrs_str + name) } - Some(e) => Some(format!("{attrs_str}{name}{separator}{e}")), - None => { + Ok(e) => Ok(format!("{attrs_str}{name}{separator}{e}")), + Err(_) => { let expr_offset = shape.indent.block_indent(context.config); let expr = field .expr - .rewrite(context, Shape::indented(expr_offset, context.config)); + .rewrite_result(context, Shape::indented(expr_offset, context.config)); expr.map(|s| { format!( "{}{}:\n{}{}", diff --git a/src/patterns.rs b/src/patterns.rs index d8cb26a20f1..da5a0c49aa2 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,7 +13,7 @@ use crate::lists::{ use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; use crate::pairs::{rewrite_pair, PairParts}; -use crate::rewrite::{Rewrite, RewriteContext}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -254,10 +254,11 @@ impl Rewrite for Pat { } PatKind::Tuple(ref items) => rewrite_tuple_pat(items, None, self.span, context, shape), PatKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Expr, q_self, path, shape) + rewrite_path(context, PathContext::Expr, q_self, path, shape).ok() } PatKind::TupleStruct(ref q_self, ref path, ref pat_vec) => { - let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?; + let path_str = + rewrite_path(context, PathContext::Expr, q_self, path, shape).ok()?; rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape) } PatKind::Lit(ref expr) => expr.rewrite(context, shape), @@ -291,7 +292,8 @@ impl Rewrite for Pat { self.span, context, shape, - ), + ) + .ok(), PatKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Pat) } @@ -312,20 +314,21 @@ fn rewrite_struct_pat( span: Span, context: &RewriteContext<'_>, shape: Shape, -) -> Option { +) -> 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, @@ -351,7 +354,7 @@ fn rewrite_struct_pat( let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let fmt = struct_lit_formatting(nested_shape, tactic, context, false); - let mut fields_str = write_list(&item_vec, &fmt)?; + let mut fields_str = write_list(&item_vec, &fmt).unknown_error()?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let has_trailing_comma = fmt.needs_trailing_separator(); @@ -379,7 +382,7 @@ 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 { diff --git a/src/types.rs b/src/types.rs index 942e31f3c92..c15ee2f3c5b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -40,7 +40,7 @@ pub(crate) fn rewrite_path( qself: &Option>, path: &ast::Path, shape: Shape, -) -> Option { +) -> RewriteResult { let skip_count = qself.as_ref().map_or(0, |x| x.position); // 32 covers almost all path lengths measured when compiling core, and there isn't a big @@ -56,7 +56,7 @@ pub(crate) fn rewrite_path( if let Some(qself) = qself { result.push('<'); - let fmt_ty = qself.ty.rewrite(context, shape)?; + let fmt_ty = qself.ty.rewrite_result(context, shape)?; result.push_str(&fmt_ty); if skip_count > 0 { @@ -66,7 +66,7 @@ pub(crate) fn rewrite_path( } // 3 = ">::".len() - let shape = shape.sub_width(3)?; + let shape = shape.sub_width(3).max_width_error(shape.width, path.span)?; result = rewrite_path_segments( PathContext::Type, @@ -102,7 +102,7 @@ fn rewrite_path_segments<'a, I>( span_hi: BytePos, context: &RewriteContext<'_>, shape: Shape, -) -> Option +) -> RewriteResult where I: Iterator, { @@ -121,7 +121,9 @@ where } let extra_offset = extra_offset(&buffer, shape); - let new_shape = shape.shrink_left(extra_offset)?; + let new_shape = shape + .shrink_left(extra_offset) + .max_width_error(shape.width, mk_sp(span_lo, span_hi))?; let segment_string = rewrite_segment( path_context, segment, @@ -134,7 +136,7 @@ where buffer.push_str(&segment_string); } - Some(buffer) + Ok(buffer) } #[derive(Debug)] @@ -183,8 +185,12 @@ impl<'a> Rewrite for SegmentParam<'a> { impl Rewrite for ast::PreciseCapturingArg { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self { - ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite(context, shape), + ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite_result(context, shape), ast::PreciseCapturingArg::Arg(p, _) => { rewrite_path(context, PathContext::Type, &None, p, shape) } @@ -194,13 +200,20 @@ impl Rewrite for ast::PreciseCapturingArg { impl Rewrite for ast::AssocItemConstraint { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { use ast::AssocItemConstraintKind::{Bound, Equality}; let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, self.ident)); if let Some(ref gen_args) = self.gen_args { - let budget = shape.width.checked_sub(result.len())?; + let budget = shape + .width + .checked_sub(result.len()) + .max_width_error(shape.width, self.span)?; let shape = Shape::legacy(budget, shape.indent + result.len()); let gen_str = rewrite_generic_args(gen_args, context, shape, gen_args.span())?; result.push_str(&gen_str); @@ -213,12 +226,15 @@ impl Rewrite for ast::AssocItemConstraint { }; result.push_str(infix); - let budget = shape.width.checked_sub(result.len())?; + let budget = shape + .width + .checked_sub(result.len()) + .max_width_error(shape.width, self.span)?; let shape = Shape::legacy(budget, shape.indent + result.len()); - let rewrite = self.kind.rewrite(context, shape)?; + let rewrite = self.kind.rewrite_result(context, shape)?; result.push_str(&rewrite); - Some(result) + Ok(result) } } @@ -255,16 +271,17 @@ fn rewrite_segment( span_hi: BytePos, context: &RewriteContext<'_>, shape: Shape, -) -> Option { +) -> RewriteResult { let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, segment.ident)); let ident_len = result.len(); let shape = if context.use_block_indent() { - shape.offset_left(ident_len)? + shape.offset_left(ident_len) } else { - shape.shrink_left(ident_len)? - }; + shape.shrink_left(ident_len) + } + .max_width_error(shape.width, mk_sp(*span_lo, span_hi))?; if let Some(ref args) = segment.args { let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?; @@ -295,7 +312,7 @@ fn rewrite_segment( result.push_str(&generics_str) } - Some(result) + Ok(result) } fn format_function_type<'a, I>( @@ -498,7 +515,7 @@ fn rewrite_generic_args( context: &RewriteContext<'_>, shape: Shape, span: Span, -) -> Option { +) -> RewriteResult { match gen_args { ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { let args = data @@ -515,6 +532,7 @@ fn rewrite_generic_args( .collect::>(); overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span) + .unknown_error() } ast::GenericArgs::Parenthesized(ref data) => format_function_type( data.inputs.iter().map(|x| &**x), @@ -523,9 +541,8 @@ fn rewrite_generic_args( data.span, context, shape, - ) - .ok(), - _ => Some("".to_owned()), + ), + _ => Ok("".to_owned()), } } @@ -717,23 +734,32 @@ impl Rewrite for ast::GenericParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { if let Some(lifetime_str) = rewrite_bound_params(context, shape, &self.bound_generic_params) { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let path_str = self - .trait_ref - .rewrite(context, shape.offset_left(extra_offset)?)?; + let shape = shape + .offset_left(extra_offset) + .max_width_error(shape.width, self.span)?; + let path_str = self.trait_ref.rewrite_result(context, shape)?; - Some(format!("for<{lifetime_str}> {path_str}")) + Ok(format!("for<{lifetime_str}> {path_str}")) } else { - self.trait_ref.rewrite(context, shape) + self.trait_ref.rewrite_result(context, shape) } } } impl Rewrite for ast::TraitRef { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { rewrite_path(context, PathContext::Type, &None, &self.path, shape) } } @@ -912,7 +938,7 @@ impl Rewrite for ast::Ty { ast::TyKind::AnonStruct(..) => Ok(context.snippet(self.span).to_owned()), ast::TyKind::AnonUnion(..) => Ok(context.snippet(self.span).to_owned()), ast::TyKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Type, q_self, path, shape).unknown_error() + rewrite_path(context, PathContext::Type, q_self, path, shape) } ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair( &**ty, diff --git a/src/vertical.rs b/src/vertical.rs index 003eb0208ee..691759803e5 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -13,7 +13,7 @@ use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; -use crate::rewrite::{Rewrite, RewriteContext}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteResult}; use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -30,7 +30,7 @@ pub(crate) trait AlignedItem { context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, - ) -> Option; + ) -> RewriteResult; } impl AlignedItem for ast::FieldDef { @@ -66,8 +66,8 @@ impl AlignedItem for ast::FieldDef { context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, - ) -> Option { - rewrite_struct_field(context, self, shape, prefix_max_width).ok() + ) -> RewriteResult { + rewrite_struct_field(context, self, shape, prefix_max_width) } } @@ -103,7 +103,7 @@ impl AlignedItem for ast::ExprField { context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, - ) -> Option { + ) -> RewriteResult { rewrite_field(context, self, shape, prefix_max_width) } } @@ -228,7 +228,11 @@ fn rewrite_aligned_items_inner( ",", |field| field.get_span().lo(), |field| field.get_span().hi(), - |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), + |field| { + field + .rewrite_aligned_item(context, item_shape, field_prefix_max_width) + .ok() + }, span.lo(), span.hi(), false, @@ -244,8 +248,9 @@ fn rewrite_aligned_items_inner( if tactic == DefinitiveListTactic::Horizontal { // since the items fits on a line, there is no need to align them - let do_rewrite = - |field: &T| -> Option { field.rewrite_aligned_item(context, item_shape, 0) }; + let do_rewrite = |field: &T| -> Option { + field.rewrite_aligned_item(context, item_shape, 0).ok() + }; fields .iter() .zip(items.iter_mut())