From 2b3bceb89f4a1c8e122edfce1f25e01fd5edcb7b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: [PATCH 01/35] Add `{ast,hir,thir}::PatKind::Missing` variants. "Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- src/items.rs | 6 +----- src/patterns.rs | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/items.rs b/src/items.rs index 3fb3284e3d7..81ff6327a4f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2433,11 +2433,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param } pub(crate) fn is_named_param(param: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { - ident.name != symbol::kw::Empty - } else { - true - } + !matches!(param.pat.kind, ast::PatKind::Missing) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/patterns.rs b/src/patterns.rs index bafed41e39f..8ec3de286dc 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -42,6 +42,7 @@ pub(crate) fn is_short_pattern( fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool { match &pat.kind { + ast::PatKind::Missing => unreachable!(), ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => { true } @@ -100,6 +101,7 @@ impl Rewrite for Pat { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self.kind { + PatKind::Missing => unreachable!(), PatKind::Or(ref pats) => { let pat_strs = pats .iter() From ce70a7999c172ec6e02d0d704802c5fa840ee692 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 16 May 2024 09:22:37 +1000 Subject: [PATCH 02/35] Impl `Copy` for `Token` and `TokenKind`. --- src/macros.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index ddf3d2ce96a..1e16aace304 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -858,18 +858,18 @@ impl MacroArgParser { }; self.result.push(ParsedMacroArg { - kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()), + kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok), }); Some(()) } - fn update_buffer(&mut self, t: &Token) { + fn update_buffer(&mut self, t: Token) { if self.buf.is_empty() { - self.start_tok = t.clone(); + self.start_tok = t; } else { let needs_space = match next_space(&self.last_tok.kind) { - SpaceState::Ident => ident_like(t), - SpaceState::Punctuation => !ident_like(t), + SpaceState::Ident => ident_like(&t), + SpaceState::Punctuation => !ident_like(&t), SpaceState::Always => true, SpaceState::Never => false, }; @@ -878,7 +878,7 @@ impl MacroArgParser { } } - self.buf.push_str(&pprust::token_to_string(t)); + self.buf.push_str(&pprust::token_to_string(&t)); } fn need_space_prefix(&self) -> bool { @@ -937,7 +937,7 @@ impl MacroArgParser { ) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(ref t, _) => self.update_buffer(t), + &TokenTree::Token(t, _) => self.update_buffer(t), &TokenTree::Delimited(_dspan, _spacing, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok.kind) == SpaceState::Always { From 409c7b8501d207efdc3fc34afdf56c9e72ca0bea Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Dec 2024 10:15:05 +1100 Subject: [PATCH 03/35] Tighten up assignment operator representations. In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and `AssocOp::AssignOp`, even though this allows some nonsensical combinations. E.g. there is no `&&=` operator. Likewise for HIR and THIR. This commit introduces `AssignOpKind` which only includes the ten assignable operators, and uses it in `ExprKind::AssignOp` and `AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and `thir::ExprKind`.) This avoids the possibility of nonsensical combinations, as seen by the removal of the `bug!` case in `lang_item_for_binop`. The commit is mostly plumbing, including: - Adds an `impl From for BinOpKind` (AST) and `impl From for BinOp` (MIR/THIR). - `BinOpCategory` can now be created from both `BinOpKind` and `AssignOpKind`. - Replaces the `IsAssign` type with `Op`, which has more information and a few methods. - `suggest_swapping_lhs_and_rhs`: moves the condition to the call site, it's easier that way. - `check_expr_inner`: had to factor out some code into a separate method. I'm on the fence about whether avoiding the nonsensical combinations is worth the extra code. --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 65120770edd..be6b483bfff 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2058,7 +2058,7 @@ fn rewrite_assignment( context: &RewriteContext<'_>, lhs: &ast::Expr, rhs: &ast::Expr, - op: Option<&ast::BinOp>, + op: Option<&ast::AssignOp>, shape: Shape, ) -> RewriteResult { let operator_str = match op { From 1abbb9219ec5cb2d2e5aa0ccfe539ea5bd1b3c5a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Apr 2025 16:13:50 +1000 Subject: [PATCH 04/35] Remove `token::{Open,Close}Delim`. By replacing them with `{Open,Close}{Param,Brace,Bracket,Invisible}`. PR #137902 made `ast::TokenKind` more like `lexer::TokenKind` by replacing the compound `BinOp{,Eq}(BinOpToken)` variants with fieldless variants `Plus`, `Minus`, `Star`, etc. This commit does a similar thing with delimiters. It also makes `ast::TokenKind` more similar to `parser::TokenType`. This requires a few new methods: - `TokenKind::is_{,open_,close_}delim()` replace various kinds of pattern matches. - `Delimiter::as_{open,close}_token_kind` are used to convert `Delimiter` values to `TokenKind`. Despite these additions, it's a net reduction in lines of code. This is because e.g. `token::OpenParen` is so much shorter than `token::OpenDelim(Delimiter::Parenthesis)` that many multi-line forms reduce to single line forms. And many places where the number of lines doesn't change are still easier to read, just because the names are shorter, e.g.: ``` - } else if self.token != token::CloseDelim(Delimiter::Brace) { + } else if self.token != token::CloseBrace { ``` --- src/macros.rs | 12 +++++++++--- src/parse/macros/cfg_if.rs | 6 ++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 1e16aace304..0ff0aad7a2d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -722,7 +722,7 @@ fn last_tok(tt: &TokenTree) -> Token { match *tt { TokenTree::Token(ref t, _) => t.clone(), TokenTree::Delimited(delim_span, _, delim, _) => Token { - kind: TokenKind::CloseDelim(delim), + kind: delim.as_open_token_kind(), span: delim_span.close, }, } @@ -1124,8 +1124,14 @@ fn next_space(tok: &TokenKind) -> SpaceState { TokenKind::PathSep | TokenKind::Pound | TokenKind::Dollar - | TokenKind::OpenDelim(_) - | TokenKind::CloseDelim(_) => SpaceState::Never, + | TokenKind::OpenParen + | TokenKind::CloseParen + | TokenKind::OpenBrace + | TokenKind::CloseBrace + | TokenKind::OpenBracket + | TokenKind::CloseBracket + | TokenKind::OpenInvisible(_) + | TokenKind::CloseInvisible(_) => SpaceState::Never, TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(..) => { SpaceState::Ident diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index 0b7b6c4d361..30b83373c17 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -1,7 +1,7 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::ast; -use rustc_ast::token::{Delimiter, TokenKind}; +use rustc_ast::token::TokenKind; use rustc_parse::exp; use rustc_parse::parser::ForceCollect; use rustc_span::symbol::kw; @@ -60,9 +60,7 @@ fn parse_cfg_if_inner<'a>( return Err("Expected an opening brace"); } - while parser.token != TokenKind::CloseDelim(Delimiter::Brace) - && parser.token.kind != TokenKind::Eof - { + while parser.token != TokenKind::CloseBrace && parser.token.kind != TokenKind::Eof { let item = match parser.parse_item(ForceCollect::No) { Ok(Some(item_ptr)) => item_ptr.into_inner(), Ok(None) => continue, From 31d40e5e580066f2e5cc2b1f6b6179e767e9016b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Feb 2025 09:46:46 +0000 Subject: [PATCH 05/35] Add or-patterns to pattern types --- src/types.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/types.rs b/src/types.rs index 75a5a8532b8..7ec1032dcb4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1093,6 +1093,19 @@ impl Rewrite for ast::TyPat { ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => { rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span) } + ast::TyPatKind::Or(ref variants) => { + let mut first = true; + let mut s = String::new(); + for variant in variants { + if first { + first = false + } else { + s.push_str(" | "); + } + s.push_str(&variant.rewrite_result(context, shape)?); + } + Ok(s) + } ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), } } From ce64001450d155d995f3d6e663717fce4832dfc0 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 29 Apr 2025 15:36:23 -0500 Subject: [PATCH 06/35] Also allow bool literals as first item of let chain Co-authored-by: est31 --- src/pairs.rs | 14 +++++++++----- tests/source/let_chains.rs | 10 +++++----- tests/target/let_chains.rs | 8 +++----- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/pairs.rs b/src/pairs.rs index 9c51298416b..17ff041d775 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -1,4 +1,4 @@ -use rustc_ast::ast; +use rustc_ast::{ast, token}; use rustc_span::Span; use crate::config::IndentStyle; @@ -272,13 +272,17 @@ struct PairList<'a, 'b, T: Rewrite> { span: Span, } -fn is_ident(expr: &ast::Expr) -> bool { +fn is_ident_or_bool_lit(expr: &ast::Expr) -> bool { match &expr.kind { ast::ExprKind::Path(None, path) if path.segments.len() == 1 => true, + ast::ExprKind::Lit(token::Lit { + kind: token::LitKind::Bool, + .. + }) => true, ast::ExprKind::Unary(_, expr) | ast::ExprKind::AddrOf(_, _, expr) | ast::ExprKind::Paren(expr) - | ast::ExprKind::Try(expr) => is_ident(expr), + | ast::ExprKind::Try(expr) => is_ident_or_bool_lit(expr), _ => false, } } @@ -296,10 +300,10 @@ impl<'a, 'b> PairList<'a, 'b, ast::Expr> { return false; } - let fist_item_is_ident = is_ident(self.list[0].0); + let fist_item_is_ident_or_bool_lit = is_ident_or_bool_lit(self.list[0].0); let second_item_is_let_chain = matches!(self.list[1].0.kind, ast::ExprKind::Let(..)); - fist_item_is_ident && second_item_is_let_chain + fist_item_is_ident_or_bool_lit && second_item_is_let_chain } } diff --git a/tests/source/let_chains.rs b/tests/source/let_chains.rs index b7c1f811096..0c4d8aa85ea 100644 --- a/tests/source/let_chains.rs +++ b/tests/source/let_chains.rs @@ -20,6 +20,11 @@ fn test_single_line_let_chain() { if a && let Some(b) = foo() { } + // first item in let-chain is a bool literal + if true && let Some(x) = y { + + } + // first item in let-chain is a unary ! with an ident let unary_not = if !from_hir_call && let Some(p) = parent @@ -94,11 +99,6 @@ fn test_multi_line_let_chain() { } - // bool literal - if true && let Some(x) = y { - - } - // cast to a bool if 1 as bool && let Some(x) = y { diff --git a/tests/target/let_chains.rs b/tests/target/let_chains.rs index 1ceecac8abc..204937b4cac 100644 --- a/tests/target/let_chains.rs +++ b/tests/target/let_chains.rs @@ -50,6 +50,9 @@ fn test_single_line_let_chain() { // first item in let-chain is an ident if a && let Some(b) = foo() {} + // first item in let-chain is a bool literal + if true && let Some(x) = y {} + // first item in let-chain is a unary ! with an ident let unary_not = if !from_hir_call && let Some(p) = parent {}; @@ -102,11 +105,6 @@ fn test_multi_line_let_chain() { && let Some(x) = y {} - // bool literal - if true - && let Some(x) = y - {} - // cast to a bool if 1 as bool && let Some(x) = y From 266da42737a328d14429c97e43de22c056899208 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 May 2025 15:30:48 +0000 Subject: [PATCH 07/35] Do not remove super keyword from super-let --- src/items.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/items.rs b/src/items.rs index 5c3be769f9e..e79b7803c60 100644 --- a/src/items.rs +++ b/src/items.rs @@ -63,6 +63,11 @@ impl Rewrite for ast::Local { return Err(RewriteError::SkipFormatting); } + // FIXME(super_let): Implement formatting + if self.super_.is_some() { + return Err(RewriteError::SkipFormatting); + } + let attrs_str = self.attrs.rewrite_result(context, shape)?; let mut result = if attrs_str.is_empty() { "let ".to_owned() From 6210ac1a15cb75ea95e9ad51e665d19eeb13d2f4 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 30 Apr 2025 01:06:38 +0200 Subject: [PATCH 08/35] attempt to have rustfmt use the new logic apparently it doesn't really use the asm parsing at present, so this may work? --- src/parse/macros/asm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs index 58c8d21bd7a..18e3386f4f1 100644 --- a/src/parse/macros/asm.rs +++ b/src/parse/macros/asm.rs @@ -1,11 +1,14 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args}; +use rustc_builtin_macros::asm::{RawAsmArg, parse_raw_asm_args}; use crate::rewrite::RewriteContext; #[allow(dead_code)] -pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option { +pub(crate) fn parse_asm( + context: &RewriteContext<'_>, + mac: &ast::MacCall, +) -> Option> { let ts = mac.args.tokens.clone(); let mut parser = super::build_parser(context, ts); - parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok() + parse_raw_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok() } From 2f3a0a55364d31a39d09ba1a3d62d74e92b8c08a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 17 May 2025 23:17:06 +0200 Subject: [PATCH 09/35] rename to get rid of the 'raw' concept --- src/parse/macros/asm.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs index 18e3386f4f1..1a9614bacec 100644 --- a/src/parse/macros/asm.rs +++ b/src/parse/macros/asm.rs @@ -1,14 +1,11 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{RawAsmArg, parse_raw_asm_args}; +use rustc_builtin_macros::asm::{AsmArg, parse_asm_args}; use crate::rewrite::RewriteContext; #[allow(dead_code)] -pub(crate) fn parse_asm( - context: &RewriteContext<'_>, - mac: &ast::MacCall, -) -> Option> { +pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option> { let ts = mac.args.tokens.clone(); let mut parser = super::build_parser(context, ts); - parse_raw_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok() + parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok() } From 79a989770dd8efd377fb6fe20f938393f2d7bfdf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 May 2025 02:32:22 +1000 Subject: [PATCH 10/35] Reduce `P` to a typedef of `Box`. Keep the `P` constructor function for now, to minimize immediate churn. All the `into_inner` calls are removed, which is nice. --- src/modules.rs | 2 +- src/parse/macros/cfg_if.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules.rs b/src/modules.rs index bc5a6d3e704..44c8123517c 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -174,7 +174,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { ) -> Result<(), ModuleResolutionError> { for item in items { if is_cfg_if(&item) { - self.visit_cfg_if(Cow::Owned(item.into_inner()))?; + self.visit_cfg_if(Cow::Owned(*item))?; continue; } diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index 30b83373c17..26bf6c5326f 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -62,7 +62,7 @@ fn parse_cfg_if_inner<'a>( while parser.token != TokenKind::CloseBrace && parser.token.kind != TokenKind::Eof { let item = match parser.parse_item(ForceCollect::No) { - Ok(Some(item_ptr)) => item_ptr.into_inner(), + Ok(Some(item_ptr)) => *item_ptr, Ok(None) => continue, Err(err) => { err.cancel(); From 4718757845dd5baf85849e430520f478662c835f Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 5 May 2025 15:24:14 +0200 Subject: [PATCH 11/35] move asm parsing code into `rustc_parse` --- src/lib.rs | 1 - src/parse/macros/asm.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 08cda6913b9..942b42ec5f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ // N.B. these crates are loaded from the sysroot, so they need extern crate. extern crate rustc_ast; extern crate rustc_ast_pretty; -extern crate rustc_builtin_macros; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_expand; diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs index 1a9614bacec..bfa9c6300c4 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::{AsmArg, parse_asm_args}; +use rustc_parse::parser::asm::{AsmArg, parse_asm_args}; use crate::rewrite::RewriteContext; From 2d7453d602012352a1c5f121fb72c1810da9a3b3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 May 2025 08:20:30 +1000 Subject: [PATCH 12/35] Reorder `ast::ItemKind::{Struct,Enum,Union}` fields. So they match the order of the parts in the source code, e.g.: ``` struct Foo { t: T, u: U } <-><----> <------------> / | \ ident generics variant_data ``` --- src/items.rs | 4 ++-- src/visitor.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items.rs b/src/items.rs index e79b7803c60..1a3897b51cb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1110,10 +1110,10 @@ impl<'a> StructParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (prefix, def, ident, generics) = match item.kind { - ast::ItemKind::Struct(ident, ref def, ref generics) => { + ast::ItemKind::Struct(ident, ref generics, ref def) => { ("struct ", def, ident, generics) } - ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics), + ast::ItemKind::Union(ident, ref generics, ref def) => ("union ", def, ident, generics), _ => unreachable!(), }; StructParts { diff --git a/src/visitor.rs b/src/visitor.rs index 16d1f5105d5..f6a9a3f2cd1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -521,7 +521,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { self.visit_struct(&StructParts::from_item(item)); } - ast::ItemKind::Enum(ident, ref def, ref generics) => { + ast::ItemKind::Enum(ident, ref generics, ref def) => { self.format_missing_with_indent(source!(self, item.span).lo()); self.visit_enum(ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); From d37c63f4cd9069445bdb71cb125ea71ca744edc2 Mon Sep 17 00:00:00 2001 From: Frank King Date: Sun, 19 Jan 2025 22:01:11 +0800 Subject: [PATCH 13/35] Implement pinned borrows, part of `pin_ergonomics` --- src/expr.rs | 2 ++ tests/source/pin_sugar.rs | 10 ++++++++++ tests/target/pin_sugar.rs | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/src/expr.rs b/src/expr.rs index be6b483bfff..08aedff2b20 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2289,8 +2289,10 @@ fn rewrite_expr_addrof( ) -> RewriteResult { let operator_str = match (mutability, borrow_kind) { (ast::Mutability::Not, ast::BorrowKind::Ref) => "&", + (ast::Mutability::Not, ast::BorrowKind::Pin) => "&pin const ", (ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ", (ast::Mutability::Mut, ast::BorrowKind::Ref) => "&mut ", + (ast::Mutability::Mut, ast::BorrowKind::Pin) => "&pin mut ", (ast::Mutability::Mut, ast::BorrowKind::Raw) => "&raw mut ", }; rewrite_unary_prefix(context, operator_str, expr, shape) diff --git a/tests/source/pin_sugar.rs b/tests/source/pin_sugar.rs index 370dfbc196a..e5b47339b92 100644 --- a/tests/source/pin_sugar.rs +++ b/tests/source/pin_sugar.rs @@ -18,3 +18,13 @@ impl Foo { mut self) {} fn i(&pin mut self) {} } + +fn borrows() { + let mut foo = 0_i32; + let x: Pin<&mut _> = & pin + mut foo; + + let x: Pin<&_> = & + pin const + foo; +} diff --git a/tests/target/pin_sugar.rs b/tests/target/pin_sugar.rs index 7d04efb1b32..09ad23a5807 100644 --- a/tests/target/pin_sugar.rs +++ b/tests/target/pin_sugar.rs @@ -16,3 +16,10 @@ impl Foo { fn h<'a>(&'a pin mut self) {} fn i(&pin mut self) {} } + +fn borrows() { + let mut foo = 0_i32; + let x: Pin<&mut _> = &pin mut foo; + + let x: Pin<&_> = &pin const foo; +} From 928d1dc5b91dadfc1dc7f69953b0b73d931cc4cc Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 19 Jun 2025 13:02:04 -0500 Subject: [PATCH 14/35] Extract Translator struct --- src/parse/session.rs | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index afd847f9515..73a89072f14 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::registry::Registry; -use rustc_errors::translation::Translate; +use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ @@ -47,16 +47,6 @@ impl SilentOnIgnoredFilesEmitter { } } -impl Translate for SilentOnIgnoredFilesEmitter { - fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { - self.emitter.fluent_bundle() - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - self.emitter.fallback_fluent_bundle() - } -} - impl Emitter for SilentOnIgnoredFilesEmitter { fn source_map(&self) -> Option<&SourceMap> { None @@ -84,6 +74,10 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } self.handle_non_ignoreable_error(diag, registry); } + + fn translator(&self) -> &Translator { + self.emitter.translator() + } } impl From for ColorConfig { @@ -110,12 +104,9 @@ fn default_dcx( ColorConfig::Never }; - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); + let translator = rustc_driver::default_translator(); let emitter = Box::new( - HumanEmitter::new(stderr_destination(emit_color), fallback_bundle) + HumanEmitter::new(stderr_destination(emit_color), translator) .sm(Some(source_map.clone())), ); @@ -335,16 +326,6 @@ mod tests { num_emitted_errors: Arc, } - impl Translate for TestEmitter { - fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { - None - } - - fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - panic!("test emitter attempted to translate a diagnostic"); - } - } - impl Emitter for TestEmitter { fn source_map(&self) -> Option<&SourceMap> { None @@ -353,6 +334,10 @@ mod tests { fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } + + fn translator(&self) -> &Translator { + panic!("test emitter attempted to translate a diagnostic"); + } } fn build_diagnostic(level: DiagnosticLevel, span: Option) -> DiagInner { From e9d0738467380dcc32de35c33e14d1d7a3197c05 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Tue, 17 Jun 2025 16:59:57 -0500 Subject: [PATCH 15/35] Rename SilentEmitter -> FatalOnlyEmitter --- src/parse/session.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index 73a89072f14..c50d4ef0489 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; +use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, FatalOnlyEmitter, stderr_destination}; use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; @@ -111,7 +111,7 @@ fn default_dcx( ); let emitter: Box = if !show_parse_errors { - Box::new(SilentEmitter { + Box::new(FatalOnlyEmitter { fatal_emitter: emitter, fatal_note: None, emit_fatal_diagnostic: false, From ced2bb075e8c24dc62dd7981604bfc859dcd5f2a Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 19 Jun 2025 13:05:01 -0500 Subject: [PATCH 16/35] Extract SilentEmitter --- src/parse/session.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/parse/session.rs b/src/parse/session.rs index c50d4ef0489..10e2809e58b 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, FatalOnlyEmitter, stderr_destination}; +use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; @@ -105,19 +105,14 @@ fn default_dcx( }; let translator = rustc_driver::default_translator(); - let emitter = Box::new( - HumanEmitter::new(stderr_destination(emit_color), translator) - .sm(Some(source_map.clone())), - ); - - let emitter: Box = if !show_parse_errors { - Box::new(FatalOnlyEmitter { - fatal_emitter: emitter, - fatal_note: None, - emit_fatal_diagnostic: false, - }) + + let emitter: Box = if show_parse_errors { + Box::new( + HumanEmitter::new(stderr_destination(emit_color), translator) + .sm(Some(source_map.clone())), + ) } else { - emitter + Box::new(SilentEmitter { translator }) }; DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, @@ -196,7 +191,7 @@ impl ParseSess { } pub(crate) fn set_silent_emitter(&mut self) { - self.raw_psess.dcx().make_silent(None, false); + self.raw_psess.dcx().make_silent(); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { From f81941c038505626abdeb3743f59840ec881988b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 May 2025 15:06:56 +1000 Subject: [PATCH 17/35] Remove an unnecessary check in rustfmt. "{{root}}" is an internal-only name, and cannot appear in Rust code being formatted. --- src/imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imports.rs b/src/imports.rs index b741dd9b5da..788fed013ad 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -184,7 +184,7 @@ impl UseSegment { modsep: bool, ) -> Option { let name = rewrite_ident(context, path_seg.ident); - if name.is_empty() || name == "{{root}}" { + if name.is_empty() { return None; } let kind = match name { From 9debb8f171b19e3f07f508f60820b40012d45cf1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 11 Mar 2025 12:08:45 +0000 Subject: [PATCH 18/35] Change const trait bound syntax from ~const to [const] --- tests/source/type.rs | 12 ++++++------ tests/target/type.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/source/type.rs b/tests/source/type.rs index 7a232f85198..213fad7cb16 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -142,18 +142,18 @@ type MyFn = fn(a: SomeLongComplexType, b: SomeOtherLongComplexType,) -> Box() -> i32 { ::CONST } +const fn not_quite_const() -> i32 { ::CONST } -impl ~ const T {} +impl const T for U {} -fn apit(_: impl ~ const T) {} +fn apit(_: impl [ const ] T) {} -fn rpit() -> impl ~ const T { S } +fn rpit() -> impl [ const] T { S } pub struct Foo(T); -impl Foo { +impl Foo { fn new(t: T) -> Self { Self(t) } diff --git a/tests/target/type.rs b/tests/target/type.rs index 325adb52f3f..93479f8b484 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -147,22 +147,22 @@ type MyFn = fn( // Const bound -trait T: ~const Super {} +trait T: [const] Super {} -const fn not_quite_const() -> i32 { +const fn not_quite_const() -> i32 { ::CONST } -impl ~const T {} +impl const T for U {} -fn apit(_: impl ~const T) {} +fn apit(_: impl [const] T) {} -fn rpit() -> impl ~const T { +fn rpit() -> impl [const] T { S } pub struct Foo(T); -impl Foo { +impl Foo { fn new(t: T) -> Self { Self(t) } From a22fa5b897314f398ac2c78d459bb7f65c0c1674 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sun, 29 Jun 2025 13:06:21 -0500 Subject: [PATCH 19/35] Remove let_chains feature --- tests/source/let_chains.rs | 2 ++ tests/target/let_chains.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/source/let_chains.rs b/tests/source/let_chains.rs index 0c4d8aa85ea..fc2a9310569 100644 --- a/tests/source/let_chains.rs +++ b/tests/source/let_chains.rs @@ -1,3 +1,5 @@ +// rustfmt-edition: 2024 + fn main() { if let x = x && x {} diff --git a/tests/target/let_chains.rs b/tests/target/let_chains.rs index 204937b4cac..4fd6048d914 100644 --- a/tests/target/let_chains.rs +++ b/tests/target/let_chains.rs @@ -1,3 +1,5 @@ +// rustfmt-edition: 2024 + fn main() { if let x = x && x From a5c21f93c66b60cbaad8cd2547f8e43d60a0efa1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 26 Jun 2025 02:01:38 +0000 Subject: [PATCH 20/35] Remove support for dyn* --- src/types.rs | 6 ------ tests/target/issue_5542.rs | 10 ---------- 2 files changed, 16 deletions(-) delete mode 100644 tests/target/issue_5542.rs diff --git a/src/types.rs b/src/types.rs index 7ec1032dcb4..dd1515805e5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -835,12 +835,6 @@ impl Rewrite for ast::Ty { .max_width_error(shape.width, self.span())?; (shape, "dyn ") } - ast::TraitObjectSyntax::DynStar => { - let shape = shape - .offset_left(5) - .max_width_error(shape.width, self.span())?; - (shape, "dyn* ") - } ast::TraitObjectSyntax::None => (shape, ""), }; let mut res = bounds.rewrite_result(context, shape)?; diff --git a/tests/target/issue_5542.rs b/tests/target/issue_5542.rs deleted file mode 100644 index 730bb7b681a..00000000000 --- a/tests/target/issue_5542.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(dyn_star)] -#![allow(incomplete_features)] - -use core::fmt::Debug; - -fn main() { - let i = 42; - let dyn_i = i as dyn* Debug; - dbg!(dyn_i); -} From 97b6e88265e714ab194e7fc29037c533b44bbe8e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 2 Jul 2024 09:38:49 +0000 Subject: [PATCH 21/35] Replace kw_span by full span. --- src/spanned.rs | 2 +- src/types.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spanned.rs b/src/spanned.rs index 507647566d4..ac132999b62 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -122,7 +122,7 @@ impl Spanned for ast::GenericParam { fn span(&self) -> Span { let lo = match self.kind { _ if !self.attrs.is_empty() => self.attrs[0].span.lo(), - ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(), + ast::GenericParamKind::Const { span, .. } => span.lo(), _ => self.ident.span.lo(), }; let hi = if self.bounds.is_empty() { diff --git a/src/types.rs b/src/types.rs index dd1515805e5..c0df01edd6d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -689,7 +689,7 @@ impl Rewrite for ast::GenericParam { let param_start = if let ast::GenericParamKind::Const { ref ty, - kw_span, + span, default, } = &self.kind { @@ -711,7 +711,7 @@ impl Rewrite for ast::GenericParam { default.rewrite_result(context, Shape::legacy(budget, shape.indent))?; param.push_str(&rewrite); } - kw_span.lo() + span.lo() } else { param.push_str(rewrite_ident(context, self.ident)); self.ident.span.lo() From c5916cf926d0d9356c9df997d3b194f02791cb97 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 6 Jul 2025 14:02:19 -0700 Subject: [PATCH 22/35] rustfmt: migrate BareFn -> FnPtr --- src/types.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/types.rs b/src/types.rs index c0df01edd6d..9ee10d86270 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1009,7 +1009,7 @@ impl Rewrite for ast::Ty { }) } } - ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), + ast::TyKind::FnPtr(ref fn_ptr) => rewrite_fn_ptr(fn_ptr, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { rewrite_macro(mac, context, shape, MacroPosition::Expression) @@ -1105,8 +1105,8 @@ impl Rewrite for ast::TyPat { } } -fn rewrite_bare_fn( - bare_fn: &ast::BareFnTy, +fn rewrite_fn_ptr( + fn_ptr: &ast::FnPtrTy, span: Span, context: &RewriteContext<'_>, shape: Shape, @@ -1115,7 +1115,7 @@ fn rewrite_bare_fn( let mut result = String::with_capacity(128); - if let Some(ref lifetime_str) = rewrite_bound_params(context, shape, &bare_fn.generic_params) { + if let Some(ref lifetime_str) = rewrite_bound_params(context, shape, &fn_ptr.generic_params) { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for multiline situation with lots of @@ -1124,10 +1124,10 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(crate::utils::format_safety(bare_fn.safety)); + result.push_str(crate::utils::format_safety(fn_ptr.safety)); result.push_str(&format_extern( - bare_fn.ext, + fn_ptr.ext, context.config.force_explicit_abi(), )); @@ -1145,9 +1145,9 @@ fn rewrite_bare_fn( }; let rewrite = format_function_type( - bare_fn.decl.inputs.iter(), - &bare_fn.decl.output, - bare_fn.decl.c_variadic(), + fn_ptr.decl.inputs.iter(), + &fn_ptr.decl.output, + fn_ptr.decl.c_variadic(), span, context, func_ty_shape, From a1cfe86dda8efb2a6343c3117b558bfda5e8d129 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 13 Jul 2025 16:49:19 +0800 Subject: [PATCH 23/35] parse `const trait Trait` --- src/items.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 1a3897b51cb..7084639aca9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1172,6 +1172,7 @@ pub(crate) fn format_trait( unreachable!(); }; let ast::Trait { + constness, is_auto, safety, ident, @@ -1182,7 +1183,8 @@ pub(crate) fn format_trait( let mut result = String::with_capacity(128); let header = format!( - "{}{}{}trait ", + "{}{}{}{}trait ", + format_constness(constness), format_visibility(context, &item.vis), format_safety(safety), format_auto(is_auto), From 340e59001479ef3d85ed027c4af9bf2707e30557 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 11 Sep 2023 00:59:31 -0400 Subject: [PATCH 24/35] Print thread ID in panic message if thread name is unknown `panic!` does not print any identifying information for threads that are unnamed. However, in many cases, the thread ID can be determined. This changes the panic message from something like this: thread '' panicked at src/main.rs:3:5: explicit panic To something like this: thread '' (0xff9bf) panicked at src/main.rs:3:5: explicit panic Stack overflow messages are updated as well. This change applies to both named and unnamed threads. The ID printed is the OS integer thread ID rather than the Rust thread ID, which should also be what debuggers print. --- tests/rustfmt/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index a9f58b9328e..4a9399377d1 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -185,10 +185,11 @@ fn dont_emit_ICE() { "tests/target/issue-6105.rs", ]; + let panic_re = regex::Regex::new("thread.*panicked").unwrap(); for file in files { let args = [file]; let (_stdout, stderr) = rustfmt(&args); - assert!(!stderr.contains("thread 'main' panicked")); + assert!(!panic_re.is_match(&stderr)); } } From 4501819ed04e691901e67a4b4c76b0bf8dfc5b3f Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 9 Aug 2025 13:24:06 +0800 Subject: [PATCH 25/35] remove `P` --- src/chains.rs | 6 +++--- src/closures.rs | 4 ++-- src/expr.rs | 6 +++--- src/items.rs | 10 +++++----- src/macros.rs | 10 +++++----- src/matches.rs | 6 +++--- src/modules.rs | 8 ++++---- src/overflow.rs | 4 ++-- src/parse/macros/lazy_static.rs | 3 +-- src/parse/macros/mod.rs | 14 +++++++------- src/parse/parser.rs | 4 ++-- src/patterns.rs | 13 ++++++------- src/rewrite.rs | 3 +-- src/spanned.rs | 4 ++-- src/types.rs | 5 ++--- src/utils.rs | 6 +++--- src/visitor.rs | 2 +- 17 files changed, 52 insertions(+), 56 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index 034ecde068a..2f388197ea1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -58,7 +58,7 @@ use std::borrow::Cow; use std::cmp::min; -use rustc_ast::{ast, ptr}; +use rustc_ast::ast; use rustc_span::{BytePos, Span, symbol}; use tracing::debug; @@ -187,7 +187,7 @@ enum ChainItemKind { MethodCall( ast::PathSegment, Vec, - ThinVec>, + ThinVec>, ), StructField(symbol::Ident), TupleField(symbol::Ident, bool), @@ -343,7 +343,7 @@ impl ChainItem { fn rewrite_method_call( method_name: symbol::Ident, types: &[ast::GenericArg], - args: &[ptr::P], + args: &[Box], span: Span, context: &RewriteContext<'_>, shape: Shape, diff --git a/src/closures.rs b/src/closures.rs index 61e148cdf18..bb10a7946b8 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,4 +1,4 @@ -use rustc_ast::{ast, ptr}; +use rustc_ast::ast; use rustc_span::Span; use thin_vec::thin_vec; use tracing::debug; @@ -165,7 +165,7 @@ fn rewrite_closure_with_block( let block = ast::Block { stmts: thin_vec![ast::Stmt { id: ast::NodeId::root(), - kind: ast::StmtKind::Expr(ptr::P(body.clone())), + kind: ast::StmtKind::Expr(Box::new(body.clone())), span: body.span, }], id: ast::NodeId::root(), diff --git a/src/expr.rs b/src/expr.rs index 08aedff2b20..975f9be44e4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3,7 +3,7 @@ use std::cmp::min; use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; -use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token}; +use rustc_ast::{ForLoopKind, MatchKind, ast, token}; use rustc_span::{BytePos, Span}; use tracing::debug; @@ -1368,7 +1368,7 @@ fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option, callee: &str, - args: &[ptr::P], + args: &[Box], span: Span, shape: Shape, ) -> RewriteResult { @@ -1634,7 +1634,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool fn rewrite_struct_lit<'a>( context: &RewriteContext<'_>, path: &ast::Path, - qself: &Option>, + qself: &Option>, fields: &'a [ast::ExprField], struct_rest: &ast::StructRest, attrs: &[ast::Attribute], diff --git a/src/items.rs b/src/items.rs index 7084639aca9..57d4142ebe4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -4,8 +4,8 @@ use std::borrow::Cow; use std::cmp::{Ordering, max, min}; use regex::Regex; +use rustc_ast::ast; use rustc_ast::visit; -use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol}; use tracing::debug; @@ -725,9 +725,9 @@ impl<'a> FmtVisitor<'a> { .ok() } - fn visit_impl_items(&mut self, items: &[ptr::P]) { + fn visit_impl_items(&mut self, items: &[Box]) { if self.get_context().config.reorder_impl_items() { - type TyOpt = Option>; + type TyOpt = Option>; use crate::ast::AssocItemKind::*; let is_type = |ty: &TyOpt| opaque_ty(ty).is_none(); let is_opaque = |ty: &TyOpt| opaque_ty(ty).is_some(); @@ -934,7 +934,7 @@ pub(crate) fn format_impl( fn is_impl_single_line( context: &RewriteContext<'_>, - items: &[ptr::P], + items: &[Box], result: &str, where_clause_str: &str, item: &ast::Item, @@ -2024,7 +2024,7 @@ pub(crate) struct StaticParts<'a> { generics: Option<&'a ast::Generics>, ty: &'a ast::Ty, mutability: ast::Mutability, - expr_opt: Option<&'a ptr::P>, + expr_opt: Option<&'a Box>, defaultness: Option, span: Span, } diff --git a/src/macros.rs b/src/macros.rs index 0ff0aad7a2d..2e7ac90f596 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,9 +12,9 @@ use std::collections::HashMap; use std::panic::{AssertUnwindSafe, catch_unwind}; +use rustc_ast::ast; use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; -use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol}; use tracing::debug; @@ -53,10 +53,10 @@ pub(crate) enum MacroPosition { #[derive(Debug)] pub(crate) enum MacroArg { - Expr(ptr::P), - Ty(ptr::P), - Pat(ptr::P), - Item(ptr::P), + Expr(Box), + Ty(Box), + Pat(Box), + Item(Box), Keyword(Ident, Span), } diff --git a/src/matches.rs b/src/matches.rs index 8f62648e576..209cb2f9287 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,7 +2,7 @@ use std::iter::repeat; -use rustc_ast::{MatchKind, ast, ptr}; +use rustc_ast::{MatchKind, ast}; use rustc_span::{BytePos, Span}; use tracing::debug; @@ -394,7 +394,7 @@ fn flatten_arm_body<'a>( fn rewrite_match_body( context: &RewriteContext<'_>, - body: &ptr::P, + body: &Box, pats_str: &str, shape: Shape, has_guard: bool, @@ -569,7 +569,7 @@ fn rewrite_match_body( // The `if ...` guard on a match arm. fn rewrite_guard( context: &RewriteContext<'_>, - guard: &Option>, + guard: &Option>, shape: Shape, // The amount of space used up on this line for the pattern in // the arm (excludes offset). diff --git a/src/modules.rs b/src/modules.rs index 44c8123517c..3bc656b64b3 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -26,7 +26,7 @@ type FileModMap<'ast> = BTreeMap>; #[derive(Debug, Clone)] pub(crate) struct Module<'a> { ast_mod_kind: Option>, - pub(crate) items: Cow<'a, ThinVec>>, + pub(crate) items: Cow<'a, ThinVec>>, inner_attr: ast::AttrVec, pub(crate) span: Span, } @@ -35,7 +35,7 @@ impl<'a> Module<'a> { pub(crate) fn new( mod_span: Span, ast_mod_kind: Option>, - mod_items: Cow<'a, ThinVec>>, + mod_items: Cow<'a, ThinVec>>, mod_attrs: Cow<'a, ast::AttrVec>, ) -> Self { let inner_attr = mod_attrs @@ -170,7 +170,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { /// Visit modules defined inside macro calls. fn visit_mod_outside_ast( &mut self, - items: ThinVec>, + items: ThinVec>, ) -> Result<(), ModuleResolutionError> { for item in items { if is_cfg_if(&item) { @@ -197,7 +197,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { /// Visit modules from AST. fn visit_mod_from_ast( &mut self, - items: &'ast [rustc_ast::ptr::P], + items: &'ast [Box], ) -> Result<(), ModuleResolutionError> { for item in items { if is_cfg_if(item) { diff --git a/src/overflow.rs b/src/overflow.rs index 728adff2c7d..bb1ebc87f67 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -3,8 +3,8 @@ use std::cmp::min; use itertools::Itertools; +use rustc_ast::ast; use rustc_ast::token::Delimiter; -use rustc_ast::{ast, ptr}; use rustc_span::Span; use tracing::debug; @@ -219,7 +219,7 @@ pub(crate) trait IntoOverflowableItem<'a>: Rewrite + Spanned { fn into_overflowable_item(&'a self) -> OverflowableItem<'a>; } -impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for ptr::P { +impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for Box { fn into_overflowable_item(&'a self) -> OverflowableItem<'a> { (**self).into_overflowable_item() } diff --git a/src/parse/macros/lazy_static.rs b/src/parse/macros/lazy_static.rs index cbe81004e22..8611615d123 100644 --- a/src/parse/macros/lazy_static.rs +++ b/src/parse/macros/lazy_static.rs @@ -1,5 +1,4 @@ use rustc_ast::ast; -use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_parse::exp; @@ -10,7 +9,7 @@ use crate::rewrite::RewriteContext; pub(crate) fn parse_lazy_static( context: &RewriteContext<'_>, ts: TokenStream, -) -> Option, P)>> { +) -> Option, Box)>> { let mut result = vec![]; let mut parser = super::build_parser(context, ts); macro_rules! parse_or { diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index d7964484b26..724d7a09e4a 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -1,6 +1,6 @@ +use rustc_ast::ast; use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{ast, ptr}; use rustc_parse::MACRO_ARGUMENTS; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_session::parse::ParseSess; @@ -49,26 +49,26 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { Expr, NonterminalKind::Expr(Expr), |parser: &mut Parser<'b>| parser.parse_expr(), - |x: ptr::P| Some(x) + |x: Box| Some(x) ); parse_macro_arg!( Ty, NonterminalKind::Ty, |parser: &mut Parser<'b>| parser.parse_ty(), - |x: ptr::P| Some(x) + |x: Box| Some(x) ); parse_macro_arg!( Pat, NonterminalKind::Pat(PatParam { inferred: false }), |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None), - |x: ptr::P| Some(x) + |x: Box| Some(x) ); - // `parse_item` returns `Option>`. + // `parse_item` returns `Option>`. parse_macro_arg!( Item, NonterminalKind::Item, |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No), - |x: Option>| x + |x: Option>| x ); None @@ -164,7 +164,7 @@ pub(crate) fn parse_macro_args( pub(crate) fn parse_expr( context: &RewriteContext<'_>, tokens: TokenStream, -) -> Option> { +) -> Option> { let mut parser = build_parser(context, tokens); parser.parse_expr().ok() } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index f357aed66c2..2ec8769c45f 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,7 +1,7 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::{Path, PathBuf}; -use rustc_ast::{ast, attr, ptr}; +use rustc_ast::{ast, attr}; use rustc_errors::Diag; use rustc_parse::parser::Parser as RawParser; use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; @@ -102,7 +102,7 @@ impl<'a> Parser<'a> { psess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { + ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span))); diff --git a/src/patterns.rs b/src/patterns.rs index cb3879f4be8..d212ecf392a 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,5 +1,4 @@ use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax}; -use rustc_ast::ptr; use rustc_span::{BytePos, Span}; use crate::comment::{FindUncommented, combine_strs_with_missing_comments}; @@ -77,7 +76,7 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool } pub(crate) struct RangeOperand<'a, T> { - pub operand: &'a Option>, + pub operand: &'a Option>, pub span: Span, } @@ -329,8 +328,8 @@ impl Rewrite for Pat { pub fn rewrite_range_pat( context: &RewriteContext<'_>, shape: Shape, - lhs: &Option>, - rhs: &Option>, + lhs: &Option>, + rhs: &Option>, end_kind: &rustc_span::source_map::Spanned, span: Span, ) -> RewriteResult { @@ -371,7 +370,7 @@ pub fn rewrite_range_pat( } fn rewrite_struct_pat( - qself: &Option>, + qself: &Option>, path: &ast::Path, fields: &[ast::PatField], ellipsis: bool, @@ -505,7 +504,7 @@ impl Rewrite for PatField { #[derive(Debug)] pub(crate) enum TuplePatField<'a> { - Pat(&'a ptr::P), + Pat(&'a Box), Dotdot(Span), } @@ -562,7 +561,7 @@ pub(crate) fn can_be_overflowed_pat( } fn rewrite_tuple_pat( - pats: &[ptr::P], + pats: &[Box], path_str: Option, span: Span, context: &RewriteContext<'_>, diff --git a/src/rewrite.rs b/src/rewrite.rs index 83020709797..f0accd62d1a 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -3,7 +3,6 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::ptr; use rustc_span::Span; use thiserror::Error; @@ -24,7 +23,7 @@ pub(crate) trait Rewrite { } } -impl Rewrite for ptr::P { +impl Rewrite for Box { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { (**self).rewrite(context, shape) } diff --git a/src/spanned.rs b/src/spanned.rs index ac132999b62..020651e2daa 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,6 +1,6 @@ use std::cmp::max; -use rustc_ast::{ast, ptr}; +use rustc_ast::ast; use rustc_span::{Span, source_map}; use crate::macros::MacroArg; @@ -12,7 +12,7 @@ pub(crate) trait Spanned { fn span(&self) -> Span; } -impl Spanned for ptr::P { +impl Spanned for Box { fn span(&self) -> Span { (**self).span() } diff --git a/src/types.rs b/src/types.rs index 9ee10d86270..5dce9a0c8d0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,7 +1,6 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability, Term}; -use rustc_ast::ptr; use rustc_span::{BytePos, Pos, Span, symbol::kw}; use tracing::debug; @@ -39,7 +38,7 @@ pub(crate) enum PathContext { pub(crate) fn rewrite_path( context: &RewriteContext<'_>, path_context: PathContext, - qself: &Option>, + qself: &Option>, path: &ast::Path, shape: Shape, ) -> RewriteResult { @@ -1340,7 +1339,7 @@ fn join_bounds_inner( } } -pub(crate) fn opaque_ty(ty: &Option>) -> Option<&ast::GenericBounds> { +pub(crate) fn opaque_ty(ty: &Option>) -> Option<&ast::GenericBounds> { ty.as_ref().and_then(|t| match &t.kind { ast::TyKind::ImplTrait(_, bounds) => Some(bounds), _ => None, diff --git a/src/utils.rs b/src/utils.rs index fcd475b1784..b9950e94d0c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,10 +1,10 @@ use std::borrow::Cow; +use rustc_ast::YieldKind; use rustc_ast::ast::{ self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility, VisibilityKind, }; -use rustc_ast::{YieldKind, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; @@ -149,8 +149,8 @@ pub(crate) fn format_extern(ext: ast::Extern, explicit_abi: bool) -> Cow<'static } #[inline] -// Transform `Vec>` into `Vec<&T>` -pub(crate) fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { +// Transform `Vec>` into `Vec<&T>` +pub(crate) fn ptr_vec_to_ref_vec(vec: &[Box]) -> Vec<&T> { vec.iter().map(|x| &**x).collect::>() } diff --git a/src/visitor.rs b/src/visitor.rs index f6a9a3f2cd1..23d07c930d9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -874,7 +874,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { !is_skip_attr(segments) } - fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P]) { + fn walk_mod_items(&mut self, items: &[Box]) { self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items)); } From c9ee26ffdfeb427ee88e2df41644feec3b9fd8a9 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 21 Jul 2025 20:05:16 -0500 Subject: [PATCH 26/35] Extract ast TraitImplHeader --- src/items.rs | 51 +++++++++++++++-------------------- tests/source/negative-impl.rs | 4 --- tests/target/negative-impl.rs | 8 ------ 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/items.rs b/src/items.rs index 57d4142ebe4..10df6f96702 100644 --- a/src/items.rs +++ b/src/items.rs @@ -958,20 +958,19 @@ fn format_impl_ref_and_type( offset: Indent, ) -> Option { let ast::Impl { - safety, - polarity, - defaultness, - constness, - ref generics, - of_trait: ref trait_ref, - ref self_ty, - .. - } = *iimpl; + generics, + of_trait, + self_ty, + items: _, + } = iimpl; let mut result = String::with_capacity(128); result.push_str(&format_visibility(context, &item.vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_safety(safety)); + + if let Some(of_trait) = of_trait.as_deref() { + result.push_str(format_defaultness(of_trait.defaultness)); + result.push_str(format_safety(of_trait.safety)); + } let shape = if context.config.style_edition() >= StyleEdition::Edition2024 { Shape::indented(offset + last_line_width(&result), context.config) @@ -984,28 +983,24 @@ fn format_impl_ref_and_type( }; let generics_str = rewrite_generics(context, "impl", generics, shape).ok()?; result.push_str(&generics_str); - result.push_str(format_constness_right(constness)); - let polarity_str = match polarity { - ast::ImplPolarity::Negative(_) => "!", - ast::ImplPolarity::Positive => "", - }; - - let polarity_overhead; let trait_ref_overhead; - if let Some(ref trait_ref) = *trait_ref { + if let Some(of_trait) = of_trait.as_deref() { + result.push_str(format_constness_right(of_trait.constness)); + let polarity_str = match of_trait.polarity { + ast::ImplPolarity::Negative(_) => "!", + ast::ImplPolarity::Positive => "", + }; let result_len = last_line_width(&result); result.push_str(&rewrite_trait_ref( context, - trait_ref, + &of_trait.trait_ref, offset, polarity_str, result_len, )?); - polarity_overhead = 0; // already written trait_ref_overhead = " for".len(); } else { - polarity_overhead = polarity_str.len(); trait_ref_overhead = 0; } @@ -1020,17 +1015,15 @@ fn format_impl_ref_and_type( } else { 0 }; - let used_space = - last_line_width(&result) + polarity_overhead + trait_ref_overhead + curly_brace_overhead; + let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; // 1 = space before the type. let budget = context.budget(used_space + 1); if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { if !self_ty_str.contains('\n') { - if trait_ref.is_some() { + if of_trait.is_some() { result.push_str(" for "); } else { result.push(' '); - result.push_str(polarity_str); } result.push_str(&self_ty_str); return Some(result); @@ -1042,12 +1035,10 @@ fn format_impl_ref_and_type( // Add indentation of one additional tab. let new_line_offset = offset.block_indent(context.config); result.push_str(&new_line_offset.to_string(context.config)); - if trait_ref.is_some() { + if of_trait.is_some() { result.push_str("for "); - } else { - result.push_str(polarity_str); } - let budget = context.budget(last_line_width(&result) + polarity_overhead); + let budget = context.budget(last_line_width(&result)); let type_offset = match context.config.indent_style() { IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, diff --git a/tests/source/negative-impl.rs b/tests/source/negative-impl.rs index da242d4f3dc..e8f9508e656 100644 --- a/tests/source/negative-impl.rs +++ b/tests/source/negative-impl.rs @@ -1,7 +1,3 @@ impl ! Display for JoinHandle { } -impl ! Box < JoinHandle > { } - impl ! std :: fmt :: Display for JoinHandle < T : std :: future :: Future + std :: marker :: Send + std :: marker :: Sync > { } - -impl ! JoinHandle < T : std :: future :: Future < Output > + std :: marker :: Send + std :: marker :: Sync + 'static > + 'static { } diff --git a/tests/target/negative-impl.rs b/tests/target/negative-impl.rs index 16ce7e26a99..bb53048dbc6 100644 --- a/tests/target/negative-impl.rs +++ b/tests/target/negative-impl.rs @@ -1,14 +1,6 @@ impl !Display for JoinHandle {} -impl !Box {} - impl !std::fmt::Display for JoinHandle { } - -impl - !JoinHandle + std::marker::Send + std::marker::Sync + 'static> - + 'static -{ -} From b63507db20c6801d00022bddf51afc91e1060a20 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 19 Aug 2025 15:06:48 +1000 Subject: [PATCH 27/35] Prevent impossible combinations in `ast::ModKind`. `ModKind::Loaded` has an `inline` field and a `had_parse_error` field. If the `inline` field is `Inline::Yes` then `had_parse_error` must be `Ok(())`. This commit moves the `had_parse_error` field into the `Inline::No` variant. This makes it impossible to create the nonsensical combination of `inline == Inline::Yes` and `had_parse_error = Err(_)`. --- src/items.rs | 2 +- src/modules.rs | 7 ++++--- src/visitor.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/items.rs b/src/items.rs index 10df6f96702..6555679c394 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3600,7 +3600,7 @@ pub(crate) fn rewrite_extern_crate( pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { !matches!( item.kind, - ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) + ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) ) } diff --git a/src/modules.rs b/src/modules.rs index 3bc656b64b3..af9feccb32e 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -316,11 +316,12 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.directory = directory; } match (sub_mod.ast_mod_kind, sub_mod.items) { - (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _, _))), _) => { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => { self.visit_mod_from_ast(items) } - (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _, _))), _) - | (_, Cow::Owned(items)) => self.visit_mod_outside_ast(items), + (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => { + self.visit_mod_outside_ast(items) + } (_, _) => Ok(()), } } diff --git a/src/visitor.rs b/src/visitor.rs index 23d07c930d9..a3acbb218ff 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -942,7 +942,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans, _) = mod_kind { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, ref spans) = mod_kind { let ast::ModSpans { inner_span, inject_use_span: _, From 366a08f08993d2642335149b00c8826720e50279 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 8 Aug 2025 16:31:53 -0500 Subject: [PATCH 28/35] test(rustfmt): Verify frontmatter is preserved This is to prove that the frontmatter is preserved. The choices in tests is intended for showing the different parts of the proposed Style Guide for frontmatters. --- tests/source/frontmatter_compact.rs | 8 ++++++++ tests/source/frontmatter_escaped.rs | 13 +++++++++++++ tests/source/frontmatter_spaced.rs | 16 ++++++++++++++++ tests/target/frontmatter_compact.rs | 8 ++++++++ tests/target/frontmatter_escaped.rs | 13 +++++++++++++ tests/target/frontmatter_spaced.rs | 16 ++++++++++++++++ 6 files changed, 74 insertions(+) create mode 100644 tests/source/frontmatter_compact.rs create mode 100644 tests/source/frontmatter_escaped.rs create mode 100644 tests/source/frontmatter_spaced.rs create mode 100644 tests/target/frontmatter_compact.rs create mode 100644 tests/target/frontmatter_escaped.rs create mode 100644 tests/target/frontmatter_spaced.rs diff --git a/tests/source/frontmatter_compact.rs b/tests/source/frontmatter_compact.rs new file mode 100644 index 00000000000..21d4c6f4b61 --- /dev/null +++ b/tests/source/frontmatter_compact.rs @@ -0,0 +1,8 @@ +#!/usr/bin/env cargo +---identifier +[dependencies] +regex = "1" +--- +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/source/frontmatter_escaped.rs b/tests/source/frontmatter_escaped.rs new file mode 100644 index 00000000000..0d026377566 --- /dev/null +++ b/tests/source/frontmatter_escaped.rs @@ -0,0 +1,13 @@ +#!/usr/bin/env cargo +------------ +package.description = """ +Header +----- + +Body +""" +------------ + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/source/frontmatter_spaced.rs b/tests/source/frontmatter_spaced.rs new file mode 100644 index 00000000000..ee0bb81705c --- /dev/null +++ b/tests/source/frontmatter_spaced.rs @@ -0,0 +1,16 @@ +#!/usr/bin/env cargo + + +--- identifier +[dependencies] +regex = "1" + +--- + + + + + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/target/frontmatter_compact.rs b/tests/target/frontmatter_compact.rs new file mode 100644 index 00000000000..21d4c6f4b61 --- /dev/null +++ b/tests/target/frontmatter_compact.rs @@ -0,0 +1,8 @@ +#!/usr/bin/env cargo +---identifier +[dependencies] +regex = "1" +--- +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/target/frontmatter_escaped.rs b/tests/target/frontmatter_escaped.rs new file mode 100644 index 00000000000..0d026377566 --- /dev/null +++ b/tests/target/frontmatter_escaped.rs @@ -0,0 +1,13 @@ +#!/usr/bin/env cargo +------------ +package.description = """ +Header +----- + +Body +""" +------------ + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/target/frontmatter_spaced.rs b/tests/target/frontmatter_spaced.rs new file mode 100644 index 00000000000..ee0bb81705c --- /dev/null +++ b/tests/target/frontmatter_spaced.rs @@ -0,0 +1,16 @@ +#!/usr/bin/env cargo + + +--- identifier +[dependencies] +regex = "1" + +--- + + + + + +#![feature(frontmatter)] + +fn main() {} From 671c0c9a9ad785e56a68f8d3f4c47997d096f80d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 21 Aug 2025 21:51:20 +1000 Subject: [PATCH 29/35] Remove `dirs-sys-0.4.1` dependency. By updating rustfmt to use `dirs-6.0.0`. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e497b792342..6392ffbe409 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ cargo_metadata = "0.18" clap = { version = "4.4.2", features = ["derive"] } clap-cargo = "0.12.0" diff = "0.1" -dirs = "5.0" +dirs = "6.0" getopts = "0.2" ignore = "0.4" itertools = "0.12" From 2890913f4e5fbe0055ede7064ec9d6ff78294bf2 Mon Sep 17 00:00:00 2001 From: Valdemar Erk Date: Sat, 23 Aug 2025 11:37:53 +0200 Subject: [PATCH 30/35] add span to struct pattern rest (..) --- src/patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns.rs b/src/patterns.rs index d212ecf392a..848bd0766e7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -303,7 +303,7 @@ impl Rewrite for Pat { qself, path, fields, - rest == ast::PatFieldsRest::Rest, + matches!(rest, ast::PatFieldsRest::Rest(_)), self.span, context, shape, From 086aa840db2649fa86a4496dc5d15467fb588cf3 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Mon, 1 Sep 2025 08:55:25 -0400 Subject: [PATCH 31/35] fix a constness ordering bug in rustfmt Normally, changes to rustfmt go into the separate repo. But, in this case, the bug is introduced in a local change and therefore isn't present in the rustfmt repo. --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index 6555679c394..75e468b3525 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1175,8 +1175,8 @@ pub(crate) fn format_trait( let mut result = String::with_capacity(128); let header = format!( "{}{}{}{}trait ", - format_constness(constness), format_visibility(context, &item.vis), + format_constness(constness), format_safety(safety), format_auto(is_auto), ); From 288b931c202adfc483756333bd219aa5bd9beeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 8 Sep 2025 19:25:22 +0200 Subject: [PATCH 32/35] Strip frontmatter in fewer places --- src/parse/parser.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 2ec8769c45f..63c6c8c99d0 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::{ast, attr}; use rustc_errors::Diag; +use rustc_parse::lexer::StripTokens; use rustc_parse::parser::Parser as RawParser; use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_span::{Span, sym}; @@ -64,11 +65,14 @@ impl<'a> ParserBuilder<'a> { input: Input, ) -> Result, Vec>> { match input { - Input::File(ref file) => new_parser_from_file(psess, file, None), + Input::File(ref file) => { + new_parser_from_file(psess, file, StripTokens::ShebangAndFrontmatter, None) + } Input::Text(text) => new_parser_from_source_str( psess, rustc_span::FileName::Custom("stdin".to_owned()), text, + StripTokens::ShebangAndFrontmatter, ), } } @@ -104,8 +108,12 @@ impl<'a> Parser<'a> { span: Span, ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { - let mut parser = - unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span))); + let mut parser = unwrap_or_emit_fatal(new_parser_from_file( + psess.inner(), + path, + StripTokens::ShebangAndFrontmatter, + Some(span), + )); match parser.parse_mod(exp!(Eof)) { Ok((a, i, spans)) => Some((a, i, spans.inner_span)), Err(e) => { From f30038006f6dfcc99a875c14552c56904e875e02 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 1 Aug 2025 21:55:11 +0300 Subject: [PATCH 33/35] resolve: Do not finalize shadowed bindings I.e. do not mark them as used, or non-speculative loaded, or similar. Previously they were sometimes finalized during early resolution, causing issues like https://github.com/rust-lang/rust/pull/144793#issuecomment-3168108005. --- src/config/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 6b63108c037..525953bf445 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -516,7 +516,6 @@ mod test { #[allow(dead_code)] mod mock { use super::super::*; - use crate::config_option_with_style_edition_default; use rustfmt_config_proc_macro::config_type; #[config_type] From 08586bba8e66b73280d16739bb8f80a14a35e081 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 8 Oct 2025 19:24:54 +0800 Subject: [PATCH 34/35] chore: bump rustfmt toolchain to nightly-2025-10-07 Bumping the toolchain version as part of a git subtree push. current toolchain (nightly-2025-04-02): - 1.88.0-nightly (e2014e876 2025-04-01) latest toolchain (nightly-2025-10-07): - 1.92.0-nightly (f6aa851db 2025-10-07) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 80851788276..97aa26d4e6c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-04-02" +channel = "nightly-2025-10-07" components = ["llvm-tools", "rustc-dev"] From af9a7c850903a890c749e2ca100c06edba0bd93f Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 8 Oct 2025 20:50:49 +0800 Subject: [PATCH 35/35] fix: non-trivial merge conflicts and broken test headers --- Cargo.lock | 100 ++++++++++++++++++++++------ src/closures.rs | 2 +- src/modules.rs | 2 +- src/parse/macros/cfg_match.rs | 10 ++- tests/source/issue-6202/long_pat.rs | 9 +-- tests/target/issue-6202/long_pat.rs | 7 +- 6 files changed, 96 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3fc87feca4..070e6106f78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -56,7 +56,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -66,7 +66,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -87,6 +87,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + [[package]] name = "bstr" version = "0.2.17" @@ -131,7 +137,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.40", ] [[package]] @@ -214,9 +220,9 @@ checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] @@ -233,14 +239,14 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users", - "windows-sys", + "redox_users 0.5.2", + "windows-sys 0.61.2", ] [[package]] @@ -250,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.3", "winapi", ] @@ -366,6 +372,16 @@ version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.9.4", + "libc", +] + [[package]] name = "log" version = "0.4.16" @@ -426,9 +442,9 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -448,7 +464,7 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -459,7 +475,18 @@ checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", - "thiserror", + "thiserror 1.0.40", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom", + "libredox", + "thiserror 2.0.17", ] [[package]] @@ -518,7 +545,7 @@ dependencies = [ "serde", "serde_json", "term", - "thiserror", + "thiserror 1.0.40", "toml", "tracing", "tracing-subscriber", @@ -620,9 +647,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.48" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -646,7 +673,16 @@ version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.40", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", ] [[package]] @@ -660,6 +696,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -837,6 +884,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.48.0" @@ -846,6 +899,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.48.0" diff --git a/src/closures.rs b/src/closures.rs index bd8853437f7..cbf3ff6a655 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,4 +1,4 @@ -use rustc_ast::{Label, ast, ptr}; +use rustc_ast::{Label, ast}; use rustc_span::Span; use thin_vec::thin_vec; use tracing::debug; diff --git a/src/modules.rs b/src/modules.rs index 69066308acb..b1d6394875b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -198,7 +198,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { } if is_cfg_match(&item) { - self.visit_cfg_match(Cow::Owned(item.into_inner()))?; + self.visit_cfg_match(Cow::Owned(*item))?; continue; } diff --git a/src/parse/macros/cfg_match.rs b/src/parse/macros/cfg_match.rs index 87071db2749..388217af004 100644 --- a/src/parse/macros/cfg_match.rs +++ b/src/parse/macros/cfg_match.rs @@ -1,7 +1,7 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::ast; -use rustc_ast::token::{Delimiter, TokenKind}; +use rustc_ast::token::TokenKind; use rustc_parse::exp; use rustc_parse::parser::ForceCollect; @@ -26,7 +26,7 @@ fn parse_cfg_match_inner<'a>( let ts = mac.args.tokens.clone(); let mut parser = build_stream_parser(psess.inner(), ts); - if parser.token == TokenKind::OpenDelim(Delimiter::Brace) { + if parser.token == TokenKind::OpenBrace { return Err("Expression position cfg_match! not yet supported"); } @@ -48,11 +48,9 @@ fn parse_cfg_match_inner<'a>( return Err("Expected an opening brace"); } - while parser.token != TokenKind::CloseDelim(Delimiter::Brace) - && parser.token.kind != TokenKind::Eof - { + while parser.token != TokenKind::CloseBrace && parser.token.kind != TokenKind::Eof { let item = match parser.parse_item(ForceCollect::No) { - Ok(Some(item_ptr)) => item_ptr.into_inner(), + Ok(Some(item)) => *item, Ok(None) => continue, Err(err) => { err.cancel(); diff --git a/tests/source/issue-6202/long_pat.rs b/tests/source/issue-6202/long_pat.rs index a7f47f32cb2..37ce5dfb51b 100644 --- a/tests/source/issue-6202/long_pat.rs +++ b/tests/source/issue-6202/long_pat.rs @@ -1,6 +1,7 @@ -// max_width = 120 -// error_on_line_overflow = true -// style_edition = "2027" +// rustfmt-max_width: 120 +// rustfmt-error_on_line_overflow: true +// rustfmt-edition: 2024 +// rustfmt-style_edition: 2027 impl EarlyLintPass for NeedlessContinue { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { @@ -11,4 +12,4 @@ impl EarlyLintPass for NeedlessContinue { check_final_block_stmt(cx, body, label, expr.span.ctxt()); } } -} \ No newline at end of file +} diff --git a/tests/target/issue-6202/long_pat.rs b/tests/target/issue-6202/long_pat.rs index fef118a9da2..9e4accb29df 100644 --- a/tests/target/issue-6202/long_pat.rs +++ b/tests/target/issue-6202/long_pat.rs @@ -1,6 +1,7 @@ -// max_width = 120 -// error_on_line_overflow = true -// style_edition = "2027" +// rustfmt-max_width: 120 +// rustfmt-error_on_line_overflow: true +// rustfmt-edition: 2024 +// rustfmt-style_edition: 2027 impl EarlyLintPass for NeedlessContinue { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {