From 51df533d06286cf509dd76b4a604db09fbc85c41 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Jun 2024 14:56:57 -0400 Subject: [PATCH 01/30] Tighten spans for async blocks --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 8266f95fd70..c7c4b680b07 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -372,7 +372,7 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Gen(capture_by, ref block, ref kind) => { + ast::ExprKind::Gen(capture_by, ref block, ref kind, _) => { let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) { "move " } else { From 88f98c2929eebf2c4547dc5adbdaaf3ec651906a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 28 Jun 2024 14:18:36 -0400 Subject: [PATCH 02/30] Implement RTN support in rustfmt --- src/types.rs | 34 ++++++++++++++++------------ tests/target/return-type-notation.rs | 10 ++++++++ 2 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 tests/target/return-type-notation.rs diff --git a/src/types.rs b/src/types.rs index c0bf9482b11..c826547e9d0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -484,21 +484,25 @@ fn rewrite_generic_args( span: Span, ) -> Option { match gen_args { - ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { - let args = data - .args - .iter() - .map(|x| match x { - ast::AngleBracketedArg::Arg(generic_arg) => { - SegmentParam::from_generic_arg(generic_arg) - } - ast::AngleBracketedArg::Constraint(constraint) => { - SegmentParam::Binding(constraint) - } - }) - .collect::>(); + ast::GenericArgs::AngleBracketed(ref data) => { + if data.args.is_empty() { + Some("".to_owned()) + } else { + let args = data + .args + .iter() + .map(|x| match x { + ast::AngleBracketedArg::Arg(generic_arg) => { + SegmentParam::from_generic_arg(generic_arg) + } + ast::AngleBracketedArg::Constraint(constraint) => { + SegmentParam::Binding(constraint) + } + }) + .collect::>(); - overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span) + overflow::rewrite_with_angle_brackets(context, "", args.iter(), shape, span) + } } ast::GenericArgs::Parenthesized(ref data) => format_function_type( data.inputs.iter().map(|x| &**x), @@ -508,7 +512,7 @@ fn rewrite_generic_args( context, shape, ), - _ => Some("".to_owned()), + ast::GenericArgs::ParenthesizedElided(..) => Some("(..)".to_owned()), } } diff --git a/tests/target/return-type-notation.rs b/tests/target/return-type-notation.rs new file mode 100644 index 00000000000..0f26e7e272b --- /dev/null +++ b/tests/target/return-type-notation.rs @@ -0,0 +1,10 @@ +fn rtn() +where + T: Trait, + T::method(..): Send + 'static, +{ +} + +fn test() { + let x: T::method(..); +} From 163d26ea9d4ba35242974254a9281d0714c76705 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Jul 2024 21:59:28 -0400 Subject: [PATCH 03/30] Remove rustdoc tests which no longer parse --- tests/source/type.rs | 2 -- tests/target/negative-bounds.rs | 6 ------ tests/target/type.rs | 2 -- 3 files changed, 10 deletions(-) diff --git a/tests/source/type.rs b/tests/source/type.rs index 61ef73a3cab..7a232f85198 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -146,8 +146,6 @@ trait T: ~ const Super {} const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); - impl ~ const T {} fn apit(_: impl ~ const T) {} diff --git a/tests/target/negative-bounds.rs b/tests/target/negative-bounds.rs index 4fb35cccf66..9fcb86ef4a4 100644 --- a/tests/target/negative-bounds.rs +++ b/tests/target/negative-bounds.rs @@ -3,9 +3,3 @@ where i32: !Copy, { } - -fn maybe_const_negative() -where - i32: ~const !Copy, -{ -} diff --git a/tests/target/type.rs b/tests/target/type.rs index c789ecb055a..325adb52f3f 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -153,8 +153,6 @@ const fn not_quite_const() -> i32 { ::CONST } -struct S(std::marker::PhantomData); - impl ~const T {} fn apit(_: impl ~const T) {} From 90a86a78d267242fcf4a7933547697aadb3c0b83 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 10:10:36 -0400 Subject: [PATCH 04/30] Suppress must_use on eat calls in rustfmt --- src/parse/macros/lazy_static.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/parse/macros/lazy_static.rs b/src/parse/macros/lazy_static.rs index 7baac247e22..b6de5f8691c 100644 --- a/src/parse/macros/lazy_static.rs +++ b/src/parse/macros/lazy_static.rs @@ -33,15 +33,17 @@ pub(crate) fn parse_lazy_static( } while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. + // FIXME: These `eat_*` calls should be converted to `parse_or` to avoid + // silently formatting malformed lazy-statics. let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No); - parser.eat_keyword(kw::Static); - parser.eat_keyword(kw::Ref); + let _ = parser.eat_keyword(kw::Static); + let _ = parser.eat_keyword(kw::Ref); let id = parse_or!(parse_ident); - parser.eat(&TokenKind::Colon); + let _ = parser.eat(&TokenKind::Colon); let ty = parse_or!(parse_ty); - parser.eat(&TokenKind::Eq); + let _ = parser.eat(&TokenKind::Eq); let expr = parse_or!(parse_expr); - parser.eat(&TokenKind::Semi); + let _ = parser.eat(&TokenKind::Semi); result.push((vis, id, ty, expr)); } From 6159460963f472ab89eac839ab2344a29b51849a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 2 Aug 2024 02:12:29 -0700 Subject: [PATCH 05/30] rustfmt: Remove `has_cpuid` from test --- tests/source/cfg_if/detect/os/x86.rs | 9 --------- tests/target/cfg_if/detect/os/x86.rs | 9 --------- 2 files changed, 18 deletions(-) diff --git a/tests/source/cfg_if/detect/os/x86.rs b/tests/source/cfg_if/detect/os/x86.rs index 9257b8a4be6..b9adc67221a 100644 --- a/tests/source/cfg_if/detect/os/x86.rs +++ b/tests/source/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, diff --git a/tests/target/cfg_if/detect/os/x86.rs b/tests/target/cfg_if/detect/os/x86.rs index 2e228aa3745..944b51615f8 100644 --- a/tests/target/cfg_if/detect/os/x86.rs +++ b/tests/target/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, From 57af02c9c4867a47b0f42d33d842d7754b980929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 12 Mar 2024 02:12:28 +0100 Subject: [PATCH 06/30] Link `std` statically in `rustc_driver` --- src/git-rustfmt/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 3059d917c6b..5674f40bef9 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -1,3 +1,7 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to +// `rustc_driver`. +#![feature(rustc_private)] + #[macro_use] extern crate tracing; From 7b2299a2d210c71cd8f40b4e94af4bcd0aa8381c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 9 Aug 2024 17:44:47 +1000 Subject: [PATCH 07/30] Use `impl PartialEq for Token` more. This lets us compare a `Token` with a `TokenKind`. It's used a lot, but can be used even more, avoiding the need for some `.kind` uses. --- src/parse/macros/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index 60c827fd03b..8d5f7f90958 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -84,9 +84,7 @@ pub(crate) struct ParsedMacroArgs { fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { for &keyword in RUST_KW.iter() { if parser.token.is_keyword(keyword) - && parser.look_ahead(1, |t| { - t.kind == TokenKind::Eof || t.kind == TokenKind::Comma - }) + && parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma) { parser.bump(); return Some(MacroArg::Keyword( @@ -131,7 +129,7 @@ pub(crate) fn parse_macro_args( Some(arg) => { args.push(arg); parser.bump(); - if parser.token.kind == TokenKind::Eof && args.len() == 2 { + if parser.token == TokenKind::Eof && args.len() == 2 { vec_with_semi = true; break; } @@ -150,7 +148,7 @@ pub(crate) fn parse_macro_args( parser.bump(); - if parser.token.kind == TokenKind::Eof { + if parser.token == TokenKind::Eof { trailing_comma = true; break; } From d34fca4f017eae6b08b2ba582dcad7f88da3c494 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Sat, 17 Aug 2024 14:38:27 -0400 Subject: [PATCH 08/30] bump toolchain to nightly-2024-08-17 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d04c524861a..7b7081bfe81 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-06-25" +channel = "nightly-2024-08-17" components = ["llvm-tools", "rustc-dev"] From 6f5e99b7b5a00a1bed4d29f323fce0c989cf28aa Mon Sep 17 00:00:00 2001 From: ding-young Date: Mon, 22 Jul 2024 14:55:54 +0900 Subject: [PATCH 09/30] update macro rewrite functions to return RewriteResult --- src/expr.rs | 17 ++-- src/items.rs | 2 +- src/macros.rs | 252 +++++++++++++++++++++++++++++------------------- src/patterns.rs | 2 +- src/rewrite.rs | 28 ++++++ src/types.rs | 2 +- src/visitor.rs | 5 +- 7 files changed, 198 insertions(+), 110 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 138689bc132..02372e7be13 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -243,13 +243,16 @@ pub(crate) fn format_expr( | ast::ExprKind::MethodCall(..) | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape).ok(), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|_| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + .max_width_error(shape.width, expr.span) + }) + .ok() } ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { diff --git a/src/items.rs b/src/items.rs index 35591df0fd8..3894ee2cdf8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3427,7 +3427,7 @@ impl Rewrite for ast::ForeignItem { rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item) + rewrite_macro(mac, None, context, shape, MacroPosition::Item).ok() } }?; diff --git a/src/macros.rs b/src/macros.rs index c520971f40c..51ded869229 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -31,7 +31,9 @@ use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::overflow; use crate::parse::macros::lazy_static::parse_lazy_static; use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs}; -use crate::rewrite::{Rewrite, RewriteContext, RewriteError}; +use crate::rewrite::{ + MacroErrorKind, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult, +}; use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -71,22 +73,30 @@ impl MacroArg { impl Rewrite for ast::Item { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { let mut visitor = crate::visitor::FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); - Some(visitor.buffer.to_owned()) + Ok(visitor.buffer.to_owned()) } } impl Rewrite for MacroArg { 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 { - MacroArg::Expr(ref expr) => expr.rewrite(context, shape), - MacroArg::Ty(ref ty) => ty.rewrite(context, shape), - MacroArg::Pat(ref pat) => pat.rewrite(context, shape), - MacroArg::Item(ref item) => item.rewrite(context, shape), - MacroArg::Keyword(ident, _) => Some(ident.name.to_string()), + MacroArg::Expr(ref expr) => expr.rewrite_result(context, shape), + MacroArg::Ty(ref ty) => ty.rewrite_result(context, shape), + MacroArg::Pat(ref pat) => pat.rewrite_result(context, shape), + MacroArg::Item(ref item) => item.rewrite_result(context, shape), + MacroArg::Keyword(ident, _) => Ok(ident.name.to_string()), } } } @@ -110,12 +120,14 @@ fn rewrite_macro_name( } // Use this on failing to format the macro call. +// TODO(ding-young) We should also report macro parse failure to tell users why given snippet +// is left unformatted. One possible improvement is appending formatting error to context.report fn return_macro_parse_failure_fallback( context: &RewriteContext<'_>, indent: Indent, position: MacroPosition, span: Span, -) -> Option { +) -> RewriteResult { // Mark this as a failure however we format it context.macro_rewrite_failure.replace(true); @@ -133,7 +145,8 @@ fn return_macro_parse_failure_fallback( }) .unwrap_or(false); if is_like_block_indent_style { - return trim_left_preserve_layout(context.snippet(span), indent, context.config); + return trim_left_preserve_layout(context.snippet(span), indent, context.config) + .macro_error(MacroErrorKind::Unknown, span); } context.skipped_range.borrow_mut().push(( @@ -146,7 +159,7 @@ fn return_macro_parse_failure_fallback( if position == MacroPosition::Item { snippet.push(';'); } - Some(snippet) + Ok(snippet) } pub(crate) fn rewrite_macro( @@ -155,13 +168,13 @@ pub(crate) fn rewrite_macro( context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, -) -> Option { +) -> RewriteResult { let should_skip = context .skip_context .macros .skip(context.snippet(mac.path.span)); if should_skip { - None + Err(RewriteError::SkipFormatting) } else { let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { @@ -175,9 +188,16 @@ pub(crate) fn rewrite_macro( ) })); match result { - Err(..) | Ok(None) => { + Err(..) => { context.macro_rewrite_failure.replace(true); - None + Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: mac.span(), + }) + } + Ok(Err(e)) => { + context.macro_rewrite_failure.replace(true); + Err(e) } Ok(rw) => rw, } @@ -191,11 +211,11 @@ fn rewrite_macro_inner( shape: Shape, position: MacroPosition, is_nested_macro: bool, -) -> Option { +) -> RewriteResult { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { context.leave_macro(); - return expr.rewrite(context, shape); + return expr.rewrite_result(context, shape); } } @@ -215,21 +235,27 @@ fn rewrite_macro_inner( if ts.is_empty() && !has_comment { return match style { Delimiter::Parenthesis if position == MacroPosition::Item => { - Some(format!("{macro_name}();")) - } - Delimiter::Bracket if position == MacroPosition::Item => { - Some(format!("{macro_name}[];")) + Ok(format!("{macro_name}();")) } - Delimiter::Parenthesis => Some(format!("{macro_name}()")), - Delimiter::Bracket => Some(format!("{macro_name}[]")), - Delimiter::Brace => Some(format!("{macro_name} {{}}")), + Delimiter::Bracket if position == MacroPosition::Item => Ok(format!("{macro_name}[];")), + Delimiter::Parenthesis => Ok(format!("{macro_name}()")), + Delimiter::Bracket => Ok(format!("{macro_name}[]")), + Delimiter::Brace => Ok(format!("{macro_name} {{}}")), _ => unreachable!(), }; } // Format well-known macros which cannot be parsed as a valid AST. if macro_name == "lazy_static!" && !has_comment { - if let success @ Some(..) = format_lazy_static(context, shape, ts.clone()) { - return success; + match format_lazy_static(context, shape, ts.clone(), mac.span()) { + Ok(rw) => return Ok(rw), + Err(err) => match err { + // We will move on to parsing macro args just like other macros + // if we could not parse lazy_static! with known syntax + RewriteError::MacroFailure { kind, span: _ } + if kind == MacroErrorKind::ParseFailure => {} + // If formatting fails even though parsing succeeds, return the err early + _ => return Err(err), + }, } } @@ -266,7 +292,7 @@ fn rewrite_macro_inner( Delimiter::Parenthesis => { // Handle special case: `vec!(expr; expr)` if vec_with_semi { - handle_vec_semi(context, shape, arg_vec, macro_name, style) + handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span()) } else { // Format macro invocation as function call, preserve the trailing // comma because not all macros support them. @@ -283,7 +309,6 @@ fn rewrite_macro_inner( Some(SeparatorTactic::Never) }, ) - .ok() .map(|rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, @@ -293,7 +318,7 @@ fn rewrite_macro_inner( Delimiter::Bracket => { // Handle special case: `vec![expr; expr]` if vec_with_semi { - handle_vec_semi(context, shape, arg_vec, macro_name, style) + handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span()) } else { // If we are rewriting `vec!` macro or other special macros, // then we can rewrite this as a usual array literal. @@ -317,14 +342,13 @@ fn rewrite_macro_inner( shape, force_trailing_comma, Some(original_style), - ) - .ok()?; + )?; let comma = match position { MacroPosition::Item => ";", _ => "", }; - Some(format!("{rewrite}{comma}")) + Ok(format!("{rewrite}{comma}")) } } Delimiter::Brace => { @@ -333,8 +357,8 @@ fn rewrite_macro_inner( // anything in between the braces (for now). let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{'); match trim_left_preserve_layout(snippet, shape.indent, context.config) { - Some(macro_body) => Some(format!("{macro_name} {macro_body}")), - None => Some(format!("{macro_name} {snippet}")), + Some(macro_body) => Ok(format!("{macro_name} {macro_body}")), + None => Ok(format!("{macro_name} {snippet}")), } } _ => unreachable!(), @@ -347,28 +371,32 @@ fn handle_vec_semi( arg_vec: Vec, macro_name: String, delim_token: Delimiter, -) -> Option { + span: Span, +) -> RewriteResult { let (left, right) = match delim_token { Delimiter::Parenthesis => ("(", ")"), Delimiter::Bracket => ("[", "]"), _ => unreachable!(), }; - let mac_shape = shape.offset_left(macro_name.len())?; + // Should we return MaxWidthError, Or Macro failure + let mac_shape = shape + .offset_left(macro_name.len()) + .max_width_error(shape.width, span)?; // 8 = `vec![]` + `; ` or `vec!()` + `; ` let total_overhead = 8; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = arg_vec[0].rewrite(context, nested_shape)?; - let rhs = arg_vec[1].rewrite(context, nested_shape)?; + let lhs = arg_vec[0].rewrite_result(context, nested_shape)?; + let rhs = arg_vec[1].rewrite_result(context, nested_shape)?; if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { // macro_name(lhs; rhs) or macro_name[lhs; rhs] - Some(format!("{macro_name}{left}{lhs}; {rhs}{right}")) + Ok(format!("{macro_name}{left}{lhs}; {rhs}{right}")) } else { // macro_name(\nlhs;\nrhs\n) or macro_name[\nlhs;\nrhs\n] - Some(format!( + Ok(format!( "{}{}{}{};{}{}{}{}", macro_name, left, @@ -386,7 +414,7 @@ fn rewrite_empty_macro_def_body( context: &RewriteContext<'_>, span: Span, shape: Shape, -) -> Option { +) -> RewriteResult { // Create an empty, dummy `ast::Block` representing an empty macro body let block = ast::Block { stmts: vec![].into(), @@ -396,7 +424,7 @@ fn rewrite_empty_macro_def_body( tokens: None, could_be_bare_literal: false, }; - block.rewrite(context, shape) + block.rewrite_result(context, shape) } pub(crate) fn rewrite_macro_def( @@ -407,8 +435,8 @@ pub(crate) fn rewrite_macro_def( ident: symbol::Ident, vis: &ast::Visibility, span: Span, -) -> Option { - let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); +) -> RewriteResult { + let snippet = Ok(remove_trailing_white_spaces(context.snippet(span))); if snippet.as_ref().map_or(true, |s| s.ends_with(';')) { return snippet; } @@ -443,7 +471,7 @@ pub(crate) fn rewrite_macro_def( let lo = context.snippet_provider.span_before(span, "{"); result += " "; result += &rewrite_empty_macro_def_body(context, span.with_lo(lo), shape)?; - return Some(result); + return Ok(result); } let branch_items = itemize_list( @@ -454,13 +482,14 @@ pub(crate) fn rewrite_macro_def( |branch| branch.span.lo(), |branch| branch.span.hi(), |branch| match branch.rewrite(context, arm_shape, multi_branch_style) { - Some(v) => Ok(v), + Ok(v) => Ok(v), // if the rewrite returned None because a macro could not be rewritten, then return the // original body - None if context.macro_rewrite_failure.get() => { + // TODO(ding-young) report rewrite error even if we return Ok with original snippet + Err(_) if context.macro_rewrite_failure.get() => { Ok(context.snippet(branch.body).trim().to_string()) } - None => Err(RewriteError::Unknown), + Err(e) => Err(e), }, context.snippet_provider.span_after(span, "{"), span.hi(), @@ -488,7 +517,7 @@ pub(crate) fn rewrite_macro_def( result += "}"; } - Some(result) + Ok(result) } fn register_metavariable( @@ -640,12 +669,13 @@ impl MacroArgKind { context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, - ) -> Option { - let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> { + ) -> RewriteResult { + type DelimitedArgsRewrite = Result<(String, String, String), RewriteError>; + let rewrite_delimited_inner = |delim_tok, args| -> DelimitedArgsRewrite { let inner = wrap_macro_args(context, args, shape)?; let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false, inner.is_empty()); if lhs.len() + inner.len() + rhs.len() <= shape.width { - return Some((lhs, inner, rhs)); + return Ok((lhs, inner, rhs)); } let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true, false); @@ -653,27 +683,27 @@ impl MacroArgKind { .block_indent(context.config.tab_spaces()) .with_max_width(context.config); let inner = wrap_macro_args(context, args, nested_shape)?; - Some((lhs, inner, rhs)) + Ok((lhs, inner, rhs)) }; match *self { - MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${name}:{ty}")), + MacroArgKind::MetaVariable(ty, ref name) => Ok(format!("${name}:{ty}")), MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => { let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; let another = another .as_ref() - .and_then(|a| a.rewrite(context, shape, use_multiple_lines)) + .and_then(|a| a.rewrite(context, shape, use_multiple_lines).ok()) .unwrap_or_else(|| "".to_owned()); let repeat_tok = pprust::token_to_string(tok); - Some(format!("${lhs}{inner}{rhs}{another}{repeat_tok}")) + Ok(format!("${lhs}{inner}{rhs}{another}{repeat_tok}")) } MacroArgKind::Delimited(delim_tok, ref args) => { rewrite_delimited_inner(delim_tok, args) .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)) } - MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{prefix}{sep} ")), - MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{prefix}{inner}")), + MacroArgKind::Separator(ref sep, ref prefix) => Ok(format!("{prefix}{sep} ")), + MacroArgKind::Other(ref inner, ref prefix) => Ok(format!("{prefix}{inner}")), } } } @@ -689,7 +719,7 @@ impl ParsedMacroArg { context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, - ) -> Option { + ) -> RewriteResult { self.kind.rewrite(context, shape, use_multiple_lines) } } @@ -967,9 +997,9 @@ fn wrap_macro_args( context: &RewriteContext<'_>, args: &[ParsedMacroArg], shape: Shape, -) -> Option { +) -> RewriteResult { wrap_macro_args_inner(context, args, shape, false) - .or_else(|| wrap_macro_args_inner(context, args, shape, true)) + .or_else(|_| wrap_macro_args_inner(context, args, shape, true)) } fn wrap_macro_args_inner( @@ -977,7 +1007,7 @@ fn wrap_macro_args_inner( args: &[ParsedMacroArg], shape: Shape, use_multiple_lines: bool, -) -> Option { +) -> RewriteResult { let mut result = String::with_capacity(128); let mut iter = args.iter().peekable(); let indent_str = shape.indent.to_string_with_newline(context.config); @@ -1003,9 +1033,9 @@ fn wrap_macro_args_inner( } if !use_multiple_lines && result.len() >= shape.width { - None + Err(RewriteError::Unknown) } else { - Some(result) + Ok(result) } } @@ -1013,22 +1043,21 @@ fn wrap_macro_args_inner( // for some common cases. I hope the basic logic is sufficient. Note that the // meaning of some tokens is a bit different here from usual Rust, e.g., `*` // and `(`/`)` have special meaning. -// -// We always try and format on one line. -// FIXME: Use multi-line when every thing does not fit on one line. fn format_macro_args( context: &RewriteContext<'_>, token_stream: TokenStream, shape: Shape, -) -> Option { +) -> RewriteResult { + let span = span_for_token_stream(&token_stream); if !context.config.format_macro_matchers() { - let span = span_for_token_stream(&token_stream); - return Some(match span { + return Ok(match span { Some(span) => context.snippet(span).to_owned(), None => String::new(), }); } - let parsed_args = MacroArgParser::new().parse(token_stream)?; + let parsed_args = MacroArgParser::new() + .parse(token_stream) + .macro_error(MacroErrorKind::ParseFailure, span.unwrap())?; wrap_macro_args(context, &parsed_args, shape) } @@ -1241,11 +1270,14 @@ impl MacroBranch { context: &RewriteContext<'_>, shape: Shape, multi_branch_style: bool, - ) -> Option { + ) -> RewriteResult { // Only attempt to format function-like macros. if self.args_paren_kind != Delimiter::Parenthesis { // FIXME(#1539): implement for non-sugared macros. - return None; + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: self.span, + }); } let old_body = context.snippet(self.body).trim(); @@ -1256,8 +1288,13 @@ impl MacroBranch { prefix_width = 6; // 6 = " => {{" } } - let mut result = - format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?; + let mut result = format_macro_args( + context, + self.args.clone(), + shape + .sub_width(prefix_width) + .max_width_error(shape.width, self.span)?, + )?; if multi_branch_style { result += " =>"; @@ -1266,7 +1303,7 @@ impl MacroBranch { if !context.config.format_macro_bodies() { result += " "; result += context.snippet(self.whole_body); - return Some(result); + return Ok(result); } // The macro body is the most interesting part. It might end up as various @@ -1275,7 +1312,8 @@ impl MacroBranch { // `$$`). We'll try and format like an AST node, but we'll substitute // variables for new names with the same length first. - let (body_str, substs) = replace_names(old_body)?; + let (body_str, substs) = + replace_names(old_body).macro_error(MacroErrorKind::ReplaceMacroVariable, self.span)?; let mut config = context.config.clone(); config.set().show_parse_errors(false); @@ -1298,13 +1336,21 @@ impl MacroBranch { config.set().max_width(new_width); match crate::format_code_block(&body_str, &config, true) { Some(new_body) => new_body, - None => return None, + None => { + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: self.span, + }); + } } } }; if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) { - return None; + return Err(RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span, + }); } // Indent the body since it is in a block. @@ -1330,7 +1376,10 @@ impl MacroBranch { for (old, new) in &substs { if old_body.contains(new) { debug!("rewrite_macro_def: bailing matching variable: `{}`", new); - return None; + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::ReplaceMacroVariable, + span: self.span, + }); } new_body = new_body.replace(new, old); } @@ -1345,7 +1394,7 @@ impl MacroBranch { result += "}"; - Some(result) + Ok(result) } } @@ -1365,7 +1414,8 @@ fn format_lazy_static( context: &RewriteContext<'_>, shape: Shape, ts: TokenStream, -) -> Option { + span: Span, +) -> RewriteResult { let mut result = String::with_capacity(1024); let nested_shape = shape .block_indent(context.config.tab_spaces()) @@ -1374,7 +1424,8 @@ fn format_lazy_static( result.push_str("lazy_static! {"); result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); - let parsed_elems = parse_lazy_static(context, ts)?; + let parsed_elems = + parse_lazy_static(context, ts).macro_error(MacroErrorKind::ParseFailure, span)?; let last = parsed_elems.len() - 1; for (i, (vis, id, ty, expr)) in parsed_elems.iter().enumerate() { // Rewrite as a static item. @@ -1384,15 +1435,20 @@ fn format_lazy_static( "{}static ref {}: {} =", vis, id, - ty.rewrite(context, nested_shape)? + ty.rewrite_result(context, nested_shape)? )); - result.push_str(&rewrite_assign_rhs( - context, - stmt, - &*expr, - &RhsAssignKind::Expr(&expr.kind, expr.span), - nested_shape.sub_width(1)?, - )?); + result.push_str( + &rewrite_assign_rhs( + context, + stmt, + &*expr, + &RhsAssignKind::Expr(&expr.kind, expr.span), + nested_shape + .sub_width(1) + .max_width_error(nested_shape.width, expr.span)?, + ) + .unknown_error()?, + ); result.push(';'); if i != last { result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); @@ -1402,7 +1458,7 @@ fn format_lazy_static( result.push_str(&shape.indent.to_string_with_newline(context.config)); result.push('}'); - Some(result) + Ok(result) } fn rewrite_macro_with_items( @@ -1414,12 +1470,12 @@ fn rewrite_macro_with_items( original_style: Delimiter, position: MacroPosition, span: Span, -) -> Option { +) -> RewriteResult { let style_to_delims = |style| match style { - Delimiter::Parenthesis => Some(("(", ")")), - Delimiter::Bracket => Some(("[", "]")), - Delimiter::Brace => Some((" {", "}")), - _ => None, + Delimiter::Parenthesis => Ok(("(", ")")), + Delimiter::Bracket => Ok(("[", "]")), + Delimiter::Brace => Ok((" {", "}")), + _ => Err(RewriteError::Unknown), }; let (opener, closer) = style_to_delims(style)?; @@ -1441,7 +1497,7 @@ fn rewrite_macro_with_items( for item in items { let item = match item { MacroArg::Item(item) => item, - _ => return None, + _ => return Err(RewriteError::Unknown), }; visitor.visit_item(item); } @@ -1454,5 +1510,5 @@ fn rewrite_macro_with_items( result.push_str(&shape.indent.to_string_with_newline(context.config)); result.push_str(closer); result.push_str(trailing_semicolon); - Some(result) + Ok(result) } diff --git a/src/patterns.rs b/src/patterns.rs index 3ae0fbf161f..9a4f6528ce8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -327,7 +327,7 @@ impl Rewrite for Pat { shape, ), PatKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Pat).unknown_error() + rewrite_macro(mac, None, context, shape, MacroPosition::Pat) } PatKind::Paren(ref pat) => pat .rewrite_result( diff --git a/src/rewrite.rs b/src/rewrite.rs index 6644e4b27a8..8cefda1657f 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -30,6 +30,23 @@ impl Rewrite for ptr::P { } } +#[derive(Clone, Debug, PartialEq)] +pub(crate) enum MacroErrorKind { + ParseFailure, + ReplaceMacroVariable, + Unknown, +} + +impl std::fmt::Display for MacroErrorKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MacroErrorKind::ParseFailure => write!(f, "(parse failure)"), + MacroErrorKind::ReplaceMacroVariable => write!(f, "(replacing macro variables with $)"), + MacroErrorKind::Unknown => write!(f, ""), + } + } +} + #[derive(Clone, Error, Debug)] pub(crate) enum RewriteError { #[error("Formatting was skipped due to skip attribute or out of file range.")] @@ -38,6 +55,9 @@ pub(crate) enum RewriteError { #[error("It exceeds the required width of {configured_width} for the span: {span:?}")] ExceedsMaxWidth { configured_width: usize, span: Span }, + #[error("Failed to format given macro{} at: {span:?}", kind)] + MacroFailure { kind: MacroErrorKind, span: Span }, + /// Format failure that does not fit to above categories. #[error("An unknown error occurred during formatting.")] Unknown, @@ -46,6 +66,7 @@ pub(crate) enum RewriteError { /// Extension trait used to conveniently convert to RewriteError pub(crate) trait RewriteErrorExt { fn max_width_error(self, width: usize, span: Span) -> Result; + fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result; fn unknown_error(self) -> Result; } @@ -57,6 +78,13 @@ impl RewriteErrorExt for Option { }) } + fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result { + self.ok_or_else(|| RewriteError::MacroFailure { + kind: kind, + span: span, + }) + } + fn unknown_error(self) -> Result { self.ok_or_else(|| RewriteError::Unknown) } diff --git a/src/types.rs b/src/types.rs index f9dafe7d625..76eb0ea0529 100644 --- a/src/types.rs +++ b/src/types.rs @@ -958,7 +958,7 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).unknown_error() + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Ok(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { diff --git a/src/visitor.rs b/src/visitor.rs index b08aa35f8f8..9859100a038 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -584,7 +584,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item.ident, &item.vis, item.span, - ); + ) + .ok(); self.push_rewrite(item.span, rewrite); } ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => { @@ -683,7 +684,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // 1 = ; let shape = self.shape().saturating_sub_width(1); - let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); + let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok()); // As of v638 of the rustc-ap-* crates, the associated span no longer includes // the trailing semicolon. This determines the correct span to ensure scenarios // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) From 5ee4d3b532a4f329fdb9319453a22d5ee9c3a7b0 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 24 Aug 2024 20:50:16 +0100 Subject: [PATCH 10/30] Remove outdated comment from `mac.yml` --- .github/workflows/mac.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 89a980c42c5..f98c9830a4d 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -8,7 +8,6 @@ on: jobs: test: # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources - # macOS Catalina 10.15 runs-on: macos-latest name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) env: From 53d5ccd5e965086f7d43d43a1eabdb7064780cb5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 18:42:45 -0500 Subject: [PATCH 11/30] refactor: use style edition when loading from partial config --- src/config/config_type.rs | 2 +- src/config/mod.rs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 91efb71744b..4b83e974932 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -210,7 +210,7 @@ macro_rules! create_config { )+ #[allow(unreachable_pub)] - pub fn default_with_style_edition(style_edition: StyleEdition) -> Config { + pub(super) fn default_with_style_edition(style_edition: StyleEdition) -> Config { Config { $( $i: ( diff --git a/src/config/mod.rs b/src/config/mod.rs index 5d6047c385d..6462c62a358 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -217,9 +217,37 @@ impl PartialConfig { ::toml::to_string(&cloned).map_err(ToTomlError) } + + pub(super) fn to_parsed_config( + self, + style_edition_override: Option, + edition_override: Option, + dir: &Path, + ) -> Config { + Config::default_for_possible_style_edition( + style_edition_override.or(self.style_edition), + edition_override.or(self.edition), + ) + .fill_from_parsed_config(self, dir) + } } impl Config { + pub fn default_for_possible_style_edition( + style_edition: Option, + edition: Option, + ) -> Config { + style_edition.map_or_else( + || { + edition.map_or_else( + || Config::default(), + |e| Self::default_with_style_edition(e.into()), + ) + }, + |se| Self::default_with_style_edition(se), + ) + } + pub(crate) fn version_meets_requirement(&self) -> bool { if self.was_set().required_version() { let version = env!("CARGO_PKG_VERSION"); @@ -324,12 +352,13 @@ impl Config { err.push_str(msg) } } - match parsed.try_into() { + + match parsed.try_into::() { Ok(parsed_config) => { if !err.is_empty() { eprint!("{err}"); } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) + Ok(parsed_config.to_parsed_config(None, None, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); From c0c3dc7a25f6e4079b41acf46a513e574d9f2855 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 22:14:23 -0500 Subject: [PATCH 12/30] refactor: include edition & style edition in CliOptions --- src/bin/main.rs | 12 ++++++++++++ src/config/mod.rs | 10 +++++++--- src/config/options.rs | 2 ++ src/git-rustfmt/main.rs | 6 ++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 1185454c8e7..2e4877c7569 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -734,6 +734,18 @@ impl CliOptions for GetOptsOptions { fn config_path(&self) -> Option<&Path> { self.config_path.as_deref() } + + fn edition(&self) -> Option { + self.inline_config + .get("edition") + .map_or(self.edition, |e| Edition::from_str(e).ok()) + } + + fn style_edition(&self) -> Option { + self.inline_config + .get("style_edition") + .map_or(self.style_edition, |se| StyleEdition::from_str(se).ok()) + } } fn edition_from_edition_str(edition_str: &str) -> Result { diff --git a/src/config/mod.rs b/src/config/mod.rs index 6462c62a358..3b77902fa2a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -376,9 +376,13 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let over_ride = match options { - Some(ref opts) => config_path(opts)?, - None => None, + let (over_ride, _edition, _style_edition) = match options { + Some(ref opts) => ( + config_path(opts)?, + opts.edition(), + opts.style_edition(), + ), + None => (None, None, None), }; let result = if let Some(over_ride) = over_ride { diff --git a/src/config/options.rs b/src/config/options.rs index 40cfafed29d..f7a8c114330 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -419,6 +419,8 @@ pub trait CliOptions { /// It is ok if the returned path doesn't exist or is not canonicalized /// (i.e. the callers are expected to handle such cases). fn config_path(&self) -> Option<&Path>; + fn edition(&self) -> Option; + fn style_edition(&self) -> Option; } /// The edition of the syntax and semantics of code (RFC 2052). diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 5674f40bef9..14ac81322b9 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -89,6 +89,12 @@ impl CliOptions for NullOptions { fn config_path(&self) -> Option<&Path> { unreachable!(); } + fn edition(&self) -> Option { + unreachable!(); + } + fn style_edition(&self) -> Option { + unreachable!(); + } } fn uncommitted_files() -> Vec { From 0c6515cacc4465ae29d90f4bacc7f95ace7afe0b Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 23:17:26 -0500 Subject: [PATCH 13/30] feat: support style edition differing defaults in config loading --- src/config/mod.rs | 61 ++++++++++++++++++++++++++++++++++------------- src/test/mod.rs | 55 +++++++++++++++++++++++++++++++++++------- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 3b77902fa2a..da7adea5a74 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -271,12 +271,21 @@ impl Config { /// /// Returns a `Config` if the config could be read and parsed from /// the file, otherwise errors. - pub(super) fn from_toml_path(file_path: &Path) -> Result { + pub(super) fn from_toml_path( + file_path: &Path, + edition: Option, + style_edition: Option, + ) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + Config::from_toml_for_style_edition( + &toml, + file_path.parent().unwrap(), + edition, + style_edition, + ) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolves the config for input in `dir`. @@ -288,7 +297,11 @@ impl Config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + pub(super) fn from_resolved_toml_path( + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of the nearest project file if one exists, /// or `None` if no project file was found. @@ -333,12 +346,26 @@ impl Config { } match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + None => Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )), + Some(path) => Config::from_toml_path(&path, edition, style_edition) + .map(|config| (config, Some(path))), } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + #[allow(dead_code)] + pub(super) fn from_toml(toml: &str, dir: &Path) -> Result { + Self::from_toml_for_style_edition(toml, dir, None, None) + } + + pub(crate) fn from_toml_for_style_edition( + toml: &str, + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; @@ -358,7 +385,7 @@ impl Config { if !err.is_empty() { eprint!("{err}"); } - Ok(parsed_config.to_parsed_config(None, None, dir)) + Ok(parsed_config.to_parsed_config(style_edition, edition, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -376,21 +403,21 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let (over_ride, _edition, _style_edition) = match options { - Some(ref opts) => ( - config_path(opts)?, - opts.edition(), - opts.style_edition(), - ), + let (over_ride, edition, style_edition) = match options { + Some(ref opts) => (config_path(opts)?, opts.edition(), opts.style_edition()), None => (None, None, None), }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) + Config::from_toml_path(over_ride.as_ref(), edition, style_edition) + .map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path) + Config::from_resolved_toml_path(file_path, edition, style_edition) } else { - Ok((Config::default(), None)) + Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )) }; result.map(|(mut c, p)| { diff --git a/src/test/mod.rs b/src/test/mod.rs index 7c563801c32..96706efb161 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -6,14 +6,17 @@ use std::iter::Peekable; use std::mem; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::str::Chars; +use std::str::{Chars, FromStr}; use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::{ + is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, + StyleEdition, +}; use rustfmt_config_proc_macro::nightly_only_test; @@ -710,13 +713,22 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); + let (edition, style_edition) = get_editions_from_comments(&sig_comments); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) + get_config( + sig_comments.get("config").map(Path::new), + edition, + style_edition, + ) } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) + get_config( + filename.with_extension("toml").file_name().map(Path::new), + edition, + style_edition, + ) }; for (key, val) in &sig_comments { @@ -747,13 +759,28 @@ enum IdempotentCheckError { Parse, } +fn get_editions_from_comments( + comments: &HashMap, +) -> (Option, Option) { + ( + comments + .get("edition") + .map(|e| Edition::from_str(e).expect(&format!("invalid edition value: '{}'", e))), + comments.get("style_edition").map(|se| { + StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se)) + }), + ) +} + fn idempotent_check( filename: &PathBuf, opt_config: &Option, ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found") + let (edition, style_edition) = get_editions_from_comments(&sig_comments); + Config::from_toml_path(config_file_path, edition, style_edition) + .expect("`rustfmt.toml` not found") } else { read_config(filename) }; @@ -777,14 +804,18 @@ fn idempotent_check( // Reads test config file using the supplied (optional) file name. If there's no file name or the // file doesn't exist, just return the default config. Otherwise, the file must be read // successfully. -fn get_config(config_file: Option<&Path>) -> Config { +fn get_config( + config_file: Option<&Path>, + edition: Option, + style_edition: Option, +) -> Config { let config_file_name = match config_file { - None => return Default::default(), + None => return Config::default_for_possible_style_edition(style_edition, edition), Some(file_name) => { let mut full_path = PathBuf::from("tests/config/"); full_path.push(file_name); if !full_path.exists() { - return Default::default(); + return Config::default_for_possible_style_edition(style_edition, edition); }; full_path } @@ -796,7 +827,13 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") + Config::from_toml_for_style_edition( + &def_config, + Path::new("tests/config/"), + edition, + style_edition, + ) + .expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map. From 065258659db720bfbb4987fa56137450e63d3cc4 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 23:26:00 -0500 Subject: [PATCH 14/30] feat: implement 2024 Style Edition for expr overflows --- rustfmt.toml | 1 + src/bin/main.rs | 32 ++++ src/config/mod.rs | 2 +- src/config/options.rs | 2 +- .../style-edition/overrides/rustfmt.toml | 2 + .../style_edition/overflow_delim_expr_2015.rs | 155 ++++++++++++++++++ .../style_edition/overflow_delim_expr_2024.rs | 155 ++++++++++++++++++ .../style_edition/overflow_delim_expr_2015.rs | 135 +++++++++++++++ .../style_edition/overflow_delim_expr_2024.rs | 120 ++++++++++++++ 9 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 tests/config/style-edition/overrides/rustfmt.toml create mode 100644 tests/source/configs/style_edition/overflow_delim_expr_2015.rs create mode 100644 tests/source/configs/style_edition/overflow_delim_expr_2024.rs create mode 100644 tests/target/configs/style_edition/overflow_delim_expr_2015.rs create mode 100644 tests/target/configs/style_edition/overflow_delim_expr_2024.rs diff --git a/rustfmt.toml b/rustfmt.toml index 52e4d728b64..86447eac2e6 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ error_on_line_overflow = true error_on_unformatted = true style_edition = "2024" +overflow_delimited_expr = false diff --git a/src/bin/main.rs b/src/bin/main.rs index 2e4877c7569..9e7476b1f81 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -915,4 +915,36 @@ mod test { let config = get_config(config_file, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2021); } + + #[nightly_only_test] + #[test] + fn correct_defaults_for_style_edition_loaded() { + let mut options = GetOptsOptions::default(); + options.style_edition = Some(StyleEdition::Edition2024); + let config = get_config(None, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); + } + + #[nightly_only_test] + #[test] + fn style_edition_defaults_overridden_from_config() { + let options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/overrides")); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), false); + } + + #[nightly_only_test] + #[test] + fn style_edition_defaults_overridden_from_cli() { + let mut options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/just-style-edition")); + options.inline_config = + HashMap::from([("overflow_delimited_expr".to_owned(), "false".to_owned())]); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), false); + } } diff --git a/src/config/mod.rs b/src/config/mod.rs index da7adea5a74..cd6870e3890 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -828,7 +828,7 @@ binop_separator = "Front" remove_nested_parens = true combine_control_expr = true short_array_element_width_threshold = 10 -overflow_delimited_expr = false +overflow_delimited_expr = true struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true diff --git a/src/config/options.rs b/src/config/options.rs index f7a8c114330..46db5186b11 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -627,7 +627,7 @@ config_option_with_style_edition_default!( RemoveNestedParens, bool, _ => true; CombineControlExpr, bool, _ => true; ShortArrayElementWidthThreshold, usize, _ => 10; - OverflowDelimitedExpr, bool, _ => false; + OverflowDelimitedExpr, bool, Edition2024 => true, _ => false; StructFieldAlignThreshold, usize, _ => 0; EnumDiscrimAlignThreshold, usize, _ => 0; MatchArmBlocks, bool, _ => true; diff --git a/tests/config/style-edition/overrides/rustfmt.toml b/tests/config/style-edition/overrides/rustfmt.toml new file mode 100644 index 00000000000..24205692b1f --- /dev/null +++ b/tests/config/style-edition/overrides/rustfmt.toml @@ -0,0 +1,2 @@ +style_edition = "2024" +overflow_delimited_expr = false diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2015.rs b/tests/source/configs/style_edition/overflow_delim_expr_2015.rs new file mode 100644 index 00000000000..5cb4a870fc1 --- /dev/null +++ b/tests/source/configs/style_edition/overflow_delim_expr_2015.rs @@ -0,0 +1,155 @@ +// rustfmt-style_edition: 2015 + +fn combine_blocklike() { + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing( + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2024.rs b/tests/source/configs/style_edition/overflow_delim_expr_2024.rs new file mode 100644 index 00000000000..66c95e71aa9 --- /dev/null +++ b/tests/source/configs/style_edition/overflow_delim_expr_2024.rs @@ -0,0 +1,155 @@ +// rustfmt-style_edition: 2024 + +fn combine_blocklike() { + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing( + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2015.rs b/tests/target/configs/style_edition/overflow_delim_expr_2015.rs new file mode 100644 index 00000000000..05d4b8b6d33 --- /dev/null +++ b/tests/target/configs/style_edition/overflow_delim_expr_2015.rs @@ -0,0 +1,135 @@ +// rustfmt-style_edition: 2015 + +fn combine_blocklike() { + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing(Bar { + x: value, + y: value2, + }); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing(&[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing(vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2024.rs b/tests/target/configs/style_edition/overflow_delim_expr_2024.rs new file mode 100644 index 00000000000..ecd2e8ca797 --- /dev/null +++ b/tests/target/configs/style_edition/overflow_delim_expr_2024.rs @@ -0,0 +1,120 @@ +// rustfmt-style_edition: 2024 + +fn combine_blocklike() { + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing(Bar { + x: value, + y: value2, + }); + + do_thing(x, Bar { + x: value, + y: value2, + }); + + do_thing( + x, + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing(&[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing(vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); +} + +fn combine_struct_sample() { + let identity = verify(&ctx, VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + })?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount("/", routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ]) + .launch(); +} From 46cb7d322055625c07823dea8fdfad4c07f98754 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 14 Aug 2024 16:05:24 -0500 Subject: [PATCH 15/30] refactor: improve mapping of legacy 'version' to 'style_edition' --- src/bin/main.rs | 21 ++++++- src/config/config_type.rs | 25 -------- src/config/mod.rs | 58 +++++++++++++------ src/config/options.rs | 1 + src/git-rustfmt/main.rs | 7 ++- src/lib.rs | 2 +- src/test/mod.rs | 21 ++++--- .../style-edition/just-version/rustfmt.toml | 1 + 8 files changed, 82 insertions(+), 54 deletions(-) create mode 100644 tests/config/style-edition/just-version/rustfmt.toml diff --git a/src/bin/main.rs b/src/bin/main.rs index 9e7476b1f81..14299434bc7 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -19,7 +19,7 @@ use getopts::{Matches, Options}; use crate::rustfmt::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, - FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, + FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, }; const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; @@ -746,6 +746,13 @@ impl CliOptions for GetOptsOptions { .get("style_edition") .map_or(self.style_edition, |se| StyleEdition::from_str(se).ok()) } + + fn version(&self) -> Option { + self.inline_config + .get("version") + .map(|version| Version::from_str(version).ok()) + .flatten() + } } fn edition_from_edition_str(edition_str: &str) -> Result { @@ -814,6 +821,17 @@ mod test { options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]); let config = get_config(None, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); + } + + #[nightly_only_test] + #[test] + fn version_config_file_sets_style_edition_override_correctly() { + let options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/just-version")); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); } #[nightly_only_test] @@ -858,6 +876,7 @@ mod test { ]); let config = get_config(None, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); } #[nightly_only_test] diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 4b83e974932..14217caba0a 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -134,7 +134,6 @@ macro_rules! create_config { "fn_args_layout" => self.0.set_fn_args_layout(), "hide_parse_errors" => self.0.set_hide_parse_errors(), "version" => self.0.set_version(), - "edition" => self.0.set_edition(), &_ => (), } } @@ -165,7 +164,6 @@ macro_rules! create_config { "fn_args_layout" => self.0.set_fn_args_layout(), "hide_parse_errors" => self.0.set_hide_parse_errors(), "version" => self.0.set_version(), - "edition" => self.0.set_edition(), &_ => (), } } @@ -264,7 +262,6 @@ macro_rules! create_config { self.set_fn_args_layout(); self.set_hide_parse_errors(); self.set_version(); - self.set_edition(); self } @@ -367,7 +364,6 @@ macro_rules! create_config { "fn_args_layout" => self.set_fn_args_layout(), "hide_parse_errors" => self.set_hide_parse_errors(), "version" => self.set_version(), - "edition" => self.set_edition(), &_ => (), } } @@ -585,30 +581,9 @@ macro_rules! create_config { option which takes precedence. \ The value of the `version` option will be ignored." ); - } else if matches!(self.version(), Version::Two) { - self.style_edition.2 = StyleEdition::Edition2024; - } else { - self.style_edition.2 = StyleEdition::Edition2015; } } - fn set_edition(&mut self) { - let style_edition_set = self.was_set().style_edition() - || self.was_set_cli().style_edition(); - - if style_edition_set || self.was_set().version() { - return; - } - - // User has explicitly specified an Edition value without - // explicitly specifying a Style Edition value, so the Style Edition - // must default to whatever value was provided for Edition - // as per: https://rust-lang.github.io/rfcs/3338-style-evolution.html#explanation - self.style_edition.2 = self.edition().into(); - } - - - #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/config/mod.rs b/src/config/mod.rs index cd6870e3890..8a95cc55fcb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -222,11 +222,13 @@ impl PartialConfig { self, style_edition_override: Option, edition_override: Option, + version_override: Option, dir: &Path, ) -> Config { Config::default_for_possible_style_edition( style_edition_override.or(self.style_edition), edition_override.or(self.edition), + version_override.or(self.version), ) .fill_from_parsed_config(self, dir) } @@ -236,16 +238,25 @@ impl Config { pub fn default_for_possible_style_edition( style_edition: Option, edition: Option, + version: Option, ) -> Config { - style_edition.map_or_else( - || { - edition.map_or_else( - || Config::default(), - |e| Self::default_with_style_edition(e.into()), - ) - }, - |se| Self::default_with_style_edition(se), - ) + // Ensures the configuration defaults associated with Style Editions + // follow the precedence set in + // https://rust-lang.github.io/rfcs/3338-style-evolution.html + // 'version' is a legacy alias for 'style_edition' that we'll support + // for some period of time + // FIXME(calebcartwright) - remove 'version' at some point + match (style_edition, version, edition) { + (Some(se), _, _) => Self::default_with_style_edition(se), + (None, Some(Version::Two), _) => { + Self::default_with_style_edition(StyleEdition::Edition2024) + } + (None, Some(Version::One), _) => { + Self::default_with_style_edition(StyleEdition::Edition2015) + } + (None, None, Some(e)) => Self::default_with_style_edition(e.into()), + (None, None, None) => Config::default(), + } } pub(crate) fn version_meets_requirement(&self) -> bool { @@ -275,6 +286,7 @@ impl Config { file_path: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); @@ -284,6 +296,7 @@ impl Config { file_path.parent().unwrap(), edition, style_edition, + version, ) .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } @@ -301,6 +314,7 @@ impl Config { dir: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of the nearest project file if one exists, @@ -347,17 +361,17 @@ impl Config { match resolve_project_file(dir)? { None => Ok(( - Config::default_for_possible_style_edition(style_edition, edition), + Config::default_for_possible_style_edition(style_edition, edition, version), None, )), - Some(path) => Config::from_toml_path(&path, edition, style_edition) + Some(path) => Config::from_toml_path(&path, edition, style_edition, version) .map(|config| (config, Some(path))), } } #[allow(dead_code)] pub(super) fn from_toml(toml: &str, dir: &Path) -> Result { - Self::from_toml_for_style_edition(toml, dir, None, None) + Self::from_toml_for_style_edition(toml, dir, None, None, None) } pub(crate) fn from_toml_for_style_edition( @@ -365,6 +379,7 @@ impl Config { dir: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result { let parsed: ::toml::Value = toml .parse() @@ -385,7 +400,7 @@ impl Config { if !err.is_empty() { eprint!("{err}"); } - Ok(parsed_config.to_parsed_config(style_edition, edition, dir)) + Ok(parsed_config.to_parsed_config(style_edition, edition, version, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -403,19 +418,24 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let (over_ride, edition, style_edition) = match options { - Some(ref opts) => (config_path(opts)?, opts.edition(), opts.style_edition()), - None => (None, None, None), + let (over_ride, edition, style_edition, version) = match options { + Some(ref opts) => ( + config_path(opts)?, + opts.edition(), + opts.style_edition(), + opts.version(), + ), + None => (None, None, None, None), }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref(), edition, style_edition) + Config::from_toml_path(over_ride.as_ref(), edition, style_edition, version) .map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path, edition, style_edition) + Config::from_resolved_toml_path(file_path, edition, style_edition, version) } else { Ok(( - Config::default_for_possible_style_edition(style_edition, edition), + Config::default_for_possible_style_edition(style_edition, edition, version), None, )) }; diff --git a/src/config/options.rs b/src/config/options.rs index 46db5186b11..b9e79b9a7de 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -421,6 +421,7 @@ pub trait CliOptions { fn config_path(&self) -> Option<&Path>; fn edition(&self) -> Option; fn style_edition(&self) -> Option; + fn version(&self) -> Option; } /// The edition of the syntax and semantics of code (RFC 2052). diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 14ac81322b9..b5a71588e9e 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -15,7 +15,9 @@ use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; use tracing_subscriber::EnvFilter; -use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session}; +use crate::rustfmt::{ + load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, Version, +}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -95,6 +97,9 @@ impl CliOptions for NullOptions { fn style_edition(&self) -> Option { unreachable!(); } + fn version(&self) -> Option { + unreachable!(); + } } fn uncommitted_files() -> Vec { diff --git a/src/lib.rs b/src/lib.rs index 1e9efc5ce94..7dc698dd92c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ use crate::utils::indent_next_line; pub use crate::config::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, StyleEdition, Verbosity, + Range, StyleEdition, Verbosity, Version, }; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; diff --git a/src/test/mod.rs b/src/test/mod.rs index 96706efb161..4d22f64f352 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -15,7 +15,7 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu use crate::source_file; use crate::{ is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, - StyleEdition, + StyleEdition, Version, }; use rustfmt_config_proc_macro::nightly_only_test; @@ -713,7 +713,7 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); - let (edition, style_edition) = get_editions_from_comments(&sig_comments); + let (edition, style_edition, version) = get_editions_from_comments(&sig_comments); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. @@ -722,12 +722,14 @@ fn read_config(filename: &Path) -> Config { sig_comments.get("config").map(Path::new), edition, style_edition, + version, ) } else { get_config( filename.with_extension("toml").file_name().map(Path::new), edition, style_edition, + version, ) }; @@ -761,7 +763,7 @@ enum IdempotentCheckError { fn get_editions_from_comments( comments: &HashMap, -) -> (Option, Option) { +) -> (Option, Option, Option) { ( comments .get("edition") @@ -769,6 +771,9 @@ fn get_editions_from_comments( comments.get("style_edition").map(|se| { StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se)) }), + comments + .get("version") + .map(|v| Version::from_str(v).expect(&format!("invalid version value: '{}'", v))), ) } @@ -778,8 +783,8 @@ fn idempotent_check( ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - let (edition, style_edition) = get_editions_from_comments(&sig_comments); - Config::from_toml_path(config_file_path, edition, style_edition) + let (edition, style_edition, version) = get_editions_from_comments(&sig_comments); + Config::from_toml_path(config_file_path, edition, style_edition, version) .expect("`rustfmt.toml` not found") } else { read_config(filename) @@ -808,14 +813,15 @@ fn get_config( config_file: Option<&Path>, edition: Option, style_edition: Option, + version: Option, ) -> Config { let config_file_name = match config_file { - None => return Config::default_for_possible_style_edition(style_edition, edition), + None => return Config::default_for_possible_style_edition(style_edition, edition, version), Some(file_name) => { let mut full_path = PathBuf::from("tests/config/"); full_path.push(file_name); if !full_path.exists() { - return Config::default_for_possible_style_edition(style_edition, edition); + return Config::default_for_possible_style_edition(style_edition, edition, version); }; full_path } @@ -832,6 +838,7 @@ fn get_config( Path::new("tests/config/"), edition, style_edition, + version, ) .expect("invalid TOML") } diff --git a/tests/config/style-edition/just-version/rustfmt.toml b/tests/config/style-edition/just-version/rustfmt.toml new file mode 100644 index 00000000000..1082fd88889 --- /dev/null +++ b/tests/config/style-edition/just-version/rustfmt.toml @@ -0,0 +1 @@ +version = "Two" From 193051438d7083f465f68c5fdca86c5e02b00a8f Mon Sep 17 00:00:00 2001 From: ding-young Date: Wed, 28 Aug 2024 13:24:17 +0900 Subject: [PATCH 16/30] update rewrite_assignment to return RewriteResult --- src/expr.rs | 70 +++++++++++++++++++++++++++++---------------------- src/items.rs | 18 +++++++------ src/macros.rs | 21 +++++++--------- src/types.rs | 5 ++-- 4 files changed, 63 insertions(+), 51 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 02372e7be13..35b7bada92d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -194,10 +194,10 @@ pub(crate) fn format_expr( rewrite_path(context, PathContext::Expr, qself, path, shape).ok() } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { - rewrite_assignment(context, lhs, rhs, None, shape) + rewrite_assignment(context, lhs, rhs, None, shape).ok() } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape) + rewrite_assignment(context, lhs, rhs, Some(op), shape).ok() } ast::ExprKind::Continue(ref opt_label) => { let id_str = match *opt_label { @@ -2050,15 +2050,21 @@ fn rewrite_assignment( rhs: &ast::Expr, op: Option<&ast::BinOp>, shape: Shape, -) -> Option { +) -> RewriteResult { let operator_str = match op { Some(op) => context.snippet(op.span), None => "=", }; // 1 = space between lhs and operator. - let lhs_shape = shape.sub_width(operator_str.len() + 1)?; - let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); + let lhs_shape = shape + .sub_width(operator_str.len() + 1) + .max_width_error(shape.width, lhs.span())?; + let lhs_str = format!( + "{} {}", + lhs.rewrite_result(context, lhs_shape)?, + operator_str + ); rewrite_assign_rhs( context, @@ -2089,7 +2095,7 @@ pub(crate) fn rewrite_assign_rhs, R: Rewrite>( ex: &R, rhs_kind: &RhsAssignKind<'_>, shape: Shape, -) -> Option { +) -> RewriteResult { rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default) } @@ -2100,7 +2106,7 @@ pub(crate) fn rewrite_assign_rhs_expr( shape: Shape, rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, -) -> Option { +) -> RewriteResult { let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') { shape.indent.width() } else { @@ -2122,7 +2128,7 @@ pub(crate) fn rewrite_assign_rhs_expr( context, ex, orig_shape, - ex.rewrite(context, orig_shape), + ex.rewrite_result(context, orig_shape), rhs_kind, rhs_tactics, has_rhs_comment, @@ -2136,10 +2142,10 @@ pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( shape: Shape, rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, -) -> Option { +) -> RewriteResult { let lhs = lhs.into(); let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; - Some(lhs + &rhs) + Ok(lhs + &rhs) } pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite + Spanned>( @@ -2161,8 +2167,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite + Spa } else { shape }; - let rhs = - rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics).unknown_error()?; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; if contains_comment { let rhs = rhs.trim_start(); combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend) @@ -2175,23 +2180,25 @@ fn choose_rhs( context: &RewriteContext<'_>, expr: &R, shape: Shape, - orig_rhs: Option, + orig_rhs: RewriteResult, _rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, has_rhs_comment: bool, -) -> Option { +) -> RewriteResult { match orig_rhs { - Some(ref new_str) if new_str.is_empty() => Some(String::new()), - Some(ref new_str) - if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => - { - Some(format!(" {new_str}")) + Ok(ref new_str) if new_str.is_empty() => Ok(String::new()), + Ok(ref new_str) if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => { + Ok(format!(" {new_str}")) } _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)?; - let new_rhs = expr.rewrite(context, new_shape); + let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics) + // TODO(ding-young) Ideally, we can replace unknown_error() with max_width_error(), + // but this requires either implementing the Spanned trait for ast::GenericBounds + // or grabbing the span from the call site. + .unknown_error()?; + let new_rhs = expr.rewrite_result(context, new_shape); let new_indent_str = &shape .indent .block_indent(context.config) @@ -2199,24 +2206,27 @@ fn choose_rhs( let before_space_str = if has_rhs_comment { "" } else { " " }; match (orig_rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref new_rhs)) + (Ok(ref orig_rhs), Ok(ref new_rhs)) if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) => { - Some(format!("{before_space_str}{orig_rhs}")) + Ok(format!("{before_space_str}{orig_rhs}")) } - (Some(ref orig_rhs), Some(ref new_rhs)) + (Ok(ref orig_rhs), Ok(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => { - Some(format!("{new_indent_str}{new_rhs}")) + Ok(format!("{new_indent_str}{new_rhs}")) } - (None, Some(ref new_rhs)) => Some(format!("{new_indent_str}{new_rhs}")), - (None, None) if rhs_tactics == RhsTactics::AllowOverflow => { + (Err(_), Ok(ref new_rhs)) => Ok(format!("{new_indent_str}{new_rhs}")), + (Err(_), Err(_)) if rhs_tactics == RhsTactics::AllowOverflow => { let shape = shape.infinite_width(); - expr.rewrite(context, shape) + expr.rewrite_result(context, shape) .map(|s| format!("{}{}", before_space_str, s)) } - (None, None) => None, - (Some(orig_rhs), _) => Some(format!("{before_space_str}{orig_rhs}")), + // When both orig_rhs and new_rhs result in errors, we currently propagate + // the error from the second attempt since it is more generous with + // width constraints. This decision is somewhat arbitrary and is open to change. + (Err(_), Err(new_rhs_err)) => Err(new_rhs_err), + (Ok(orig_rhs), _) => Ok(format!("{before_space_str}{orig_rhs}")), } } } diff --git a/src/items.rs b/src/items.rs index 3894ee2cdf8..4ea9751e816 100644 --- a/src/items.rs +++ b/src/items.rs @@ -137,8 +137,7 @@ impl Rewrite for ast::Local { init, &RhsAssignKind::Expr(&init.kind, init.span), nested_shape, - ) - .max_width_error(shape.width, self.span())?; + )?; if let Some(block) = else_block { let else_kw_span = init.span.between(block.span); @@ -711,7 +710,8 @@ impl<'a> FmtVisitor<'a> { shape, &RhsAssignKind::Expr(&ex.kind, ex.span), RhsTactics::AllowOverflow, - )? + ) + .ok()? } else { variant_body }; @@ -1206,7 +1206,8 @@ pub(crate) fn format_trait( shape, &RhsAssignKind::Bounds, RhsTactics::ForceNextLineWithoutIndent, - )?; + ) + .ok()?; } // Rewrite where-clause. @@ -1396,6 +1397,7 @@ pub(crate) fn format_trait_alias( shape.sub_width(1)?, ) .map(|s| s + ";") + .ok() } fn format_unit_struct( @@ -1835,7 +1837,9 @@ fn rewrite_ty( // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape) + .map(|s| s + ";") + .ok() } else { Some(format!("{result};")) } @@ -1931,8 +1935,7 @@ pub(crate) fn rewrite_struct_field( 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) - .unknown_error()?; + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?; // 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() @@ -3421,6 +3424,7 @@ impl Rewrite for ast::ForeignItem { shape.sub_width(1)?, ) .map(|s| s + ";") + .ok() } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); diff --git a/src/macros.rs b/src/macros.rs index 51ded869229..5e537002324 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1437,18 +1437,15 @@ fn format_lazy_static( id, ty.rewrite_result(context, nested_shape)? )); - result.push_str( - &rewrite_assign_rhs( - context, - stmt, - &*expr, - &RhsAssignKind::Expr(&expr.kind, expr.span), - nested_shape - .sub_width(1) - .max_width_error(nested_shape.width, expr.span)?, - ) - .unknown_error()?, - ); + result.push_str(&rewrite_assign_rhs( + context, + stmt, + &*expr, + &RhsAssignKind::Expr(&expr.kind, expr.span), + nested_shape + .sub_width(1) + .max_width_error(nested_shape.width, expr.span)?, + )?); result.push(';'); if i != last { result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); diff --git a/src/types.rs b/src/types.rs index 76eb0ea0529..d1cd291d51f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -475,7 +475,7 @@ impl Rewrite for ast::WherePredicate { format!("{type_str}{colon}") }; - rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)? + rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape).ok()? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, @@ -488,7 +488,8 @@ impl Rewrite for ast::WherePredicate { .. }) => { let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape) + .ok()? } }; From 35b3889c77fd98b2c9ec8ab93ffd516187bdd7f6 Mon Sep 17 00:00:00 2001 From: ding-young Date: Fri, 23 Aug 2024 18:29:59 +0900 Subject: [PATCH 17/30] impl rewrite_result for ControlFlow, Stmt, update rewrite_index --- src/comment.rs | 7 ++-- src/expr.rs | 85 +++++++++++++++++++++++++++++-------------------- src/items.rs | 2 +- src/overflow.rs | 11 ++++--- src/stmt.rs | 30 ++++++++++++----- src/types.rs | 26 +++++++++------ 6 files changed, 101 insertions(+), 60 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index 5bf3c1a725c..c8cadf364da 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1703,12 +1703,11 @@ impl<'a> Iterator for CommentCodeSlices<'a> { } /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text -/// (if it fits in the width/offset, else return `None`), else return `new` pub(crate) fn recover_comment_removed( new: String, span: Span, context: &RewriteContext<'_>, -) -> Option { +) -> String { let snippet = context.snippet(span); if snippet != new && changed_comment_content(snippet, &new) { // We missed some comments. Warn and keep the original text. @@ -1722,9 +1721,9 @@ pub(crate) fn recover_comment_removed( )], ); } - Some(snippet.to_owned()) + snippet.to_owned() } else { - Some(new) + new } } diff --git a/src/expr.rs b/src/expr.rs index 35b7bada92d..8381e3ab083 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -278,7 +278,7 @@ pub(crate) fn format_expr( ) .ok(), ast::ExprKind::Index(ref expr, ref index, _) => { - rewrite_index(&**expr, &**index, context, shape) + rewrite_index(&**expr, &**index, context, shape).ok() } ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( &**expr, @@ -435,7 +435,7 @@ pub(crate) fn format_expr( }; expr_rw - .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) + .map(|expr_str| recover_comment_removed(expr_str, expr.span, context)) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); let attrs_str = attrs.rewrite(context, shape)?; @@ -672,6 +672,7 @@ pub(crate) fn rewrite_cond( String::from("\n") + &shape.indent.block_only().to_string(context.config); control_flow .rewrite_cond(context, shape, &alt_block_sep) + .ok() .map(|rw| rw.0) }), } @@ -896,10 +897,12 @@ impl<'a> ControlFlow<'a> { expr: &ast::Expr, shape: Shape, offset: usize, - ) -> Option { + ) -> RewriteResult { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr); - let cond_shape = shape.offset_left(offset)?; + let cond_shape = shape + .offset_left(offset) + .max_width_error(shape.width, expr.span)?; if let Some(pat) = self.pat { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() @@ -907,9 +910,10 @@ impl<'a> ControlFlow<'a> { format!("{} ", self.matcher) }; let pat_shape = cond_shape - .offset_left(matcher.len())? - .sub_width(self.connector.len())?; - let pat_string = pat.rewrite(context, pat_shape)?; + .offset_left(matcher.len()) + .and_then(|s| s.sub_width(self.connector.len())) + .max_width_error(cond_shape.width, pat.span)?; + let pat_string = pat.rewrite_result(context, pat_shape)?; let comments_lo = context .snippet_provider .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim()); @@ -923,14 +927,13 @@ impl<'a> ControlFlow<'a> { RhsTactics::Default, comments_span, true, - ) - .ok(); + ); } - let expr_rw = expr.rewrite(context, cond_shape); + let expr_rw = expr.rewrite_result(context, cond_shape); // The expression may (partially) fit on the current line. // We do not allow splitting between `if` and condition. - if self.keyword == "if" || expr_rw.is_some() { + if self.keyword == "if" || expr_rw.is_ok() { return expr_rw; } @@ -939,7 +942,7 @@ impl<'a> ControlFlow<'a> { .block_indent(context.config.tab_spaces()) .with_max_width(context.config); let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - expr.rewrite(context, nested_shape) + expr.rewrite_result(context, nested_shape) .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) } @@ -948,7 +951,7 @@ impl<'a> ControlFlow<'a> { context: &RewriteContext<'_>, shape: Shape, alt_block_sep: &str, - ) -> Option<(String, usize)> { + ) -> Result<(String, usize), RewriteError> { // Do not take the rhs overhead from the upper expressions into account // when rewriting pattern. let new_width = context.budget(shape.used_width()); @@ -959,7 +962,9 @@ 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)? + fresh_shape + .offset_left(7) + .max_width_error(fresh_shape.width, self.span)? } else { fresh_shape }; @@ -995,7 +1000,7 @@ impl<'a> ControlFlow<'a> { if let Some(cond_str) = trial { if cond_str.len() <= context.config.single_line_if_else_max_width() { - return Some((cond_str, 0)); + return Ok((cond_str, 0)); } } } @@ -1048,7 +1053,7 @@ impl<'a> ControlFlow<'a> { label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 }; - Some(( + Ok(( format!( "{}{}{}{}{}", label_string, @@ -1114,13 +1119,17 @@ pub(crate) fn rewrite_else_kw_with_comments( impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); let alt_block_sep = &shape.indent.to_string_with_newline(context.config); let (cond_str, used_width) = self.rewrite_cond(context, shape, alt_block_sep)?; // If `used_width` is 0, it indicates that whole control flow is written in a single line. if used_width == 0 { - return Some(cond_str); + return Ok(cond_str); } let block_width = shape.width.saturating_sub(used_width); @@ -1138,8 +1147,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let block_str = { let old_val = context.is_if_else_block.replace(self.else_block.is_some()); let result = - rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true) - .ok(); + rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true); context.is_if_else_block.replace(old_val); result? }; @@ -1165,7 +1173,7 @@ impl<'a> Rewrite for ControlFlow<'a> { true, mk_sp(else_block.span.lo(), self.span.hi()), ) - .rewrite(context, shape) + .rewrite_result(context, shape) } _ => { last_in_chain = true; @@ -1176,6 +1184,7 @@ impl<'a> Rewrite for ControlFlow<'a> { ..shape }; format_expr(else_block, ExprType::Statement, context, else_shape) + .unknown_error() } }; @@ -1190,7 +1199,7 @@ impl<'a> Rewrite for ControlFlow<'a> { result.push_str(&rewrite?); } - Some(result) + Ok(result) } } @@ -1567,8 +1576,8 @@ fn rewrite_index( index: &ast::Expr, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - let expr_str = expr.rewrite(context, shape)?; +) -> RewriteResult { + let expr_str = expr.rewrite_result(context, shape)?; let offset = last_line_width(&expr_str) + 1; let rhs_overhead = shape.rhs_overhead(context.config); @@ -1583,37 +1592,45 @@ fn rewrite_index( .and_then(|shape| shape.sub_width(1)), IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1), } - }; - let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); + } + .max_width_error(shape.width, index.span()); + let orig_index_rw = index_shape.and_then(|s| index.rewrite_result(context, s)); // Return if index fits in a single line. match orig_index_rw { - Some(ref index_str) if !index_str.contains('\n') => { - return Some(format!("{expr_str}[{index_str}]")); + Ok(ref index_str) if !index_str.contains('\n') => { + return Ok(format!("{expr_str}[{index_str}]")); } _ => (), } // 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)?; - let index_shape = index_shape.sub_width(1 + rhs_overhead)?; - let new_index_rw = index.rewrite(context, index_shape); + 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())?; + let new_index_rw = index.rewrite_result(context, index_shape); match (orig_index_rw, new_index_rw) { - (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( + (_, Ok(ref new_index_str)) if !new_index_str.contains('\n') => Ok(format!( "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), new_index_str, )), - (None, Some(ref new_index_str)) => Some(format!( + (Err(_), Ok(ref new_index_str)) => Ok(format!( "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), new_index_str, )), - (Some(ref index_str), _) => Some(format!("{expr_str}[{index_str}]")), - _ => None, + (Ok(ref index_str), _) => Ok(format!("{expr_str}[{index_str}]")), + // When both orig_index_rw and new_index_rw result in errors, we currently propagate the + // error from the second attempt since it is more generous with width constraints. + // This decision is somewhat arbitrary and is open to change. + (Err(_), Err(new_index_rw_err)) => Err(new_index_rw_err), } } diff --git a/src/items.rs b/src/items.rs index 4ea9751e816..89fb9bda9df 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2077,7 +2077,7 @@ fn rewrite_static( true, ) .ok() - .and_then(|res| recover_comment_removed(res, static_parts.span, context)) + .map(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{prefix}{ty_str};")) diff --git a/src/overflow.rs b/src/overflow.rs index 510ad3c642e..dc4716a81af 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -19,7 +19,7 @@ use crate::lists::{ }; use crate::macros::MacroArg; use crate::patterns::{can_be_overflowed_pat, TuplePatField}; -use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -90,6 +90,10 @@ impl<'a> Rewrite for OverflowableItem<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { self.map(|item| item.rewrite(context, shape)) } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + self.map(|item| item.rewrite_result(context, shape)) + } } impl<'a> Spanned for OverflowableItem<'a> { @@ -617,7 +621,7 @@ impl<'a> Context<'a> { tactic } - fn rewrite_items(&self) -> Option<(bool, String)> { + fn rewrite_items(&self) -> Result<(bool, String), RewriteError> { let span = self.items_span(); debug!("items: {:?}", self.items); @@ -661,7 +665,6 @@ impl<'a> Context<'a> { .ends_with_newline(ends_with_newline); write_list(&list_items, &fmt) - .ok() .map(|items_str| (tactic == DefinitiveListTactic::Horizontal, items_str)) } @@ -718,7 +721,7 @@ impl<'a> Context<'a> { } fn rewrite(&self, shape: Shape) -> RewriteResult { - let (extendable, items_str) = self.rewrite_items().unknown_error()?; + let (extendable, items_str) = self.rewrite_items()?; // If we are using visual indent style and failed to format, retry with block indent. if !self.context.use_block_indent() diff --git a/src/stmt.rs b/src/stmt.rs index 38433433c6b..4f31705295e 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::{format_expr, is_simple_block, ExprType}; -use crate::rewrite::{Rewrite, RewriteContext}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; use crate::spanned::Spanned; @@ -90,6 +90,14 @@ impl<'a> Stmt<'a> { impl<'a> Rewrite for Stmt<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> crate::rewrite::RewriteResult { let expr_type = if context.config.style_edition() >= StyleEdition::Edition2024 && self.is_last_expr() { ExprType::SubExpression @@ -112,11 +120,11 @@ fn format_stmt( stmt: &ast::Stmt, expr_type: ExprType, is_last_expr: bool, -) -> Option { - skip_out_of_file_lines_range!(context, stmt.span()); +) -> RewriteResult { + skip_out_of_file_lines_range_err!(context, stmt.span()); let result = match stmt.kind { - ast::StmtKind::Let(ref local) => local.rewrite(context, shape), + ast::StmtKind::Let(ref local) => local.rewrite_result(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) { ";" @@ -124,10 +132,16 @@ fn format_stmt( "" }; - let shape = shape.sub_width(suffix.len())?; - format_expr(ex, expr_type, context, shape).map(|s| s + suffix) + let shape = shape + .sub_width(suffix.len()) + .max_width_error(shape.width, ex.span())?; + format_expr(ex, expr_type, context, shape) + .map(|s| s + suffix) + .unknown_error() + } + ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => { + Err(RewriteError::Unknown) } - ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, }; - result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) + result.map(|res| recover_comment_removed(res, stmt.span(), context)) } diff --git a/src/types.rs b/src/types.rs index d1cd291d51f..af57a5843db 100644 --- a/src/types.rs +++ b/src/types.rs @@ -480,8 +480,8 @@ impl Rewrite for ast::WherePredicate { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, - .. - }) => rewrite_bounded_lifetime(lifetime, bounds, context, shape)?, + span, + }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape).ok()?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, @@ -553,23 +553,27 @@ fn rewrite_generic_args( fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], + span: Span, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - let result = lt.rewrite(context, shape)?; +) -> RewriteResult { + let result = lt.rewrite_result(context, shape)?; if bounds.is_empty() { - Some(result) + Ok(result) } 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 result = format!( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, true).ok()? + join_bounds(context, shape, bounds, true)? ); - Some(result) + Ok(result) } } @@ -580,8 +584,12 @@ impl Rewrite for ast::AnonConst { } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option { - Some(rewrite_ident(context, self.ident).to_owned()) + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, _: Shape) -> RewriteResult { + Ok(rewrite_ident(context, self.ident).to_owned()) } } From 40909b4331a7bc481f5bcef149efa388f46222f7 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 08:34:52 +0200 Subject: [PATCH 18/30] Fix `test_editions_2015_2018_2021_identical` Was comparing unit type. --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 8a95cc55fcb..d35a249a80a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -900,7 +900,7 @@ make_backup = false Config::default_with_style_edition(style_edition) .all_options() .to_toml() - .unwrap(); + .unwrap() }; let edition2015 = get_edition_toml(StyleEdition::Edition2015); let edition2018 = get_edition_toml(StyleEdition::Edition2018); From 9d407bfd1b69801d53c9c01dc8988f62d6235fed Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 08:36:44 +0200 Subject: [PATCH 19/30] Avoid allocating intermediate strings in `ItemizedBlock::trimmed_block_as_string` --- src/comment.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index c8cadf364da..1e35395cfb3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -533,10 +533,11 @@ impl ItemizedBlock { /// Returns the block as a string, with each line trimmed at the start. fn trimmed_block_as_string(&self) -> String { - self.lines - .iter() - .map(|line| format!("{} ", line.trim_start())) - .collect::() + self.lines.iter().fold(String::new(), |mut acc, line| { + acc.push_str(line.trim_start()); + acc.push(' '); + acc + }) } /// Returns the block as a string under its original form. From 5d30ce68441fabbf4e2b1c789b1af2327d9dc869 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 09:25:05 +0200 Subject: [PATCH 20/30] Avoid allocating intermediate strings in `determine_operation` --- src/bin/main.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 14299434bc7..3a0427d8372 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -462,16 +462,15 @@ fn print_version() { fn determine_operation(matches: &Matches) -> Result { if matches.opt_present("h") { - let topic = matches.opt_str("h"); - if topic.is_none() { + let Some(topic) = matches.opt_str("h") else { return Ok(Operation::Help(HelpOp::None)); - } else if topic == Some("config".to_owned()) { - return Ok(Operation::Help(HelpOp::Config)); - } else if topic == Some("file-lines".to_owned()) && is_nightly() { - return Ok(Operation::Help(HelpOp::FileLines)); - } else { - return Err(OperationError::UnknownHelpTopic(topic.unwrap())); - } + }; + + return match topic.as_str() { + "config" => Ok(Operation::Help(HelpOp::Config)), + "file-lines" if is_nightly() => Ok(Operation::Help(HelpOp::FileLines)), + _ => Err(OperationError::UnknownHelpTopic(topic)), + }; } let mut free_matches = matches.free.iter(); From 1681c91a356af14a2425a2017fea2fc675c8200a Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 9 Jul 2024 02:20:31 -0400 Subject: [PATCH 21/30] implement version-sorting algorithm for rust identifiers The algorithm is described in the [style guide] and was introduced in `r-l/rust 115046`. [style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting --- src/lib.rs | 1 + src/sort.rs | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+) create mode 100644 src/sort.rs diff --git a/src/lib.rs b/src/lib.rs index 7dc698dd92c..1f186b87767 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ mod rewrite; pub(crate) mod rustfmt_diff; mod shape; mod skip; +mod sort; pub(crate) mod source_file; pub(crate) mod source_map; mod spanned; diff --git a/src/sort.rs b/src/sort.rs new file mode 100644 index 00000000000..670f664a119 --- /dev/null +++ b/src/sort.rs @@ -0,0 +1,368 @@ +use itertools::EitherOrBoth; +use itertools::Itertools; + +/// Iterator which breaks an identifier into various [VersionChunk]s. +struct VersionChunkIter<'a> { + ident: &'a str, + start: usize, +} + +impl<'a> VersionChunkIter<'a> { + pub(crate) fn new(ident: &'a str) -> Self { + Self { ident, start: 0 } + } + + fn parse_numeric_chunk( + &mut self, + mut chars: std::str::CharIndices<'a>, + ) -> Option> { + let mut end = self.start; + let mut is_end_of_chunk = false; + + while let Some((idx, c)) = chars.next() { + end = self.start + idx; + + if c.is_ascii_digit() { + continue; + } + + is_end_of_chunk = true; + break; + } + + let source = if is_end_of_chunk { + let value = &self.ident[self.start..end]; + self.start = end; + value + } else { + let value = &self.ident[self.start..]; + self.start = self.ident.len(); + value + }; + + let zeros = source.chars().take_while(|c| *c == '0').count(); + let value = source.parse::().ok()?; + + Some(VersionChunk::Number { + value, + zeros, + source, + }) + } + + fn parse_str_chunk( + &mut self, + mut chars: std::str::CharIndices<'a>, + ) -> Option> { + let mut end = self.start; + let mut is_end_of_chunk = false; + + while let Some((idx, c)) = chars.next() { + end = self.start + idx; + + if c == '_' { + is_end_of_chunk = true; + break; + } + + if !c.is_numeric() { + continue; + } + + is_end_of_chunk = true; + break; + } + + let source = if is_end_of_chunk { + let value = &self.ident[self.start..end]; + self.start = end; + value + } else { + let value = &self.ident[self.start..]; + self.start = self.ident.len(); + value + }; + + Some(VersionChunk::Str(source)) + } +} + +impl<'a> Iterator for VersionChunkIter<'a> { + type Item = VersionChunk<'a>; + + fn next(&mut self) -> Option { + let mut chars = self.ident[self.start..].char_indices(); + let (_, next) = chars.next()?; + + if next == '_' { + self.start = self.start + next.len_utf8(); + return Some(VersionChunk::Underscore); + } + + if next.is_ascii_digit() { + return self.parse_numeric_chunk(chars); + } + + self.parse_str_chunk(chars) + } +} + +/// Represents a chunk in the version-sort algorithm +#[derive(Debug, PartialEq, Eq)] +enum VersionChunk<'a> { + /// A single `_` in an identifier. Underscores are sorted before all other characters. + Underscore, + /// A &str chunk in the version sort. + Str(&'a str), + /// A numeric chunk in the version sort. Keeps track of the numeric value and leading zeros. + Number { + value: usize, + zeros: usize, + source: &'a str, + }, +} + +/// Determine which side of the version-sort comparison had more leading zeros. +#[derive(Debug, PartialEq, Eq)] +enum MoreLeadingZeros { + Left, + Right, + Equal, +} + +/// Compare two identifiers based on the version sorting algorithm described in [the style guide] +/// +/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting +pub(crate) fn version_sort(a: &str, b: &str) -> std::cmp::Ordering { + let iter_a = VersionChunkIter::new(a); + let iter_b = VersionChunkIter::new(b); + let mut more_leading_zeros = MoreLeadingZeros::Equal; + + for either_or_both in iter_a.zip_longest(iter_b) { + match either_or_both { + EitherOrBoth::Left(_) => return std::cmp::Ordering::Greater, + EitherOrBoth::Right(_) => return std::cmp::Ordering::Less, + EitherOrBoth::Both(a, b) => match (a, b) { + (VersionChunk::Underscore, VersionChunk::Underscore) => { + continue; + } + (VersionChunk::Underscore, _) => return std::cmp::Ordering::Less, + (_, VersionChunk::Underscore) => return std::cmp::Ordering::Greater, + (VersionChunk::Str(ca), VersionChunk::Str(cb)) + | (VersionChunk::Str(ca), VersionChunk::Number { source: cb, .. }) + | (VersionChunk::Number { source: ca, .. }, VersionChunk::Str(cb)) => { + match ca.cmp(&cb) { + std::cmp::Ordering::Equal => { + continue; + } + order @ _ => return order, + } + } + ( + VersionChunk::Number { + value: va, + zeros: lza, + .. + }, + VersionChunk::Number { + value: vb, + zeros: lzb, + .. + }, + ) => match va.cmp(&vb) { + std::cmp::Ordering::Equal => { + if lza == lzb { + continue; + } + + if more_leading_zeros == MoreLeadingZeros::Equal && lza > lzb { + more_leading_zeros = MoreLeadingZeros::Left; + } else if more_leading_zeros == MoreLeadingZeros::Equal && lza < lzb { + more_leading_zeros = MoreLeadingZeros::Right; + } + continue; + } + order @ _ => return order, + }, + }, + } + } + + match more_leading_zeros { + MoreLeadingZeros::Equal => std::cmp::Ordering::Equal, + MoreLeadingZeros::Left => std::cmp::Ordering::Less, + MoreLeadingZeros::Right => std::cmp::Ordering::Greater, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_chunks() { + let mut iter = VersionChunkIter::new("x86_128"); + assert_eq!(iter.next(), Some(VersionChunk::Str("x"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 86, + zeros: 0, + source: "86" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 128, + zeros: 0, + source: "128" + }) + ); + assert_eq!(iter.next(), None); + + let mut iter = VersionChunkIter::new("w005s09t"); + assert_eq!(iter.next(), Some(VersionChunk::Str("w"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 5, + zeros: 2, + source: "005" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("s"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 9, + zeros: 1, + source: "09" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("t"))); + assert_eq!(iter.next(), None); + + let mut iter = VersionChunkIter::new("ZY_WX"); + assert_eq!(iter.next(), Some(VersionChunk::Str("ZY"))); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!(iter.next(), Some(VersionChunk::Str("WX"))); + + let mut iter = VersionChunkIter::new("_v1"); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 1, + zeros: 0, + source: "1" + }) + ); + + let mut iter = VersionChunkIter::new("_1v"); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 1, + zeros: 0, + source: "1" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + + let mut iter = VersionChunkIter::new("v009"); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 9, + zeros: 2, + source: "009" + }) + ); + } + + #[test] + fn test_version_sort() { + let mut input = vec!["", "b", "a"]; + let expected = vec!["", "a", "b"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["x7x", "xxx"]; + let expected = vec!["x7x", "xxx"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["applesauce", "apple"]; + let expected = vec!["apple", "applesauce"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["aaaaa", "aaa_a"]; + let expected = vec!["aaa_a", "aaaaa"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["AAAAA", "AAA1A", "BBBBB", "BB_BB", "C3CCC"]; + let expected = vec!["AAA1A", "AAAAA", "BB_BB", "BBBBB", "C3CCC"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["1_000_000", "1_010_001"]; + let expected = vec!["1_000_000", "1_010_001"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec![ + "5", "50", "500", "5_000", "5_005", "5_050", "5_500", "50_000", "50_005", "50_050", + "50_500", + ]; + let expected = vec![ + "5", "5_000", "5_005", "5_050", "5_500", "50", "50_000", "50_005", "50_050", "50_500", + "500", + ]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["X86_64", "x86_64", "X86_128", "x86_128"]; + let expected = vec!["X86_64", "X86_128", "x86_64", "x86_128"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["__", "_"]; + let expected = vec!["_", "__"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["foo_", "foo"]; + let expected = vec!["foo", "foo_"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["A", "AA", "B", "a", "aA", "aa", "b"]; + let expected = vec!["A", "AA", "B", "a", "aA", "aa", "b"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec![ + "x86_128", "usize", "uz", "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01", + "v1", "v009", "x87", "zyxw", "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW", + "ZYXW", "v09", "v9", "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32", + "ua", "x86_64", "ZYXW_", "a1", "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128", + "u256", + ]; + let expected = vec![ + "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW", "ZYXW", "ZYXW_", "a1", + "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128", "u256", "ua", "usize", "uz", + "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01", "v1", "v009", "v09", "v9", + "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32", "x86_64", "x86_128", + "x87", "zyxw", + ]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected) + } +} From 296417260c6a53fca85a0adf1dfd6a9b3760768f Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 9 Jul 2024 02:28:11 -0400 Subject: [PATCH 22/30] use version-sort when reordering imports using `style_edition=2024` --- src/imports.rs | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/imports.rs b/src/imports.rs index 94b62ef7aa0..868314354b0 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,6 +21,7 @@ use crate::lists::{ }; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; +use crate::sort::version_sort; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{is_same_visibility, mk_sp, rewrite_ident}; @@ -923,7 +924,7 @@ impl Ord for UseSegment { | (Crate(ref a), Crate(ref b)) => match (a, b) { (Some(sa), Some(sb)) => { if self.style_edition >= StyleEdition::Edition2024 { - sa.trim_start_matches("r#").cmp(sb.trim_start_matches("r#")) + version_sort(sa.trim_start_matches("r#"), sb.trim_start_matches("r#")) } else { a.cmp(b) } @@ -937,20 +938,26 @@ impl Ord for UseSegment { } else { (pia.as_str(), pib.as_str()) }; - // snake_case < CamelCase < UPPER_SNAKE_CASE - if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) { - return Ordering::Greater; - } - if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) { - return Ordering::Less; - } - if is_upper_snake_case(ia) && !is_upper_snake_case(ib) { - return Ordering::Greater; - } - if !is_upper_snake_case(ia) && is_upper_snake_case(ib) { - return Ordering::Less; - } - let ident_ord = ia.cmp(ib); + + let ident_ord = if self.style_edition >= StyleEdition::Edition2024 { + version_sort(ia, ib) + } else { + // snake_case < CamelCase < UPPER_SNAKE_CASE + if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) { + return Ordering::Greater; + } + if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) { + return Ordering::Less; + } + if is_upper_snake_case(ia) && !is_upper_snake_case(ib) { + return Ordering::Greater; + } + if !is_upper_snake_case(ia) && is_upper_snake_case(ib) { + return Ordering::Less; + } + ia.cmp(ib) + }; + if ident_ord != Ordering::Equal { return ident_ord; } @@ -959,8 +966,7 @@ impl Ord for UseSegment { (Some(_), None) => Ordering::Greater, (Some(aas), Some(abs)) => { if self.style_edition >= StyleEdition::Edition2024 { - aas.trim_start_matches("r#") - .cmp(abs.trim_start_matches("r#")) + version_sort(aas.trim_start_matches("r#"), abs.trim_start_matches("r#")) } else { aas.cmp(abs) } From ae59ee755afdbc086c10ce8d693f363a40e3216e Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 16 Aug 2024 14:34:06 -0400 Subject: [PATCH 23/30] sort rustfmt imports The version-sort algorithm makes changes to the sort order of imports, and we're updating them here for the self tests. --- config_proc_macro/src/utils.rs | 2 +- src/attr.rs | 12 ++++++------ src/bin/main.rs | 8 ++++---- src/chains.rs | 4 ++-- src/closures.rs | 6 +++--- src/comment.rs | 4 ++-- src/config/file_lines.rs | 2 +- src/config/options.rs | 4 ++-- src/emitter/checkstyle.rs | 2 +- src/emitter/json.rs | 2 +- src/emitter/modified_lines.rs | 2 +- src/expr.rs | 18 +++++++++--------- src/formatting.rs | 2 +- src/git-rustfmt/main.rs | 2 +- src/imports.rs | 6 +++--- src/items.rs | 17 ++++++++--------- src/lib.rs | 4 ++-- src/lists.rs | 2 +- src/macros.rs | 18 +++++++++--------- src/matches.rs | 10 +++++----- src/missed_spans.rs | 4 ++-- src/modules.rs | 2 +- src/overflow.rs | 8 ++++---- src/pairs.rs | 2 +- src/parse/macros/asm.rs | 2 +- src/parse/macros/cfg_if.rs | 2 +- src/parse/macros/mod.rs | 4 ++-- src/parse/parser.rs | 6 +++--- src/parse/session.rs | 5 +++-- src/patterns.rs | 14 +++++++------- src/reorder.rs | 6 +++--- src/rewrite.rs | 2 +- src/rustfmt_diff.rs | 2 +- src/source_file.rs | 2 +- src/spanned.rs | 2 +- src/stmt.rs | 2 +- src/string.rs | 2 +- src/test/configuration_snippet.rs | 4 ++-- src/test/mod.rs | 6 +++--- src/types.rs | 12 ++++++------ src/utils.rs | 4 ++-- src/vertical.rs | 2 +- src/visitor.rs | 12 ++++++------ 43 files changed, 117 insertions(+), 117 deletions(-) diff --git a/config_proc_macro/src/utils.rs b/config_proc_macro/src/utils.rs index f5cba87b07b..1f5b5cdb604 100644 --- a/config_proc_macro/src/utils.rs +++ b/config_proc_macro/src/utils.rs @@ -1,5 +1,5 @@ use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::{ToTokens, quote}; pub fn fold_quote(input: impl Iterator, f: F) -> TokenStream where diff --git a/src/attr.rs b/src/attr.rs index 802dfc0485c..ac57858ef7e 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,20 +1,20 @@ //! Format attributes and meta items. -use rustc_ast::ast; use rustc_ast::HasAttrs; -use rustc_span::{symbol::sym, Span}; +use rustc_ast::ast; +use rustc_span::{Span, symbol::sym}; use self::doc_comment::DocCommentFormatter; -use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; -use crate::config::lists::*; +use crate::comment::{CommentStyle, contains_comment, rewrite_doc_comment}; use crate::config::IndentStyle; +use crate::config::lists::*; use crate::expr::rewrite_literal; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; -use crate::types::{rewrite_path, PathContext}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{count_newlines, mk_sp}; mod doc_comment; diff --git a/src/bin/main.rs b/src/bin/main.rs index 3a0427d8372..0d593c6c416 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] -use anyhow::{format_err, Result}; +use anyhow::{Result, format_err}; use io::Error as IoError; use thiserror::Error; @@ -11,15 +11,15 @@ use tracing_subscriber::EnvFilter; use std::collections::HashMap; use std::env; use std::fs::File; -use std::io::{self, stdout, Read, Write}; +use std::io::{self, Read, Write, stdout}; use std::path::{Path, PathBuf}; use std::str::FromStr; use getopts::{Matches, Options}; use crate::rustfmt::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, - FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, + CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, + FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, load_config, }; const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; diff --git a/src/chains.rs b/src/chains.rs index a3f70055425..297eb268d30 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -59,9 +59,9 @@ use std::borrow::Cow; use std::cmp::min; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span}; +use rustc_span::{BytePos, Span, symbol}; -use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; +use crate::comment::{CharClasses, FullCodeCharKind, RichChar, rewrite_comment}; use crate::config::{IndentStyle, StyleEdition}; use crate::expr::rewrite_call; use crate::lists::extract_pre_comment; diff --git a/src/closures.rs b/src/closures.rs index a628e3da979..95d2bc5a00b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -3,17 +3,17 @@ use rustc_span::Span; use thin_vec::thin_vec; use crate::attr::get_attrs_from_stmt; -use crate::config::lists::*; use crate::config::StyleEdition; +use crate::config::lists::*; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; use crate::items::{span_hi_for_param, span_lo_for_param}; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; use crate::overflow::OverflowableItem; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::types::rewrite_bound_params; -use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; +use crate::utils::{NodeIdExt, last_line_width, left_most_sub_expr, stmt_expr}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. diff --git a/src/comment.rs b/src/comment.rs index 1e35395cfb3..b565712b326 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -2,13 +2,13 @@ use std::{borrow::Cow, iter}; -use itertools::{multipeek, MultiPeek}; +use itertools::{MultiPeek, multipeek}; use rustc_span::Span; use crate::config::Config; use crate::rewrite::{RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; -use crate::string::{rewrite_string, StringFormat}; +use crate::string::{StringFormat, rewrite_string}; use crate::utils::{ count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, trimmed_last_line_width, unicode_str_width, diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index bc5a28b7423..7f32765195d 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -7,7 +7,7 @@ use std::{cmp, fmt, iter, str}; use rustc_data_structures::sync::Lrc; use rustc_span::SourceFile; -use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, ser}; use serde_json as json; use thiserror::Error; diff --git a/src/config/options.rs b/src/config/options.rs index b9e79b9a7de..45496fd4e48 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,6 +1,6 @@ #![allow(unused_imports)] -use std::collections::{hash_set, HashSet}; +use std::collections::{HashSet, hash_set}; use std::fmt; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -11,10 +11,10 @@ use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use crate::config::Config; use crate::config::file_lines::FileLines; use crate::config::lists::*; use crate::config::macro_names::MacroSelectors; -use crate::config::Config; #[config_type] pub enum NewlineStyle { diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs index 9385ae59a06..c320c16bd1d 100644 --- a/src/emitter/checkstyle.rs +++ b/src/emitter/checkstyle.rs @@ -1,6 +1,6 @@ use self::xml::XmlEscaped; use super::*; -use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff}; mod xml; diff --git a/src/emitter/json.rs b/src/emitter/json.rs index 084f565804c..a99626f783d 100644 --- a/src/emitter/json.rs +++ b/src/emitter/json.rs @@ -1,5 +1,5 @@ use super::*; -use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff}; use serde::Serialize; use serde_json::to_string as to_json_string; diff --git a/src/emitter/modified_lines.rs b/src/emitter/modified_lines.rs index 81f0a31b974..0d5124bc33e 100644 --- a/src/emitter/modified_lines.rs +++ b/src/emitter/modified_lines.rs @@ -1,5 +1,5 @@ use super::*; -use crate::rustfmt_diff::{make_diff, ModifiedLines}; +use crate::rustfmt_diff::{ModifiedLines, make_diff}; #[derive(Debug, Default)] pub(crate) struct ModifiedLinesEmitter; diff --git a/src/expr.rs b/src/expr.rs index 8381e3ab083..5bd87d00b1d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3,32 +3,32 @@ use std::cmp::min; use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; -use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind}; +use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token}; use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; use crate::closures; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, - rewrite_missing_comment, CharClasses, FindUncommented, + CharClasses, FindUncommented, combine_strs_with_missing_comments, contains_comment, + recover_comment_removed, rewrite_comment, rewrite_missing_comment, }; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, StyleEdition}; use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, Separator, + ListFormatting, Separator, definitive_tactic, itemize_list, shape_for_tactic, + struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::matches::rewrite_match; use crate::overflow::{self, IntoOverflowableItem, OverflowableItem}; -use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_all_pairs, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt; -use crate::string::{rewrite_string, StringFormat}; -use crate::types::{rewrite_path, PathContext}; +use crate::string::{StringFormat, rewrite_string}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{ colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, diff --git a/src/formatting.rs b/src/formatting.rs index 7f442230b12..1315c9c43a1 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -16,7 +16,7 @@ use crate::parse::parser::{DirectoryOwnership, Parser, ParserError}; use crate::parse::session::ParseSess; use crate::utils::{contains_skip, count_newlines}; use crate::visitor::FmtVisitor; -use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +use crate::{ErrorKind, FormatReport, Input, Session, modules, source_file}; mod generated; mod newline_style; diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index b5a71588e9e..a487ede9284 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -16,7 +16,7 @@ use rustfmt_nightly as rustfmt; use tracing_subscriber::EnvFilter; use crate::rustfmt::{ - load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, Version, + CliOptions, FormatReportFormatterBuilder, Input, Session, Version, load_config, }; fn prune_files(files: Vec<&str>) -> Vec<&str> { diff --git a/src/imports.rs b/src/imports.rs index 868314354b0..b741dd9b5da 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,16 +8,16 @@ use itertools::Itertools; use rustc_ast::ast::{self, UseTreeKind}; use rustc_span::{ + BytePos, DUMMY_SP, Span, symbol::{self, sym}, - BytePos, Span, DUMMY_SP, }; use crate::comment::combine_strs_with_missing_comments; -use crate::config::lists::*; use crate::config::ImportGranularity; +use crate::config::lists::*; use crate::config::{Edition, IndentStyle, StyleEdition}; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; diff --git a/src/items.rs b/src/items.rs index 89fb9bda9df..ddcbfac1299 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1,28 +1,27 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; -use std::cmp::{max, min, Ordering}; +use std::cmp::{Ordering, max, min}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, DUMMY_SP, Span, symbol}; use crate::attr::filter_inline_attrs; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, is_last_comment_block, + FindUncommented, combine_strs_with_missing_comments, contains_comment, is_last_comment_block, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, - FindUncommented, }; use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, StyleEdition}; use crate::expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, - rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, rewrite_let_else_block, - RhsAssignKind, RhsTactics, + RhsAssignKind, RhsTactics, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_assign_rhs_with, rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, + rewrite_let_else_block, }; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; diff --git a/src/lib.rs b/src/lib.rs index 1f186b87767..7d707c341cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,8 +47,8 @@ use crate::shape::Indent; use crate::utils::indent_next_line; pub use crate::config::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, StyleEdition, Verbosity, Version, + CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, Range, + StyleEdition, Verbosity, Version, load_config, }; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; diff --git a/src/lists.rs b/src/lists.rs index f9e722130cd..415144a8abc 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -5,7 +5,7 @@ use std::iter::Peekable; use rustc_span::BytePos; -use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; +use crate::comment::{FindUncommented, find_comment_end, rewrite_comment}; use crate::config::lists::*; use crate::config::{Config, IndentStyle}; use crate::rewrite::{RewriteContext, RewriteError, RewriteResult}; diff --git a/src/macros.rs b/src/macros.rs index 5e537002324..2085ed35324 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -10,27 +10,27 @@ // and those with brackets will be formatted as array literals. use std::collections::HashMap; -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ + BytePos, DUMMY_SP, Span, Symbol, symbol::{self, kw}, - BytePos, Span, Symbol, DUMMY_SP, }; use crate::comment::{ - contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, + CharClasses, FindUncommented, FullCodeCharKind, LineClasses, contains_comment, }; -use crate::config::lists::*; use crate::config::StyleEdition; -use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind}; -use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::config::lists::*; +use crate::expr::{RhsAssignKind, rewrite_array, rewrite_assign_rhs}; +use crate::lists::{ListFormatting, itemize_list, write_list}; use crate::overflow; use crate::parse::macros::lazy_static::parse_lazy_static; -use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs}; +use crate::parse::macros::{ParsedMacroArgs, parse_expr, parse_macro_args}; use crate::rewrite::{ MacroErrorKind, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult, }; @@ -38,8 +38,8 @@ use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ - filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp, - remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt, + NodeIdExt, filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp, + remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, }; use crate::visitor::FmtVisitor; diff --git a/src/matches.rs b/src/matches.rs index 0a6fada5cb3..8de92eb5538 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,17 +2,17 @@ use std::iter::repeat; -use rustc_ast::{ast, ptr, MatchKind}; +use rustc_ast::{MatchKind, ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented}; +use crate::comment::{FindUncommented, combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, StyleEdition}; use crate::expr::{ - format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - ExprType, RhsTactics, + ExprType, RhsTactics, format_expr, is_empty_block, is_simple_block, is_unsafe_block, + prefer_next_line, rewrite_cond, }; -use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::lists::{ListFormatting, itemize_list, write_list}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 4d947328bf7..4ef54c90d46 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,9 +1,9 @@ use rustc_span::{BytePos, Pos, Span}; -use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; -use crate::config::file_lines::FileLines; +use crate::comment::{CodeCharKind, CommentCodeSlices, is_last_comment_block, rewrite_comment}; use crate::config::FileName; use crate::config::StyleEdition; +use crate::config::file_lines::FileLines; use crate::coverage::transform_missing_snippet; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; diff --git a/src/modules.rs b/src/modules.rs index 0590f28ee05..493b04f16c6 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -4,8 +4,8 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; -use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::Span; +use rustc_span::symbol::{self, Symbol, sym}; use thin_vec::ThinVec; use thiserror::Error; diff --git a/src/overflow.rs b/src/overflow.rs index dc4716a81af..8ce11897d26 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -9,21 +9,21 @@ use rustc_span::Span; use crate::closures; use crate::config::StyleEdition; -use crate::config::{lists::*, Config}; +use crate::config::{Config, lists::*}; use crate::expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, rewrite_cond, }; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::macros::MacroArg; -use crate::patterns::{can_be_overflowed_pat, TuplePatField}; +use crate::patterns::{TuplePatField, can_be_overflowed_pat}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; -use crate::types::{can_be_overflowed_type, SegmentParam}; +use crate::types::{SegmentParam, can_be_overflowed_type}; use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; /// A list of `format!`-like macros, that take a long format string and a list of arguments to diff --git a/src/pairs.rs b/src/pairs.rs index 5a7d9c8aaa4..9c51298416b 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -1,8 +1,8 @@ use rustc_ast::ast; use rustc_span::Span; -use crate::config::lists::*; use crate::config::IndentStyle; +use crate::config::lists::*; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::spanned::Spanned; diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs index 6373d0251f8..5ee083da539 100644 --- a/src/parse/macros/asm.rs +++ b/src/parse/macros/asm.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs}; +use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args}; use crate::rewrite::RewriteContext; diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index b91d203d531..ec771f96a3f 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -1,4 +1,4 @@ -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::ast; use rustc_ast::token::{Delimiter, TokenKind}; diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index 8d5f7f90958..7271e73db8d 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -1,11 +1,11 @@ use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; -use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::MACRO_ARGUMENTS; +use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{self, kw}; use rustc_span::Symbol; +use rustc_span::symbol::{self, kw}; use crate::macros::MacroArg; use crate::rewrite::RewriteContext; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 6051241309d..28b4c2b612f 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,4 +1,4 @@ -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; @@ -6,11 +6,11 @@ use rustc_ast::{ast, attr, ptr}; use rustc_errors::Diag; use rustc_parse::parser::Parser as RawParser; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; -use rustc_span::{sym, Span}; +use rustc_span::{Span, sym}; use thin_vec::ThinVec; -use crate::parse::session::ParseSess; use crate::Input; +use crate::parse::session::ParseSess; pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership; pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; diff --git a/src/parse/session.rs b/src/parse/session.rs index 05cf467167c..4160e02b8f8 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -2,13 +2,14 @@ use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; -use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter}; +use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ + BytePos, Span, source_map::{FilePathMapping, SourceMap}, - symbol, BytePos, Span, + symbol, }; use crate::config::file_lines::LineRange; diff --git a/src/patterns.rs b/src/patterns.rs index 9a4f6528ce8..6fe2d4a8520 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -2,22 +2,22 @@ use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd, use rustc_ast::ptr; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; -use crate::config::lists::*; +use crate::comment::{FindUncommented, combine_strs_with_missing_comments}; use crate::config::StyleEdition; +use crate::config::lists::*; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, shape_for_tactic, + struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; -use crate::types::{rewrite_path, PathContext}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident}; /// Returns `true` if the given pattern is "short". diff --git a/src/reorder.rs b/src/reorder.rs index 80d1c738994..8a31e0ac816 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -9,12 +9,12 @@ use std::cmp::Ordering; use rustc_ast::{ast, attr}; -use rustc_span::{symbol::sym, Span}; +use rustc_span::{Span, symbol::sym}; use crate::config::{Config, GroupImportsTactic}; -use crate::imports::{normalize_use_trees_with_granularity, UseSegmentKind, UseTree}; +use crate::imports::{UseSegmentKind, UseTree, normalize_use_trees_with_granularity}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; -use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; +use crate::lists::{ListFormatting, ListItem, itemize_list, write_list}; use crate::rewrite::{RewriteContext, RewriteErrorExt}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; diff --git a/src/rewrite.rs b/src/rewrite.rs index 8cefda1657f..83020709797 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -7,12 +7,12 @@ use rustc_ast::ptr; use rustc_span::Span; use thiserror::Error; +use crate::FormatReport; use crate::config::{Config, IndentStyle}; use crate::parse::session::ParseSess; use crate::shape::Shape; use crate::skip::SkipContext; use crate::visitor::SnippetProvider; -use crate::FormatReport; pub(crate) type RewriteResult = Result; pub(crate) trait Rewrite { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c9883452185..4624683fa05 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -282,7 +282,7 @@ where #[cfg(test)] mod test { use super::DiffLine::*; - use super::{make_diff, Mismatch}; + use super::{Mismatch, make_diff}; use super::{ModifiedChunk, ModifiedLines}; #[test] diff --git a/src/source_file.rs b/src/source_file.rs index 5eea8021b32..73f8ecb5529 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -2,10 +2,10 @@ use std::fs; use std::io::{self, Write}; use std::path::Path; +use crate::NewlineStyle; use crate::config::FileName; use crate::emitter::{self, Emitter}; use crate::parse::session::ParseSess; -use crate::NewlineStyle; #[cfg(test)] use crate::config::Config; diff --git a/src/spanned.rs b/src/spanned.rs index 030495e3ff8..b4424e476ee 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,7 +1,7 @@ use std::cmp::max; use rustc_ast::{ast, ptr}; -use rustc_span::{source_map, Span}; +use rustc_span::{Span, source_map}; use crate::macros::MacroArg; use crate::patterns::RangeOperand; diff --git a/src/stmt.rs b/src/stmt.rs index 4f31705295e..426bf89fc16 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -3,7 +3,7 @@ use rustc_span::Span; use crate::comment::recover_comment_removed; use crate::config::StyleEdition; -use crate::expr::{format_expr, is_simple_block, ExprType}; +use crate::expr::{ExprType, format_expr, is_simple_block}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; diff --git a/src/string.rs b/src/string.rs index cb666fff695..41fddeb517e 100644 --- a/src/string.rs +++ b/src/string.rs @@ -375,7 +375,7 @@ fn graphemes_width(graphemes: &[&str]) -> usize { #[cfg(test)] mod test { - use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat}; + use super::{SnippetState, StringFormat, break_string, detect_url, rewrite_string}; use crate::config::Config; use crate::shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs index e4a390ada66..5b93703de0b 100644 --- a/src/test/configuration_snippet.rs +++ b/src/test/configuration_snippet.rs @@ -4,9 +4,9 @@ use std::io::{BufRead, BufReader, Write}; use std::iter::Enumerate; use std::path::{Path, PathBuf}; -use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE}; +use super::{DIFF_CONTEXT_SIZE, print_mismatches, write_message}; use crate::config::{Config, EmitMode, Verbosity}; -use crate::rustfmt_diff::{make_diff, Mismatch}; +use crate::rustfmt_diff::{Mismatch, make_diff}; use crate::{Input, Session}; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; diff --git a/src/test/mod.rs b/src/test/mod.rs index 4d22f64f352..9dc05c846de 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,11 +11,11 @@ use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; use crate::formatting::{ReportedErrors, SourceFile}; -use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; +use crate::rustfmt_diff::{DiffLine, Mismatch, ModifiedChunk, OutputWriter, make_diff, print_diff}; use crate::source_file; use crate::{ - is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, - StyleEdition, Version, + Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, StyleEdition, Version, + is_nightly_channel, }; use rustfmt_config_proc_macro::nightly_only_test; diff --git a/src/types.rs b/src/types.rs index af57a5843db..384a69e23b2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,21 +2,21 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability, Term}; use rustc_ast::ptr; -use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use rustc_span::{BytePos, Pos, Span, symbol::kw}; use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, StyleEdition, TypeDensity}; use crate::expr::{ - format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, - RhsAssignKind, + ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, + rewrite_unary_prefix, }; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; diff --git a/src/utils.rs b/src/utils.rs index 57f2f177960..be21e89f760 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,10 +6,10 @@ use rustc_ast::ast::{ }; use rustc_ast::ptr; use rustc_ast_pretty::pprust; -use rustc_span::{sym, symbol, BytePos, LocalExpnId, Span, Symbol, SyntaxContext}; +use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; -use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; +use crate::comment::{CharClasses, FullCodeCharKind, LineClasses, filter_normal_code}; use crate::config::{Config, StyleEdition}; use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; diff --git a/src/vertical.rs b/src/vertical.rs index 80c46da4620..1ec239c3821 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -11,7 +11,7 @@ use crate::config::lists::*; use crate::expr::rewrite_field; use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::rewrite::{Rewrite, RewriteContext, RewriteResult}; use crate::shape::{Indent, Shape}; diff --git a/src/visitor.rs b/src/visitor.rs index 9859100a038..afb54c8e2bc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -3,22 +3,22 @@ use std::rc::Rc; use rustc_ast::{ast, token::Delimiter, visit}; use rustc_data_structures::sync::Lrc; -use rustc_span::{symbol, BytePos, Pos, Span}; +use rustc_span::{BytePos, Pos, Span, symbol}; use crate::attr::*; -use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::comment::{CodeCharKind, CommentCodeSlices, contains_comment, rewrite_comment}; use crate::config::{BraceStyle, Config, MacroSelector, StyleEdition}; use crate::coverage::transform_missing_snippet; use crate::items::{ - format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, - rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, + FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, format_impl, format_trait, + format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, rewrite_type_alias, }; -use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::macros::{MacroPosition, macro_style, rewrite_macro, rewrite_macro_def}; use crate::modules::Module; use crate::parse::session::ParseSess; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; -use crate::skip::{is_skip_attr, SkipContext}; +use crate::skip::{SkipContext, is_skip_attr}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; From 06e16449d28bf4ff2c56e49b158b4f1cead2b993 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 16 Aug 2024 15:27:57 -0400 Subject: [PATCH 24/30] Add test cases for issue 4381 This was one of the original issues filed against rustfmt that discussed using a natural sort order instead of a lexicographical order. At the time it was closed, but now that we're supporting version-sorting in `style_edition=2024` I thought it would be good to add a test case. --- tests/source/issue-4381/style_edition_2015.rs | 3 +++ tests/target/issue-4381/style_edition_2015.rs | 3 +++ tests/target/issue-4381/style_edition_2024.rs | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 tests/source/issue-4381/style_edition_2015.rs create mode 100644 tests/target/issue-4381/style_edition_2015.rs create mode 100644 tests/target/issue-4381/style_edition_2024.rs diff --git a/tests/source/issue-4381/style_edition_2015.rs b/tests/source/issue-4381/style_edition_2015.rs new file mode 100644 index 00000000000..bb4c9feae1d --- /dev/null +++ b/tests/source/issue-4381/style_edition_2015.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2015 + +use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64}; diff --git a/tests/target/issue-4381/style_edition_2015.rs b/tests/target/issue-4381/style_edition_2015.rs new file mode 100644 index 00000000000..1fc1613083e --- /dev/null +++ b/tests/target/issue-4381/style_edition_2015.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2015 + +use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8}; diff --git a/tests/target/issue-4381/style_edition_2024.rs b/tests/target/issue-4381/style_edition_2024.rs new file mode 100644 index 00000000000..df85636ad57 --- /dev/null +++ b/tests/target/issue-4381/style_edition_2024.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2024 + +use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64}; From 1a70f40d7fa8cafa37037652ba6ea8b7d9938b7a Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 13:13:14 +0200 Subject: [PATCH 25/30] Avoid allocation in `ChainItemKind::is_tup_field_access` --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains.rs b/src/chains.rs index 297eb268d30..693aaef9979 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -209,7 +209,7 @@ impl ChainItemKind { fn is_tup_field_access(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Field(_, ref field) => { - field.name.to_string().chars().all(|c| c.is_digit(10)) + field.name.as_str().chars().all(|c| c.is_digit(10)) } _ => false, } From 263937090528baf51d703a364a91a2b2a647e848 Mon Sep 17 00:00:00 2001 From: ding-young Date: Thu, 29 Aug 2024 01:25:09 +0900 Subject: [PATCH 26/30] impl rewrite_result for TraitAliasBounds, WherePredicate --- src/items.rs | 67 ++++++++++++++++++++++++++++++---------------------- src/types.rs | 19 +++++++++------ 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/items.rs b/src/items.rs index ddcbfac1299..39fb358401e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -840,7 +840,8 @@ pub(crate) fn format_impl( where_span_end, self_ty.span.hi(), option, - )?; + ) + .ok()?; // If there is no where-clause, we may have missing comments between the trait name and // the opening brace. @@ -1231,7 +1232,8 @@ pub(crate) fn format_trait( None, pos_before_where, option, - )?; + ) + .ok()?; // If the where-clause cannot fit on the same line, // put the where-clause on a new line if !where_clause_str.contains('\n') @@ -1336,7 +1338,11 @@ pub(crate) struct TraitAliasBounds<'a> { impl<'a> Rewrite for TraitAliasBounds<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let generic_bounds_str = self.generic_bounds.rewrite(context, shape)?; + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + let generic_bounds_str = self.generic_bounds.rewrite_result(context, shape)?; let mut option = WhereClauseOption::new(true, WhereClauseSpace::None); option.allow_single_line(); @@ -1365,7 +1371,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { shape.indent.to_string_with_newline(context.config) }; - Some(format!("{generic_bounds_str}{space}{where_str}")) + Ok(format!("{generic_bounds_str}{space}{where_str}")) } } @@ -1623,7 +1629,8 @@ fn format_tuple_struct( None, body_hi, option, - )? + ) + .ok()? } None => "".to_owned(), }; @@ -1792,7 +1799,8 @@ fn rewrite_ty( None, generics.span.hi(), option, - )?; + ) + .ok()?; result.push_str(&where_clause_str); if let Some(ty) = rhs { @@ -2663,7 +2671,8 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - )?; + ) + .ok()?; // If there are neither where-clause nor return type, we may be missing comments between // params and `{`. if where_clause_str.is_empty() { @@ -2939,7 +2948,7 @@ fn rewrite_where_clause_rfc_style( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option { +) -> RewriteResult { let (where_keyword, allow_single_line) = rewrite_where_keyword( context, predicates, @@ -2953,8 +2962,9 @@ fn rewrite_where_clause_rfc_style( let clause_shape = shape .block() .with_max_width(context.config) - .block_left(context.config.tab_spaces())? - .sub_width(1)?; + .block_left(context.config.tab_spaces()) + .and_then(|s| s.sub_width(1)) + .max_width_error(shape.width, where_span)?; let force_single_line = context.config.where_single_line() && predicates.len() == 1 && !where_clause_option.veto_single_line; @@ -2979,7 +2989,7 @@ fn rewrite_where_clause_rfc_style( clause_shape.indent.to_string_with_newline(context.config) }; - Some(format!("{where_keyword}{clause_sep}{preds_str}")) + Ok(format!("{where_keyword}{clause_sep}{preds_str}")) } /// Rewrite `where` and comment around it. @@ -2990,12 +3000,13 @@ fn rewrite_where_keyword( shape: Shape, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option<(String, bool)> { +) -> Result<(String, bool), RewriteError> { let block_shape = shape.block().with_max_width(context.config); // 1 = `,` let clause_shape = block_shape - .block_left(context.config.tab_spaces())? - .sub_width(1)?; + .block_left(context.config.tab_spaces()) + .and_then(|s| s.sub_width(1)) + .max_width_error(block_shape.width, where_span)?; let comment_separator = |comment: &str, shape: Shape| { if comment.is_empty() { @@ -3026,7 +3037,7 @@ fn rewrite_where_keyword( && comment_before.is_empty() && comment_after.is_empty(); - Some((result, allow_single_line)) + Ok((result, allow_single_line)) } /// Rewrite bounds on a where clause. @@ -3038,7 +3049,7 @@ fn rewrite_bounds_on_where_clause( span_end: Option, where_clause_option: WhereClauseOption, force_single_line: bool, -) -> Option { +) -> RewriteResult { let span_start = predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. @@ -3077,7 +3088,7 @@ fn rewrite_bounds_on_where_clause( .tactic(shape_tactic) .trailing_separator(comma_tactic) .preserve_newline(preserve_newline); - write_list(&items.collect::>(), &fmt).ok() + write_list(&items.collect::>(), &fmt) } fn rewrite_where_clause( @@ -3091,9 +3102,9 @@ fn rewrite_where_clause( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option { +) -> RewriteResult { if predicates.is_empty() { - return Some(String::new()); + return Ok(String::new()); } if context.config.indent_style() == IndentStyle::Block { @@ -3153,7 +3164,7 @@ fn rewrite_where_clause( .trailing_separator(comma_tactic) .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) .preserve_newline(true); - let preds_str = write_list(&item_vec, &fmt).ok()?; + let preds_str = write_list(&item_vec, &fmt)?; let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two @@ -3171,13 +3182,13 @@ fn rewrite_where_clause( || preds_str.contains('\n') || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { - Some(format!( + Ok(format!( "\n{}where {}", (shape.indent + extra_indent).to_string(context.config), preds_str )) } else { - Some(format!(" where {preds_str}")) + Ok(format!(" where {preds_str}")) } } @@ -3198,15 +3209,14 @@ fn rewrite_comments_before_after_where( span_before_where: Span, span_after_where: Span, shape: Shape, -) -> Option<(String, String)> { - let before_comment = rewrite_missing_comment(span_before_where, shape, context).ok()?; +) -> Result<(String, String), RewriteError> { + let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; let after_comment = rewrite_missing_comment( span_after_where, shape.block_indent(context.config.tab_spaces()), context, - ) - .ok()?; - Some((before_comment, after_comment)) + )?; + Ok((before_comment, after_comment)) } fn format_header( @@ -3288,7 +3298,8 @@ fn format_generics( Some(span.hi()), span_end_before_where, option, - )?; + ) + .ok()?; result.push_str(&where_clause_str); ( brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine, diff --git a/src/types.rs b/src/types.rs index 384a69e23b2..5477942f82e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -457,6 +457,10 @@ fn get_tactics(item_vec: &[ListItem], output: &str, shape: Shape) -> DefinitiveL impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { // FIXME: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { @@ -465,7 +469,7 @@ impl Rewrite for ast::WherePredicate { ref bounds, .. }) => { - let type_str = bounded_ty.rewrite(context, shape)?; + let type_str = bounded_ty.rewrite_result(context, shape)?; let colon = type_bound_colon(context).trim_end(); let lhs = if let Some(binder_str) = rewrite_bound_params(context, shape, bound_generic_params) @@ -475,25 +479,26 @@ impl Rewrite for ast::WherePredicate { format!("{type_str}{colon}") }; - rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape).ok()? + rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, span, - }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape).ok()?, + }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape)?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape) - .ok()? + let lhs_ty_str = lhs_ty + .rewrite_result(context, shape) + .map(|lhs| lhs + " =")?; + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? } }; - Some(result) + Ok(result) } } From b40c3cc3888229080dff8a59e607cffbcfed82b7 Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 1 Sep 2024 15:44:17 +0900 Subject: [PATCH 27/30] impl rewrite_result for ForeignItem --- src/items.rs | 118 +++++++++++++++++++++++++++---------------------- src/visitor.rs | 16 ++++--- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/src/items.rs b/src/items.rs index 39fb358401e..1f25827e919 100644 --- a/src/items.rs +++ b/src/items.rs @@ -433,7 +433,7 @@ impl<'a> FmtVisitor<'a> { let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause); let (result, _, force_newline_brace) = - rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?; + rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style).ok()?; // 2 = ` {` if self.config.brace_style() == BraceStyle::AlwaysNextLine @@ -454,7 +454,7 @@ impl<'a> FmtVisitor<'a> { vis: &ast::Visibility, generics: &ast::Generics, span: Span, - ) -> Option { + ) -> RewriteResult { // Drop semicolon or it will be interpreted as comment. let span = mk_sp(span.lo(), span.hi() - BytePos(1)); let context = self.get_context(); @@ -476,7 +476,7 @@ impl<'a> FmtVisitor<'a> { // Re-attach semicolon result.push(';'); - Some(result) + Ok(result) } pub(crate) fn single_line_fn( @@ -977,7 +977,7 @@ fn format_impl_ref_and_type( 0, )? }; - let generics_str = rewrite_generics(context, "impl", generics, shape)?; + let generics_str = rewrite_generics(context, "impl", generics, shape).ok()?; result.push_str(&generics_str); result.push_str(format_constness_right(constness)); @@ -1185,7 +1185,7 @@ pub(crate) fn format_trait( let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = - rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?; + rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. @@ -1386,7 +1386,7 @@ pub(crate) fn format_trait_alias( let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; - let generics_str = rewrite_generics(context, alias, generics, g_shape)?; + 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} ="); // 1 = ";" @@ -1613,7 +1613,7 @@ fn format_tuple_struct( Some(generics) => { let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); - let generics_str = rewrite_generics(context, "", generics, shape)?; + let generics_str = rewrite_generics(context, "", generics, shape).ok()?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1700,7 +1700,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( indent: Indent, visitor_kind: &ItemVisitorKind<'b>, span: Span, -) -> Option { +) -> RewriteResult { use ItemVisitorKind::*; let ast::TyAlias { @@ -1738,8 +1738,8 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( rewrite_ty(rw_info, Some(bounds), ty_opt, vis) }?; match defaultness { - ast::Defaultness::Default(..) => Some(format!("default {result}")), - _ => Some(result), + ast::Defaultness::Default(..) => Ok(format!("default {result}")), + _ => Ok(result), } } } @@ -1750,7 +1750,7 @@ fn rewrite_ty( generic_bounds_opt: Option<&ast::GenericBounds>, rhs: Option<&R>, vis: &ast::Visibility, -) -> Option { +) -> RewriteResult { let mut result = String::with_capacity(128); let TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span) = *rw_info; let (before_where_predicates, after_where_predicates) = generics @@ -1758,7 +1758,7 @@ fn rewrite_ty( .predicates .split_at(where_clauses.split); if !after_where_predicates.is_empty() { - return None; + return Err(RewriteError::Unknown); } result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); @@ -1767,9 +1767,11 @@ fn rewrite_ty( result.push_str(ident_str) } else { // 2 = `= ` - let g_shape = Shape::indented(indent, context.config) - .offset_left(result.len())? - .sub_width(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)?; let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?; result.push_str(&generics_str); } @@ -1777,8 +1779,13 @@ fn rewrite_ty( if let Some(bounds) = generic_bounds_opt { if !bounds.is_empty() { // 2 = `: ` - let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; - let type_bounds = bounds.rewrite(context, shape).map(|s| format!(": {}", s))?; + let shape = Shape::indented(indent, context.config); + let shape = shape + .offset_left(result.len() + 2) + .max_width_error(shape.width, span)?; + let type_bounds = bounds + .rewrite_result(context, shape) + .map(|s| format!(": {}", s))?; result.push_str(&type_bounds); } } @@ -1799,8 +1806,7 @@ fn rewrite_ty( None, generics.span.hi(), option, - ) - .ok()?; + )?; result.push_str(&where_clause_str); if let Some(ty) = rhs { @@ -1820,13 +1826,20 @@ fn rewrite_ty( let lhs = match comment_span { Some(comment_span) - if contains_comment(context.snippet_provider.span_to_snippet(comment_span)?) => + if contains_comment( + context + .snippet_provider + .span_to_snippet(comment_span) + .unknown_error()?, + ) => { let comment_shape = if has_where { Shape::indented(indent, context.config) } else { - Shape::indented(indent, context.config) - .block_left(context.config.tab_spaces())? + let shape = Shape::indented(indent, context.config); + shape + .block_left(context.config.tab_spaces()) + .max_width_error(shape.width, span)? }; combine_strs_with_missing_comments( @@ -1836,19 +1849,17 @@ fn rewrite_ty( comment_span, comment_shape, true, - ) - .ok()? + )? } _ => format!("{result}="), }; // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape) - .map(|s| s + ";") - .ok() + let shape = Shape::indented(indent, context.config); + let shape = shape.sub_width(1).max_width_error(shape.width, span)?; + rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";") } else { - Some(format!("{result};")) + Ok(format!("{result};")) } } @@ -2392,7 +2403,7 @@ fn rewrite_fn_base( fn_sig: &FnSig<'_>, span: Span, fn_brace_style: FnBraceStyle, -) -> Option<(String, bool, bool)> { +) -> Result<(String, bool, bool), RewriteError> { let mut force_new_line_for_brace = false; let where_clause = &fn_sig.generics.where_clause; @@ -2436,7 +2447,7 @@ fn rewrite_fn_base( // return type later anyway. let ret_str = fd .output - .rewrite(context, Shape::indented(indent, context.config))?; + .rewrite_result(context, Shape::indented(indent, context.config))?; let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -2449,7 +2460,7 @@ fn rewrite_fn_base( ret_str_len, fn_brace_style, multi_line_ret_str, - )?; + ); debug!( "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, param_indent: {:?}", @@ -2611,7 +2622,7 @@ fn rewrite_fn_base( if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = fd.output.rewrite(context, ret_shape)?; + let ret_str = fd.output.rewrite_result(context, ret_shape)?; result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -2671,8 +2682,7 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - ) - .ok()?; + )?; // If there are neither where-clause nor return type, we may be missing comments between // params and `{`. if where_clause_str.is_empty() { @@ -2699,7 +2709,7 @@ fn rewrite_fn_base( force_new_line_for_brace |= ends_with_comment; force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line() && !where_clause_str.is_empty(); - Some((result, ends_with_comment, force_new_line_for_brace)) + Ok((result, ends_with_comment, force_new_line_for_brace)) } /// Kind of spaces to put before `where`. @@ -2770,7 +2780,7 @@ fn rewrite_params( param_indent: Indent, span: Span, variadic: bool, -) -> Option { +) -> RewriteResult { if params.is_empty() { let comment = context .snippet(mk_sp( @@ -2779,7 +2789,7 @@ fn rewrite_params( span.hi() - BytePos(1), )) .trim(); - return Some(comment.to_owned()); + return Ok(comment.to_owned()); } let param_items: Vec<_> = itemize_list( context.snippet_provider, @@ -2829,7 +2839,7 @@ fn rewrite_params( .trailing_separator(trailing_separator) .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) .preserve_newline(true); - write_list(¶m_items, &fmt).ok() + write_list(¶m_items, &fmt) } fn compute_budgets_for_params( @@ -2839,7 +2849,7 @@ fn compute_budgets_for_params( ret_str_len: usize, fn_brace_style: FnBraceStyle, force_vertical_layout: bool, -) -> Option<(usize, usize, Indent)> { +) -> (usize, usize, Indent) { debug!( "compute_budgets_for_params {} {:?}, {}, {:?}", result.len(), @@ -2876,7 +2886,7 @@ fn compute_budgets_for_params( } }; - return Some((one_line_budget, multi_line_budget, indent)); + return (one_line_budget, multi_line_budget, indent); } } @@ -2888,7 +2898,7 @@ fn compute_budgets_for_params( // Account for `)` and possibly ` {`. IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, }; - Some((0, context.budget(used_space), new_indent)) + (0, context.budget(used_space), new_indent) } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> FnBraceStyle { @@ -2913,16 +2923,16 @@ fn rewrite_generics( ident: &str, generics: &ast::Generics, shape: Shape, -) -> Option { +) -> RewriteResult { // FIXME: convert bounds to where-clauses where they get too big or if // there is a where-clause at all. if generics.params.is_empty() { - return Some(ident.to_owned()); + return Ok(ident.to_owned()); } let params = generics.params.iter(); - overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span).ok() + overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { @@ -3272,7 +3282,7 @@ fn format_generics( used_width: usize, ) -> Option { let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, "", generics, shape)?; + let mut result = rewrite_generics(context, "", generics, shape).ok()?; // If the generics are not parameterized then generics.span.hi() == 0, // so we use span.lo(), which is the position after `struct Foo`. @@ -3366,7 +3376,11 @@ fn format_generics( impl Rewrite for ast::ForeignItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + let attrs_str = self.attrs.rewrite_result(context, shape)?; // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); @@ -3399,7 +3413,7 @@ impl Rewrite for ast::ForeignItem { defaultness, Some(&inner_attrs), ); - Some(visitor.buffer.to_owned()) + Ok(visitor.buffer.to_owned()) } else { rewrite_fn_base( context, @@ -3431,17 +3445,18 @@ impl Rewrite for ast::ForeignItem { prefix, &static_foreign_item.ty, &RhsAssignKind::Ty, - shape.sub_width(1)?, + shape + .sub_width(1) + .max_width_error(shape.width, static_foreign_item.ty.span)?, ) .map(|s| s + ";") - .ok() } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item).ok() + rewrite_macro(mac, None, context, shape, MacroPosition::Item) } }?; @@ -3458,7 +3473,6 @@ impl Rewrite for ast::ForeignItem { shape, false, ) - .ok() } } diff --git a/src/visitor.rs b/src/visitor.rs index afb54c8e2bc..99416f85503 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -561,9 +561,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) } else { let indent = self.block_indent; - let rewrite = self.rewrite_required_fn( - indent, item.ident, sig, &item.vis, generics, item.span, - ); + let rewrite = self + .rewrite_required_fn( + indent, item.ident, sig, &item.vis, generics, item.span, + ) + .ok(); self.push_rewrite(item.span, rewrite); } } @@ -610,7 +612,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.block_indent, visitor_kind, span, - ); + ) + .ok(); self.push_rewrite(span, rewrite); } @@ -656,8 +659,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } else { let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span); + let rewrite = self + .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span) + .ok(); self.push_rewrite(ai.span, rewrite); } } From d720a7ef77f76670d2275952e81e9ae6b2556638 Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 25 Aug 2024 15:42:46 +0900 Subject: [PATCH 28/30] impl rewrite_result for ast::Expr --- src/expr.rs | 174 +++++++++++++++++++++++-------------------------- src/matches.rs | 23 ++++--- src/stmt.rs | 4 +- src/types.rs | 4 ++ src/utils.rs | 8 --- 5 files changed, 98 insertions(+), 115 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 5bd87d00b1d..32bfc8b4722 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -39,6 +39,10 @@ use crate::visitor::FmtVisitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { format_expr(self, ExprType::SubExpression, context, shape) } } @@ -58,14 +62,14 @@ pub(crate) fn format_expr( expr_type: ExprType, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - skip_out_of_file_lines_range!(context, expr.span); +) -> RewriteResult { + skip_out_of_file_lines_range_err!(context, expr.span); if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span()).to_owned()); + return Ok(context.snippet(expr.span()).to_owned()); } let shape = if expr_type == ExprType::Statement && semicolon_for_expr(context, expr) { - shape.sub_width(1)? + shape.sub_width(1).max_width_error(shape.width, expr.span)? } else { shape }; @@ -79,41 +83,38 @@ pub(crate) fn format_expr( shape, choose_separator_tactic(context, expr.span), None, - ) - .ok(), + ), ast::ExprKind::Lit(token_lit) => { if let Ok(expr_rw) = rewrite_literal(context, token_lit, expr.span, shape) { - Some(expr_rw) + Ok(expr_rw) } else { if let LitKind::StrRaw(_) = token_lit.kind { - Some(context.snippet(expr.span).trim().into()) + Ok(context.snippet(expr.span).trim().into()) } else { - None + Err(RewriteError::Unknown) } } } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - let callee_str = callee.rewrite(context, shape)?; - rewrite_call(context, &callee_str, args, inner_span, shape).ok() + let callee_str = callee.rewrite_result(context, shape)?; + rewrite_call(context, &callee_str, args, inner_span, shape) } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span).ok(), + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), ast::ExprKind::Binary(op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_all_pairs(expr, shape, context) - .or_else(|_| { - rewrite_pair( - &**lhs, - &**rhs, - PairParts::infix(&format!(" {} ", context.snippet(op.span))), - context, - shape, - context.config.binop_separator(), - ) - }) - .ok() + rewrite_all_pairs(expr, shape, context).or_else(|_| { + rewrite_pair( + &**lhs, + &**rhs, + PairParts::infix(&format!(" {} ", context.snippet(op.span))), + context, + shape, + context.config.binop_separator(), + ) + }) } - ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape).ok(), + ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref struct_expr) => { let ast::StructExpr { qself, @@ -131,19 +132,17 @@ 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).ok() - } - ast::ExprKind::Let(ref pat, ref expr, _span, _) => { - rewrite_let(context, shape, pat, expr).ok() + rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } + ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr), ast::ExprKind::If(..) | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) - .and_then(|control_flow| control_flow.rewrite(context, shape)), + .unknown_error() + .and_then(|control_flow| control_flow.rewrite_result(context, shape)), ast::ExprKind::ConstBlock(ref anon_const) => { let rewrite = match anon_const.value.kind { ast::ExprKind::Block(ref block, opt_label) => { @@ -151,24 +150,24 @@ pub(crate) fn format_expr( // not the `ast::Block` node we're about to rewrite. To prevent dropping inner // attributes call `rewrite_block` directly. // See https://github.com/rust-lang/rustfmt/issues/6158 - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok()? + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)? } - _ => anon_const.rewrite(context, shape)?, + _ => anon_const.rewrite_result(context, shape)?, }; - Some(format!("const {}", rewrite)) + Ok(format!("const {}", rewrite)) } ast::ExprKind::Block(ref block, opt_label) => { match expr_type { ExprType::Statement => { if is_unsafe_block(block) { - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok() - } else if let rw @ Some(_) = + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) + } else if let Some(rw) = rewrite_empty_block(context, block, Some(&expr.attrs), opt_label, "", shape) { // Rewrite block without trying to put it in a single line. - rw + Ok(rw) } else { - let prefix = block_prefix(context, block, shape).ok()?; + let prefix = block_prefix(context, block, shape)?; rewrite_block_with_visitor( context, @@ -179,32 +178,31 @@ pub(crate) fn format_expr( shape, true, ) - .ok() } } ExprType::SubExpression => { - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok() + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) } } } ast::ExprKind::Match(ref cond, ref arms, kind) => { - rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind).ok() + 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).ok() + rewrite_path(context, PathContext::Expr, qself, path, shape) } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { - rewrite_assignment(context, lhs, rhs, None, shape).ok() + rewrite_assignment(context, lhs, rhs, None, shape) } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape).ok() + rewrite_assignment(context, lhs, rhs, Some(op), shape) } ast::ExprKind::Continue(ref opt_label) => { let id_str = match *opt_label { Some(label) => format!(" {}", label.ident), None => String::new(), }; - Some(format!("continue{id_str}")) + Ok(format!("continue{id_str}")) } ast::ExprKind::Break(ref opt_label, ref opt_expr) => { let id_str = match *opt_label { @@ -213,16 +211,16 @@ pub(crate) fn format_expr( }; if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape).ok() + rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape) } else { - Some(format!("break{id_str}")) + Ok(format!("break{id_str}")) } } ast::ExprKind::Yield(ref opt_expr) => { if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape).ok() + rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { - Some("yield".to_string()) + Ok("yield".to_string()) } } ast::ExprKind::Closure(ref cl) => closures::rewrite_closure( @@ -236,37 +234,32 @@ pub(crate) fn format_expr( expr.span, context, shape, - ) - .ok(), + ), ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape).ok(), + | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|_| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - .max_width_error(shape.width, expr.span) - }) - .ok() + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + .max_width_error(shape.width, expr.span) + }) } - ast::ExprKind::Ret(None) => Some("return".to_owned()), + ast::ExprKind::Ret(None) => Ok("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape).ok() - } - ast::ExprKind::Become(ref expr) => { - rewrite_unary_prefix(context, "become ", &**expr, shape).ok() + rewrite_unary_prefix(context, "return ", &**expr, shape) } - ast::ExprKind::Yeet(None) => Some("do yeet".to_owned()), + ast::ExprKind::Become(ref expr) => rewrite_unary_prefix(context, "become ", &**expr, shape), + ast::ExprKind::Yeet(None) => Ok("do yeet".to_owned()), ast::ExprKind::Yeet(Some(ref expr)) => { - rewrite_unary_prefix(context, "do yeet ", &**expr, shape).ok() + rewrite_unary_prefix(context, "do yeet ", &**expr, shape) } ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => { - rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape).ok() + rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape) } ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, @@ -275,10 +268,9 @@ pub(crate) fn format_expr( context, shape, SeparatorPlace::Front, - ) - .ok(), + ), ast::ExprKind::Index(ref expr, ref index, _) => { - rewrite_index(&**expr, &**index, context, shape).ok() + rewrite_index(&**expr, &**index, context, shape) } ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( &**expr, @@ -287,8 +279,7 @@ pub(crate) fn format_expr( context, shape, SeparatorPlace::Back, - ) - .ok(), + ), ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { ast::RangeLimits::HalfOpen => "..", @@ -341,7 +332,6 @@ pub(crate) fn format_expr( shape, context.config.binop_separator(), ) - .ok() } (None, Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { @@ -349,7 +339,7 @@ pub(crate) fn format_expr( } else { default_sp_delim(None, Some(rhs)) }; - rewrite_unary_prefix(context, &sp_delim, &*rhs, shape).ok() + rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) } (Some(lhs), None) => { let sp_delim = if context.config.spaces_around_ranges() { @@ -357,25 +347,25 @@ pub(crate) fn format_expr( } else { default_sp_delim(Some(lhs), None) }; - rewrite_unary_suffix(context, &sp_delim, &*lhs, shape).ok() + rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } - (None, None) => Some(delim.to_owned()), + (None, None) => Ok(delim.to_owned()), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 - ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + ast::ExprKind::InlineAsm(..) => Ok(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Ok(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) { - rw.ok() + rw } else { // 9 = `try ` let budget = shape.width.saturating_sub(9); - Some(format!( + Ok(format!( "{}{}", "try ", rewrite_block( @@ -384,8 +374,7 @@ pub(crate) fn format_expr( None, context, Shape::legacy(budget, shape.indent) - ) - .ok()? + )? )) } } @@ -403,11 +392,11 @@ pub(crate) fn format_expr( None, shape, ) { - rw.ok() + rw } else { // 6 = `async ` let budget = shape.width.saturating_sub(6); - Some(format!( + Ok(format!( "{kind} {mover}{}", rewrite_block( block, @@ -415,12 +404,11 @@ pub(crate) fn format_expr( None, context, Shape::legacy(budget, shape.indent) - ) - .ok()? + )? )) } } - ast::ExprKind::Underscore => Some("_".to_owned()), + ast::ExprKind::Underscore => Ok("_".to_owned()), ast::ExprKind::FormatArgs(..) | ast::ExprKind::Type(..) | ast::ExprKind::IncludedBytes(..) @@ -429,22 +417,21 @@ pub(crate) fn format_expr( // rustfmt tries to parse macro arguments when formatting macros, so it's not totally // impossible for rustfmt to come across one of these nodes when formatting a file. // Also, rustfmt might get passed the output from `-Zunpretty=expanded`. - None + Err(RewriteError::Unknown) } - ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None, + ast::ExprKind::Err(_) | ast::ExprKind::Dummy => Err(RewriteError::Unknown), }; expr_rw .map(|expr_str| recover_comment_removed(expr_str, expr.span, context)) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); - let attrs_str = attrs.rewrite(context, shape)?; + let attrs_str = attrs.rewrite_result(context, shape)?; let span = mk_sp( attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), expr.span.lo(), ); combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) - .ok() }) } @@ -1184,7 +1171,6 @@ impl<'a> Rewrite for ControlFlow<'a> { ..shape }; format_expr(else_block, ExprType::Statement, context, else_shape) - .unknown_error() } }; diff --git a/src/matches.rs b/src/matches.rs index 8de92eb5538..ee631fa1b47 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -516,7 +516,7 @@ fn rewrite_match_body( .offset_left(extra_offset(pats_str, shape) + 4) .and_then(|shape| shape.sub_width(comma.len())); let orig_body = if forbid_same_line || !arrow_comment.is_empty() { - None + Err(RewriteError::Unknown) } else if let Some(body_shape) = orig_body_shape { let rewrite = nop_block_collapse( format_expr(body, ExprType::Statement, context, body_shape), @@ -524,7 +524,7 @@ fn rewrite_match_body( ); match rewrite { - Some(ref body_str) + Ok(ref body_str) if is_block || (!body_str.contains('\n') && unicode_str_width(body_str) <= body_shape.width) => @@ -534,7 +534,7 @@ fn rewrite_match_body( _ => rewrite, } } else { - None + Err(RewriteError::Unknown) }; let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); @@ -545,20 +545,23 @@ fn rewrite_match_body( next_line_body_shape.width, ); match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) + (Ok(ref orig_str), Ok(ref next_line_str)) if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { combine_next_line_body(next_line_str) } - (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + (Ok(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { combine_orig_body(orig_str) } - (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + (Ok(ref orig_str), Ok(ref next_line_str)) if orig_str.contains('\n') => { combine_next_line_body(next_line_str) } - (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), - (None, None) => Err(RewriteError::Unknown), - (Some(ref orig_str), _) => combine_orig_body(orig_str), + (Err(_), Ok(ref next_line_str)) => combine_next_line_body(next_line_str), + // When both orig_body and next_line_body result in errors, we currently propagate the + // error from the second attempt since it is more generous with width constraints. + // This decision is somewhat arbitrary and is open to change. + (Err(_), Err(next_line_err)) => Err(next_line_err), + (Ok(ref orig_str), _) => combine_orig_body(orig_str), } } @@ -605,7 +608,7 @@ fn rewrite_guard( } } -fn nop_block_collapse(block_str: Option, budget: usize) -> Option { +fn nop_block_collapse(block_str: RewriteResult, budget: usize) -> RewriteResult { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { if block_str.starts_with('{') diff --git a/src/stmt.rs b/src/stmt.rs index 426bf89fc16..2788159018d 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -135,9 +135,7 @@ fn format_stmt( let shape = shape .sub_width(suffix.len()) .max_width_error(shape.width, ex.span())?; - format_expr(ex, expr_type, context, shape) - .map(|s| s + suffix) - .unknown_error() + format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => { Err(RewriteError::Unknown) diff --git a/src/types.rs b/src/types.rs index 5477942f82e..1aa3f60f868 100644 --- a/src/types.rs +++ b/src/types.rs @@ -584,6 +584,10 @@ fn rewrite_bounded_lifetime( impl Rewrite for ast::AnonConst { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { format_expr(&self.value, ExprType::SubExpression, context, shape) } } diff --git a/src/utils.rs b/src/utils.rs index be21e89f760..d1cfc6acc49 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -367,14 +367,6 @@ macro_rules! out_of_file_lines_range { }; } -macro_rules! skip_out_of_file_lines_range { - ($self:ident, $span:expr) => { - if out_of_file_lines_range!($self, $span) { - return None; - } - }; -} - macro_rules! skip_out_of_file_lines_range_err { ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) { From 91b2c17ffb0f0e34e586fabff47d915c5caeed95 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Mon, 9 Sep 2024 23:23:15 +0800 Subject: [PATCH 29/30] Add missing backtick in comment (#6317) Signed-off-by: cuishuang --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index d35a249a80a..80515077abd 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -448,7 +448,7 @@ pub fn load_config( }) } -// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +// Check for the presence of known config file names (`rustfmt.toml`, `.rustfmt.toml`) in `dir` // // Return the path if a config file exists, empty if no file exists, and Error for IO errors fn get_toml_path(dir: &Path) -> Result, Error> { From 182a20378b3a844e3677ff93d96f8ac70b9f009a Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:51:19 -0700 Subject: [PATCH 30/30] ci: bump actions/checkout to v4 --- .github/workflows/check_diff.yml | 2 +- .github/workflows/integration.yml | 2 +- .github/workflows/linux.yml | 2 +- .github/workflows/mac.yml | 2 +- .github/workflows/rustdoc_check.yml | 2 +- .github/workflows/upload-assets.yml | 2 +- .github/workflows/windows.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml index 2f2beb76915..99daa0addf5 100644 --- a/.github/workflows/check_diff.yml +++ b/.github/workflows/check_diff.yml @@ -21,7 +21,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install rustup run: | diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f0dd0cf73bb..bda374562bc 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -64,7 +64,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index bce9b0c8d5a..3a5e6ab5404 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,7 +26,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index f98c9830a4d..2c766d0573b 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -22,7 +22,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml index cd0c3218971..6e8a7ecd7ad 100644 --- a/.github/workflows/rustdoc_check.yml +++ b/.github/workflows/rustdoc_check.yml @@ -11,7 +11,7 @@ jobs: name: rustdoc check steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install rustup run: | diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml index 7dfaa4b9204..7a639b469e8 100644 --- a/.github/workflows/upload-assets.yml +++ b/.github/workflows/upload-assets.yml @@ -31,7 +31,7 @@ jobs: target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ec37c714b08..728f1b90b13 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -33,7 +33,7 @@ jobs: - name: disable git eol translation run: git config --global core.autocrlf false - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: Install Rustup using win.rustup.rs