From cb66c855559bb175013cc076f9533ac4985fe702 Mon Sep 17 00:00:00 2001 From: "Andrew V. Teylu" Date: Fri, 6 Mar 2026 10:08:22 +0000 Subject: [PATCH] Preserve parentheses around Fn trait bounds in pretty printer The AST pretty printer was dropping parentheses around `Fn` trait bounds in `dyn`/`impl` types when additional `+` bounds were present. For example: dyn (FnMut(&mut T) -> &mut dyn ResourceLimiter) + Send + Sync was pretty-printed as: dyn FnMut(&mut T) -> &mut dyn ResourceLimiter + Send + Sync Without parens, `+ Send + Sync` binds to the inner `dyn ResourceLimiter` instead of the outer type, producing invalid Rust. The parser already tracks parentheses via `PolyTraitRef.parens`, but `print_poly_trait_ref` never checked this field. This adds `popen()` and `pclose()` calls when `parens == Parens::Yes`. Signed-off-by: Andrew V. Teylu --- compiler/rustc_ast_pretty/src/pprust/state.rs | 8 +++++++- tests/pretty/paren-trait-bound.rs | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/pretty/paren-trait-bound.rs diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 1ca071560618..c85d6f454321 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1415,6 +1415,9 @@ fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) } fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) { + if let ast::Parens::Yes = t.parens { + self.popen(); + } self.print_formal_generic_params(&t.bound_generic_params); let ast::TraitBoundModifiers { constness, asyncness, polarity } = t.modifiers; @@ -1437,7 +1440,10 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) { } } - self.print_trait_ref(&t.trait_ref) + self.print_trait_ref(&t.trait_ref); + if let ast::Parens::Yes = t.parens { + self.pclose(); + } } fn print_stmt(&mut self, st: &ast::Stmt) { diff --git a/tests/pretty/paren-trait-bound.rs b/tests/pretty/paren-trait-bound.rs new file mode 100644 index 000000000000..98e75308abfe --- /dev/null +++ b/tests/pretty/paren-trait-bound.rs @@ -0,0 +1,11 @@ +//@ pp-exact + +trait Dummy {} + +// Without parens, `+ Send` would bind to `dyn Dummy` instead of the outer `dyn`. +fn f1(_: Box Box) + Send>) {} + +// Without parens, `+ Send + Sync` would bind to `dyn Dummy` instead of the outer `impl`. +fn f2(_: impl (FnMut(&mut u8) -> &mut dyn Dummy) + Send + Sync) {} + +fn main() {}