From 8bac4780cbf28b041fb8de9a85c88d6ffa940650 Mon Sep 17 00:00:00 2001 From: ding-young Date: Wed, 19 Jun 2024 16:32:03 +0900 Subject: [PATCH 1/2] add rewrite_result method to Rewrite trait impl rewrite_result for ast::Local, ast::FieldDef, ast::Param, ast::FnRetTy --- src/items.rs | 146 ++++++++++++++++++++++++++++++++++++++----------- src/rewrite.rs | 22 +++++++- src/utils.rs | 8 +++ 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 { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { 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 { - rewrite_struct_field(context, self, shape, 0) + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { + 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 { + self.rewrite_result(context, shape).ok() + } + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { 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 { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { 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, ¶m_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; + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { + self.rewrite(context, shape).ok_or(RewriteError::Unknown) + } } impl Rewrite for ptr::P { @@ -24,6 +32,19 @@ impl Rewrite for ptr::P { } } +#[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>>, } - pub(crate) struct InsideMacroGuard { is_nested_macro_context: bool, inside_macro_ref: Rc>, 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) { From 867528956ff267ad19f66d619d143d7d329ea512 Mon Sep 17 00:00:00 2001 From: ding-young Date: Tue, 25 Jun 2024 10:42:39 +0900 Subject: [PATCH 2/2] add Ext trait for converting Option->RewriteResult --- src/items.rs | 177 +++++++++++++++++++++--------------------------- src/rewrite.rs | 30 ++++++-- src/vertical.rs | 21 +++--- 3 files changed, 111 insertions(+), 117 deletions(-) diff --git a/src/items.rs b/src/items.rs index eb808678403..48f5c36ac07 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, RewriteError}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; @@ -51,11 +51,7 @@ impl Rewrite for ast::Local { self.rewrite_result(context, shape).ok() } - fn rewrite_result( - &self, - context: &RewriteContext<'_>, - shape: Shape, - ) -> Result { + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { debug!( "Local::rewrite {:?} {} {:?}", self, shape.width, shape.indent @@ -82,26 +78,20 @@ impl Rewrite for ast::Local { shape, false, ) - .ok_or_else(|| RewriteError::Unknown)? + .unknown_error()? }; let let_kw_offset = result.len() - "let ".len(); // 4 = "let ".len() - let pat_shape = shape.offset_left(4).ok_or_else(|| RewriteError::Unknown)?; + let pat_shape = shape + .offset_left(4) + .max_width_error(shape.width, self.span())?; // 1 = ; 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(), - })?; + .max_width_error(shape.width, self.span())?; + let pat_str = self.pat.rewrite_result(context, pat_shape)?; + result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -116,16 +106,10 @@ impl Rewrite for ast::Local { shape } .offset_left(last_line_width(&result) + separator.len()) - .ok_or_else(|| RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - })? + .max_width_error(shape.width, self.span())? // 2 = ` =` .sub_width(2) - .ok_or_else(|| RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - })?; + .max_width_error(shape.width, self.span())?; let rewrite = ty.rewrite_result(context, ty_shape)?; @@ -144,7 +128,9 @@ 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).ok_or_else(|| RewriteError::Unknown)?; + let nested_shape = shape + .sub_width(1) + .max_width_error(shape.width, self.span())?; result = rewrite_assign_rhs( context, @@ -153,7 +139,7 @@ impl Rewrite for ast::Local { &RhsAssignKind::Expr(&init.kind, init.span), nested_shape, ) - .ok_or_else(|| RewriteError::Unknown)?; + .max_width_error(shape.width, self.span())?; if let Some(block) = else_block { let else_kw_span = init.span.between(block.span); @@ -196,7 +182,7 @@ impl Rewrite for ast::Local { let mut rw_else_block = rewrite_let_else_block(block, allow_single_line, context, shape) - .ok_or_else(|| RewriteError::Unknown)?; + .unknown_error()?; let single_line_else = !rw_else_block.contains('\n'); // +1 for the trailing `;` @@ -205,8 +191,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) - .ok_or_else(|| RewriteError::Unknown)?; + rw_else_block = + rewrite_let_else_block(block, false, context, shape).unknown_error()?; } result.push_str(&rw_else_block); @@ -1860,10 +1846,10 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { pub(crate) fn rewrite_struct_field_prefix( context: &RewriteContext<'_>, field: &ast::FieldDef, -) -> Option { +) -> RewriteResult { let vis = format_visibility(context, &field.vis); let type_annotation_spacing = type_annotation_spacing(context.config); - Some(match field.ident { + Ok(match field.ident { Some(name) => format!( "{}{}{}:", vis, @@ -1879,12 +1865,8 @@ impl Rewrite for ast::FieldDef { self.rewrite_result(context, shape).ok() } - fn rewrite_result( - &self, - context: &RewriteContext<'_>, - shape: Shape, - ) -> Result { - rewrite_struct_field(context, self, shape, 0).ok_or_else(|| RewriteError::Unknown) + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + rewrite_struct_field(context, self, shape, 0) } } @@ -1893,15 +1875,15 @@ pub(crate) fn rewrite_struct_field( field: &ast::FieldDef, shape: Shape, lhs_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 type_annotation_spacing = type_annotation_spacing(context.config); let prefix = rewrite_struct_field_prefix(context, field)?; - let attrs_str = field.attrs.rewrite(context, shape)?; + let attrs_str = field.attrs.rewrite_result(context, shape)?; let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); let missing_span = if field.attrs.is_empty() { mk_sp(field.span.lo(), field.span.lo()) @@ -1921,7 +1903,8 @@ pub(crate) fn rewrite_struct_field( missing_span, shape, attrs_extendable, - )?; + ) + .unknown_error()?; let overhead = trimmed_last_line_width(&attr_prefix); let lhs_offset = lhs_max_width.saturating_sub(overhead); for _ in 0..lhs_offset { @@ -1931,18 +1914,21 @@ pub(crate) fn rewrite_struct_field( if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { spacing.push(' '); } + let orig_ty = shape .offset_left(overhead + spacing.len()) - .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); + .and_then(|ty_shape| field.ty.rewrite_result(context, ty_shape).ok()); + if let Some(ref ty) = orig_ty { if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) { - return Some(attr_prefix + &spacing + ty); + return Ok(attr_prefix + &spacing + ty); } } let is_prefix_empty = prefix.is_empty(); // We must use multiline. We are going to put attributes and a field on different lines. - let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?; + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape) + .unknown_error()?; // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. let field_str = if is_prefix_empty { field_str.trim_start() @@ -1950,6 +1936,7 @@ pub(crate) fn rewrite_struct_field( &field_str }; combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) + .unknown_error() } pub(crate) struct StaticParts<'a> { @@ -2112,38 +2099,33 @@ impl Rewrite for ast::FnRetTy { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { self.rewrite_result(context, shape).ok() } - fn rewrite_result( - &self, - context: &RewriteContext<'_>, - shape: Shape, - ) -> Result { + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match *self { ast::FnRetTy::Default(_) => Ok(String::new()), ast::FnRetTy::Ty(ref ty) => { + let arrow_width = "-> ".len(); if context.config.version() == Version::One || context.config.indent_style() == IndentStyle::Visual { - let inner_width = shape.width.checked_sub(3).ok_or_else(|| { - RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - } - })?; + let inner_width = shape + .width + .checked_sub(arrow_width) + .max_width_error(shape.width, self.span())?; return ty - .rewrite_result(context, Shape::legacy(inner_width, shape.indent + 3)) + .rewrite_result( + context, + Shape::legacy(inner_width, shape.indent + arrow_width), + ) .map(|r| format!("-> {}", r)); } - ty.rewrite_result( - context, - shape - .offset_left(3) - .ok_or_else(|| RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - })?, - ) - .map(|s| format!("-> {}", s)) + let shape = shape + .offset_left(arrow_width) + .max_width_error(shape.width, self.span())?; + + ty.rewrite_result(context, shape) + .map(|s| format!("-> {}", s)) } } } @@ -2197,11 +2179,7 @@ impl Rewrite for ast::Param { self.rewrite_result(context, shape).ok() } - fn rewrite_result( - &self, - context: &RewriteContext<'_>, - shape: Shape, - ) -> Result { + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { let param_attrs_result = self .attrs .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?; @@ -2227,7 +2205,6 @@ 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 @@ -2240,7 +2217,7 @@ impl Rewrite for ast::Param { shape, !has_multiple_attr_lines && !has_doc_comments, ) - .ok_or_else(|| RewriteError::Unknown)?; + .unknown_error()?; if !is_empty_infer(&*self.ty, self.pat.span) { let (before_comment, after_comment) = @@ -2249,12 +2226,10 @@ 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).ok_or_else(|| { - RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - } - })?; + let max_width = shape + .width + .checked_sub(overhead) + .max_width_error(shape.width, self.span())?; if let Ok(ty_str) = self .ty .rewrite_result(context, Shape::legacy(max_width, shape.indent)) @@ -2275,17 +2250,15 @@ impl Rewrite for ast::Param { shape, !has_multiple_attr_lines, ) - .ok_or_else(|| RewriteError::Unknown)?; + .unknown_error()?; 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).ok_or_else(|| { - RewriteError::ExceedsMaxWidth { - configured_width: shape.width, - span: self.span(), - } - })?; + let max_width = shape + .width + .checked_sub(overhead) + .max_width_error(shape.width, self.span())?; let ty_str = self .ty .rewrite_result(context, Shape::legacy(max_width, shape.indent))?; @@ -2307,58 +2280,62 @@ fn rewrite_explicit_self( span: Span, shape: Shape, has_multiple_attr_lines: bool, -) -> Option { +) -> RewriteResult { match explicit_self.node { ast::SelfKind::Region(lt, m) => { let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = l.rewrite( + let lifetime_str = l.rewrite_result( context, Shape::legacy(context.config.max_width(), Indent::empty()), )?; - Some(combine_strs_with_missing_comments( + Ok(combine_strs_with_missing_comments( context, param_attrs, &format!("&{lifetime_str} {mut_str}self"), span, shape, !has_multiple_attr_lines, - )?) + ) + .unknown_error()?) } - None => Some(combine_strs_with_missing_comments( + None => Ok(combine_strs_with_missing_comments( context, param_attrs, &format!("&{mut_str}self"), span, shape, !has_multiple_attr_lines, - )?), + ) + .unknown_error()?), } } ast::SelfKind::Explicit(ref ty, mutability) => { - let type_str = ty.rewrite( + let type_str = ty.rewrite_result( context, Shape::legacy(context.config.max_width(), Indent::empty()), )?; - Some(combine_strs_with_missing_comments( + Ok(combine_strs_with_missing_comments( context, param_attrs, &format!("{}self: {}", format_mutability(mutability), type_str), span, shape, !has_multiple_attr_lines, - )?) + ) + .unknown_error()?) } - ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments( + ast::SelfKind::Value(mutability) => Ok(combine_strs_with_missing_comments( context, param_attrs, &format!("{}self", format_mutability(mutability)), span, shape, !has_multiple_attr_lines, - )?), + ) + .unknown_error()?), } } diff --git a/src/rewrite.rs b/src/rewrite.rs index 5467bf9d1f4..acf4cc1d60b 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -14,15 +14,13 @@ use crate::skip::SkipContext; use crate::visitor::SnippetProvider; use crate::FormatReport; +pub(crate) type RewriteResult = Result; pub(crate) trait Rewrite { /// Rewrite self into shape. fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; - fn rewrite_result( - &self, - context: &RewriteContext<'_>, - shape: Shape, - ) -> Result { - self.rewrite(context, shape).ok_or(RewriteError::Unknown) + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + self.rewrite(context, shape).unknown_error() } } @@ -45,6 +43,25 @@ pub(crate) enum RewriteError { Unknown, } +/// Extension trait used to conveniently convert to RewriteError +pub(crate) trait RewriteErrorExt { + fn max_width_error(self, width: usize, span: Span) -> Result; + fn unknown_error(self) -> Result; +} + +impl RewriteErrorExt for Option { + fn max_width_error(self, width: usize, span: Span) -> Result { + self.ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: width, + span: span, + }) + } + + fn unknown_error(self) -> Result { + self.ok_or_else(|| RewriteError::Unknown) + } +} + #[derive(Clone)] pub(crate) struct RewriteContext<'a> { pub(crate) psess: &'a ParseSess, @@ -65,6 +82,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) skip_context: SkipContext, pub(crate) skipped_range: Rc>>, } + pub(crate) struct InsideMacroGuard { is_nested_macro_context: bool, inside_macro_ref: Rc>, diff --git a/src/vertical.rs b/src/vertical.rs index a06bc995aa5..003eb0208ee 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -50,16 +50,15 @@ impl AlignedItem for ast::FieldDef { mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); - rewrite_struct_field_prefix(context, self).and_then(|field_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &field_str, - missing_span, - shape, - attrs_extendable, - ) - }) + let field_str = rewrite_struct_field_prefix(context, self).ok()?; + combine_strs_with_missing_comments( + context, + &attrs_str, + &field_str, + missing_span, + shape, + attrs_extendable, + ) } fn rewrite_aligned_item( @@ -68,7 +67,7 @@ impl AlignedItem for ast::FieldDef { shape: Shape, prefix_max_width: usize, ) -> Option { - rewrite_struct_field(context, self, shape, prefix_max_width) + rewrite_struct_field(context, self, shape, prefix_max_width).ok() } }