Skip to content

Commit 2a24db9

Browse files
committed
Move dyn parser-disambiguation from ty::Dynamic to the using arms
Wrap multi-bound `impl`/`dyn` at the positions where the parser is ambiguous: `&T`, `*const T`, `*mut T`, and the function-pointer / `Fn(..) -> T` return slot. The trait method covering this is renamed to `add_disambiguating_parens` since it now applies to both prefix and return positions; `inner_needs_disambiguating_parens` for `Dynamic` counts the printable region alongside the trait predicates that the self-wrap used to handle. Non-prefix positions where the parser does not need parens (`Box<dyn A + 'a>`, `[dyn A + 'a; N]`, top-level dyn) drop them. The bulk of the touched `.stderr` baselines reflect this cleanup; inline `//~ ERROR` annotations are adjusted to match.
1 parent 1853100 commit 2a24db9

141 files changed

Lines changed: 486 additions & 489 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
353353
fn should_print_optional_region(&self, region: ty::Region<'tcx>) -> bool;
354354

355355
/// Whether `pretty_print_type` should wrap a multi-bound `impl` / `dyn`
356-
/// inner in parens after a prefix type constructor (`&`, `&mut`, `*const`,
357-
/// `*mut`), so the output is `&(impl A + B)` rather than the parser-
358-
/// ambiguous `&impl A + B`. Byte-stable printers (mangling, `type_name`)
359-
/// override this to `false`.
360-
fn add_disambiguating_parens_in_prefix_position(&self) -> bool {
356+
/// inner in parens at positions where the bare form would be parser-
357+
/// ambiguous: after a prefix type constructor (`&`, `&mut`, `*const`,
358+
/// `*mut`) where `&T + B` parses as `(&T) + B`, and in the function-
359+
/// pointer / `Fn(..) -> T` return position where `-> T + B` parses as
360+
/// the outer signature picking up an extra bound. Byte-stable printers
361+
/// (mangling, etc.) override this to `false`.
362+
fn add_disambiguating_parens(&self) -> bool {
361363
true
362364
}
363365

@@ -817,16 +819,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
817819
}
818820
ty::Adt(def, args) => self.print_def_path(def.did(), args)?,
819821
ty::Dynamic(data, r) => {
820-
let print_r = self.should_print_optional_region(r);
821-
if print_r {
822-
write!(self, "(")?;
823-
}
824822
write!(self, "dyn ")?;
825823
data.print(self)?;
826-
if print_r {
824+
if self.should_print_optional_region(r) {
827825
write!(self, " + ")?;
828826
r.print(self)?;
829-
write!(self, ")")?;
830827
}
831828
}
832829
ty::Foreign(def_id) => self.print_def_path(def_id, &[])?,
@@ -1100,7 +1097,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11001097
/// print with a top-level `+`. Without the wrap, `&impl A + B` parses as
11011098
/// the ambiguous `(&impl A) + B`.
11021099
fn inner_needs_disambiguating_parens(&self, ty: Ty<'tcx>) -> bool {
1103-
if !self.add_disambiguating_parens_in_prefix_position() || self.should_print_verbose() {
1100+
if !self.add_disambiguating_parens() || self.should_print_verbose() {
11041101
return false;
11051102
}
11061103
match ty.kind() {
@@ -1114,24 +1111,21 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11141111
self.opaque_has_multiple_bounds(*def_id)
11151112
}
11161113
ty::Dynamic(predicates, region) => {
1117-
if self.should_print_optional_region(*region) {
1118-
// `ty::Dynamic` self-wraps when it has an explicit region.
1119-
false
1120-
} else {
1121-
// Projections inline into the principal as `<Item = X>`;
1122-
// only principal/auto traits produce a top-level `+`.
1123-
predicates
1124-
.iter()
1125-
.filter(|pred| {
1126-
matches!(
1127-
pred.skip_binder(),
1128-
ty::ExistentialPredicate::Trait(_)
1129-
| ty::ExistentialPredicate::AutoTrait(_)
1130-
)
1131-
})
1132-
.count()
1133-
> 1
1134-
}
1114+
// Projections inline into the principal as `<Item = X>`;
1115+
// only principal/auto traits produce a top-level `+`. An
1116+
// explicit (printable) region adds one more `+`-joined part.
1117+
let trait_count = predicates
1118+
.iter()
1119+
.filter(|pred| {
1120+
matches!(
1121+
pred.skip_binder(),
1122+
ty::ExistentialPredicate::Trait(_)
1123+
| ty::ExistentialPredicate::AutoTrait(_)
1124+
)
1125+
})
1126+
.count();
1127+
let region_count = usize::from(self.should_print_optional_region(*region));
1128+
trait_count + region_count > 1
11351129
}
11361130
_ => false,
11371131
}
@@ -1150,7 +1144,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
11501144
// Mirror `pretty_print_opaque_impl_type`'s sized-bound handling:
11511145
// positive `Sized` and `MetaSized` are absorbed into the synthetic
11521146
// suffix below; negative `Sized` (`?Sized`) falls through and is
1153-
// printed inline. Only clause *kinds* are inspected here, so the
1147+
// printed inline. We only ever look at clause *kinds* here, so the
11541148
// identity-instantiated bounds carry all the information we need.
11551149
let mut trait_emits = 0usize;
11561150
let mut lifetimes_count = 0usize;
@@ -1669,7 +1663,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
16691663
write!(self, ")")?;
16701664
if !output.is_unit() {
16711665
write!(self, " -> ")?;
1672-
output.print(self)?;
1666+
// `Fn(..) -> X + B` parses as if `+ B` extended the outer signature,
1667+
// so wrap if `X` would print with `+`-joined bounds. Same machinery
1668+
// as the `&T`, `*const T`, `*mut T` prefix arms.
1669+
self.print_inner_with_disambiguating_parens(output)?;
16731670
}
16741671

16751672
Ok(())

compiler/rustc_symbol_mangling/src/legacy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ impl<'tcx> PrettyPrinter<'tcx> for LegacySymbolMangler<'tcx> {
479479

480480
// Mangled symbols are ABI-stable; don't pick up the default printer's
481481
// parser-disambiguating parens.
482-
fn add_disambiguating_parens_in_prefix_position(&self) -> bool {
482+
fn add_disambiguating_parens(&self) -> bool {
483483
false
484484
}
485485

src/tools/clippy/tests/ui/crashes/ice-3969.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | str: Sized;
77
= note: `-D trivial-bounds` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(trivial_bounds)]`
99

10-
error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
10+
error: trait bound for<'a> Dst<dyn A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
1111
--> tests/ui/crashes/ice-3969.rs:25:30
1212
|
1313
LL | for<'a> Dst<dyn A + 'a>: Sized,

tests/ui/abi/invalid-self-parameter-type-56806.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>`
1+
error[E0307]: invalid `self` parameter type: `Box<dyn Trait + 'static>`
22
--> $DIR/invalid-self-parameter-type-56806.rs:3:34
33
|
44
LL | fn dyn_instead_of_self(self: Box<dyn Trait>);

tests/ui/associated-types/issue-43924.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied
1+
error[E0277]: the trait bound `dyn ToString + 'static: Default` is not satisfied
22
--> $DIR/issue-43924.rs:8:45
33
|
44
LL | type Out: Default + ToString + ?Sized = dyn ToString;
5-
| ^^^^^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)`
5+
| ^^^^^^^^^^^^ the trait `Default` is not implemented for `dyn ToString + 'static`
66
|
77
note: required by a bound in `Foo::Out`
88
--> $DIR/issue-43924.rs:8:15
99
|
1010
LL | type Out: Default + ToString + ?Sized = dyn ToString;
1111
| ^^^^^^^ required by this bound in `Foo::Out`
1212

13-
error[E0599]: no associated function or constant named `default` found for trait object `(dyn ToString + 'static)` in the current scope
13+
error[E0599]: no associated function or constant named `default` found for trait object `dyn ToString + 'static` in the current scope
1414
--> $DIR/issue-43924.rs:15:39
1515
|
1616
LL | assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
17-
| ^^^^^^^ associated function or constant not found in `(dyn ToString + 'static)`
17+
| ^^^^^^^ associated function or constant not found in `dyn ToString + 'static`
1818

1919
error: aborting due to 2 previous errors
2020

tests/ui/associated-types/issue-59324.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ LL | pub trait Foo: NotFoo {
8383
| ^^^^^^^^^^^^^^^^^^^^^
8484
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
8585

86-
error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
86+
error[E0277]: the size for values of type `dyn ThriftService<(), AssocType = _> + 'static` cannot be known at compilation time
8787
--> $DIR/issue-59324.rs:24:29
8888
|
8989
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
9090
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
9191
|
92-
= help: the trait `Sized` is not implemented for `(dyn ThriftService<(), AssocType = _> + 'static)`
92+
= help: the trait `Sized` is not implemented for `dyn ThriftService<(), AssocType = _> + 'static`
9393
= help: unsized fn params are gated as an unstable feature
9494
help: you can use `impl Trait` as the argument type
9595
|

tests/ui/associated-types/projection-dyn-associated-type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ impl<T: ?Sized> Mirror for A {
2121
pub fn foo<'a>(
2222
x: &'a <dyn A + 'static as Mirror>::Assoc
2323
) -> &'a <dyn B + 'static as Mirror>::Assoc {
24-
//~^ ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277]
25-
//~| ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277]
24+
//~^ ERROR the trait bound `dyn B + 'static: Mirror` is not satisfied [E0277]
25+
//~| ERROR the trait bound `dyn B + 'static: Mirror` is not satisfied [E0277]
2626
static
2727
} //~ ERROR expected identifier, found `}`
2828

tests/ui/associated-types/projection-dyn-associated-type.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,23 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
2929
LL | impl<T: ?Sized> Mirror for A {
3030
| ^ unconstrained type parameter
3131

32-
error[E0277]: the trait bound `(dyn B + 'static): Mirror` is not satisfied
32+
error[E0277]: the trait bound `dyn B + 'static: Mirror` is not satisfied
3333
--> $DIR/projection-dyn-associated-type.rs:23:6
3434
|
3535
LL | ) -> &'a <dyn B + 'static as Mirror>::Assoc {
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `(dyn B + 'static)`
36+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `dyn B + 'static`
3737
|
3838
help: the trait `Mirror` is implemented for `dyn A`
3939
--> $DIR/projection-dyn-associated-type.rs:14:1
4040
|
4141
LL | impl<T: ?Sized> Mirror for A {
4242
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4343

44-
error[E0277]: the trait bound `(dyn B + 'static): Mirror` is not satisfied
44+
error[E0277]: the trait bound `dyn B + 'static: Mirror` is not satisfied
4545
--> $DIR/projection-dyn-associated-type.rs:23:6
4646
|
4747
LL | ) -> &'a <dyn B + 'static as Mirror>::Assoc {
48-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `(dyn B + 'static)`
48+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `dyn B + 'static`
4949
|
5050
help: the trait `Mirror` is implemented for `dyn A`
5151
--> $DIR/projection-dyn-associated-type.rs:14:1

tests/ui/async-await/async-closures/fn-exception.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn()` is not satisfied
1+
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<dyn Future<Output = ()> + 'static>> {unsafety}: AsyncFn()` is not satisfied
22
--> $DIR/fn-exception.rs:17:10
33
|
44
LL | test(unsafety);
5-
| ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
5+
| ---- ^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<dyn Future<Output = ()> + 'static>> {unsafety}`
66
| |
77
| required by a bound introduced by this call
88
|
@@ -12,11 +12,11 @@ note: required by a bound in `test`
1212
LL | fn test(f: impl AsyncFn()) {}
1313
| ^^^^^^^^^ required by this bound in `test`
1414

15-
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
15+
error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<dyn Future<Output = ()> + 'static>> {abi}: AsyncFn()` is not satisfied
1616
--> $DIR/fn-exception.rs:18:10
1717
|
1818
LL | test(abi);
19-
| ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
19+
| ---- ^^^ the trait `AsyncFn()` is not implemented for fn item `extern "C" fn() -> Pin<Box<dyn Future<Output = ()> + 'static>> {abi}`
2020
| |
2121
| required by a bound introduced by this call
2222
|

tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ LL | | yield_now().await;
1111
LL | | });
1212
| |______^ implementation of `Robot` is not general enough
1313
|
14-
= note: `Box<(dyn Robot<Id = u32> + Send + '0)>` must implement `Robot`, for any lifetime `'0`...
15-
= note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot<Id = u32> + Send + 'static)>`
14+
= note: `Box<dyn Robot<Id = u32> + Send + '0>` must implement `Robot`, for any lifetime `'0`...
15+
= note: ...but `Robot` is actually implemented for the type `Box<dyn Robot<Id = u32> + Send + 'static>`
1616

1717
error: aborting due to 1 previous error
1818

0 commit comments

Comments
 (0)