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 <andrew.teylu@vector.com>
This commit is contained in:
Andrew V. Teylu
2026-03-06 10:08:22 +00:00
parent f824853889
commit cb66c85555
2 changed files with 18 additions and 1 deletions
@@ -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) {
+11
View File
@@ -0,0 +1,11 @@
//@ pp-exact
trait Dummy {}
// Without parens, `+ Send` would bind to `dyn Dummy` instead of the outer `dyn`.
fn f1(_: Box<dyn (Fn() -> Box<dyn Dummy>) + 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() {}