From deb911fb5755d46f939917ef987a29f6c56c6ba1 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 5 Oct 2026 17:27:46 +0100 Subject: [PATCH 1/2] Struct fields: remove unnecessary parens Like is already done for expressions, e.g. let _ = ((var)) -> let _ = (var) Do this by extending the function used for expressions. This is part of my working looking in to issue rust-lang/rustfmt#6642 (but doesn't directly address it) --- src/expr.rs | 38 +++++++++++++++++++++++++++-------- src/types.rs | 11 ++++++++++ tests/source/struct_fields.rs | 7 +++++++ tests/target/struct_fields.rs | 7 +++++++ 4 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/source/struct_fields.rs create mode 100644 tests/target/struct_fields.rs diff --git a/src/expr.rs b/src/expr.rs index f0e56ffb8ea..67f97cab254 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1660,14 +1660,15 @@ pub(crate) fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) -> result } -pub(crate) fn rewrite_paren( +/// Remove any unnecessary nested parentheses from the expression. Parentheses are unnecessary when +/// they contain only whitespace. +pub(crate) fn unwrap_parens<'a, R: Rewrite + Spanned>( context: &RewriteContext<'_>, - mut subexpr: &ast::Expr, + mut subexpr: &'a R, shape: Shape, mut span: Span, -) -> RewriteResult { - debug!("rewrite_paren, shape: {:?}", shape); - + nested_getter: fn(&R) -> Option<&R>, +) -> Result<(&'a R, Span, Span, String, String), RewriteError> { // Extract comments within parens. let mut pre_span; let mut post_span; @@ -1677,14 +1678,14 @@ pub(crate) fn rewrite_paren( loop { // 1 = "(" or ")" pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span().lo()); - post_span = mk_sp(subexpr.span.hi(), span.hi() - BytePos(1)); + post_span = mk_sp(subexpr.span().hi(), span.hi() - BytePos(1)); pre_comment = rewrite_missing_comment(pre_span, shape, context)?; post_comment = rewrite_missing_comment(post_span, shape, context)?; // Remove nested parens if there are no comments. - if let ast::ExprKind::Paren(ref subsubexpr) = subexpr.kind { + if let Some(subsubexpr) = nested_getter(&subexpr) { if remove_nested_parens && pre_comment.is_empty() && post_comment.is_empty() { - span = subexpr.span; + span = subexpr.span(); subexpr = subsubexpr; continue; } @@ -1692,6 +1693,27 @@ pub(crate) fn rewrite_paren( break; } + Ok((subexpr, pre_span, post_span, pre_comment, post_comment)) +} + +pub(crate) fn rewrite_paren( + context: &RewriteContext<'_>, + subexpr: &ast::Expr, + shape: Shape, + span: Span, +) -> RewriteResult { + debug!("rewrite_paren, shape: {:?}", shape); + + let (subexpr, pre_span, post_span, pre_comment, post_comment) = unwrap_parens( + context, + subexpr, + shape, + span, + |expr: &ast::Expr| match &expr.kind { + ast::ExprKind::Paren(subsubexpr) => Some(subsubexpr), + _ => None, + }, + )?; // 1 = `(` and `)` let sub_shape = shape.offset_left(1, span)?.sub_width(1, span)?; diff --git a/src/types.rs b/src/types.rs index e2c92e58062..1169ff542f2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -9,6 +9,7 @@ use crate::config::lists::*; use crate::config::{IndentStyle, StyleEdition, TypeDensity}; use crate::expr::{ ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, + unwrap_parens, }; use crate::lists::{ ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, @@ -928,6 +929,16 @@ impl Rewrite for ast::Ty { .rewrite_result(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| format!("({})", ty_str)); } + let (ty, _, _, _, _) = unwrap_parens( + context, + ty.as_ref(), + shape, + self.span, + |ty: &ast::Ty| match &ty.kind { + ast::TyKind::Paren(nested) => Some(nested), + _ => None, + }, + )?; // 2 = () if let Some(sh) = shape.sub_width_opt(2) { diff --git a/tests/source/struct_fields.rs b/tests/source/struct_fields.rs new file mode 100644 index 00000000000..ba3a6380245 --- /dev/null +++ b/tests/source/struct_fields.rs @@ -0,0 +1,7 @@ +// rustfmt-style_edition: 2024 + +struct F { + f: ((u32)), +} + +struct F(((u32))); diff --git a/tests/target/struct_fields.rs b/tests/target/struct_fields.rs new file mode 100644 index 00000000000..e0186117a6d --- /dev/null +++ b/tests/target/struct_fields.rs @@ -0,0 +1,7 @@ +// rustfmt-style_edition: 2024 + +struct F { + f: (u32), +} + +struct F((u32)); From 36d00f62b35cd6af759c2209f08950c4763e2ee7 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 5 Oct 2026 22:45:25 +0100 Subject: [PATCH 2/2] fixup! Struct fields: remove unnecessary parens --- src/types.rs | 22 ++++++++++++---------- tests/source/struct_fields.rs | 2 +- tests/target/struct_fields.rs | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/types.rs b/src/types.rs index 1169ff542f2..8703636df71 100644 --- a/src/types.rs +++ b/src/types.rs @@ -929,16 +929,18 @@ impl Rewrite for ast::Ty { .rewrite_result(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| format!("({})", ty_str)); } - let (ty, _, _, _, _) = unwrap_parens( - context, - ty.as_ref(), - shape, - self.span, - |ty: &ast::Ty| match &ty.kind { - ast::TyKind::Paren(nested) => Some(nested), - _ => None, - }, - )?; + let ty = if context.config.style_edition() < StyleEdition::Edition2027 { + ty + } else { + let (ty, _, _, _, _) = + unwrap_parens(context, ty.as_ref(), shape, self.span, |ty: &ast::Ty| { + match &ty.kind { + ast::TyKind::Paren(nested) => Some(nested), + _ => None, + } + })?; + ty + }; // 2 = () if let Some(sh) = shape.sub_width_opt(2) { diff --git a/tests/source/struct_fields.rs b/tests/source/struct_fields.rs index ba3a6380245..9b0fff71227 100644 --- a/tests/source/struct_fields.rs +++ b/tests/source/struct_fields.rs @@ -1,4 +1,4 @@ -// rustfmt-style_edition: 2024 +// rustfmt-style_edition: 2027 struct F { f: ((u32)), diff --git a/tests/target/struct_fields.rs b/tests/target/struct_fields.rs index e0186117a6d..8b374d055ea 100644 --- a/tests/target/struct_fields.rs +++ b/tests/target/struct_fields.rs @@ -1,4 +1,4 @@ -// rustfmt-style_edition: 2024 +// rustfmt-style_edition: 2027 struct F { f: (u32),