Skip to content

Commit ddcd7ca

Browse files
committed
Fix bad suggestion when wrong parentheses around a dyn trait
1 parent fd9525a commit ddcd7ca

8 files changed

+105
-28
lines changed

Diff for: compiler/rustc_parse/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,8 @@ parse_inclusive_range_no_end = inclusive range with no end
310310
.suggestion_open_range = use `..` instead
311311
.note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
312312
313-
parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
314-
.suggestion = remove the parentheses
313+
parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds
314+
parse_incorrect_parens_trait_bounds_sugg = fix the parentheses
315315
316316
parse_incorrect_semicolon =
317317
expected item, found `;`

Diff for: compiler/rustc_parse/src/errors.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -2636,21 +2636,24 @@ pub(crate) struct MissingPlusBounds {
26362636
}
26372637

26382638
#[derive(Diagnostic)]
2639-
#[diag(parse_incorrect_braces_trait_bounds)]
2640-
pub(crate) struct IncorrectBracesTraitBounds {
2639+
#[diag(parse_incorrect_parens_trait_bounds)]
2640+
pub(crate) struct IncorrectParensTraitBounds {
26412641
#[primary_span]
26422642
pub span: Vec<Span>,
26432643
#[subdiagnostic]
2644-
pub sugg: IncorrectBracesTraitBoundsSugg,
2644+
pub sugg: IncorrectParensTraitBoundsSugg,
26452645
}
26462646

26472647
#[derive(Subdiagnostic)]
2648-
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
2649-
pub(crate) struct IncorrectBracesTraitBoundsSugg {
2648+
#[multipart_suggestion(
2649+
parse_incorrect_parens_trait_bounds_sugg,
2650+
applicability = "machine-applicable"
2651+
)]
2652+
pub(crate) struct IncorrectParensTraitBoundsSugg {
26502653
#[suggestion_part(code = " ")]
2651-
pub l: Span,
2652-
#[suggestion_part(code = "")]
2653-
pub r: Span,
2654+
pub wrong_span: Span,
2655+
#[suggestion_part(code = "(")]
2656+
pub new_span: Span,
26542657
}
26552658

26562659
#[derive(Diagnostic)]

Diff for: compiler/rustc_parse/src/parser/ty.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ impl<'a> Parser<'a> {
714714
/// ```
715715
fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
716716
let lo = self.token.span;
717+
let leading_token = self.prev_token.clone();
717718
let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
718719
let inner_lo = self.token.span;
719720

@@ -722,7 +723,7 @@ impl<'a> Parser<'a> {
722723
self.error_lt_bound_with_modifiers(modifiers);
723724
self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
724725
} else {
725-
self.parse_generic_ty_bound(lo, has_parens, modifiers)?
726+
self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)?
726727
};
727728

728729
Ok(bound)
@@ -827,6 +828,7 @@ impl<'a> Parser<'a> {
827828
lo: Span,
828829
has_parens: bool,
829830
modifiers: BoundModifiers,
831+
leading_token: &Token,
830832
) -> PResult<'a, GenericBound> {
831833
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
832834
let mut path = if self.token.is_keyword(kw::Fn)
@@ -873,18 +875,18 @@ impl<'a> Parser<'a> {
873875
}
874876

875877
if has_parens {
876-
if self.token.is_like_plus() {
877-
// Someone has written something like `&dyn (Trait + Other)`. The correct code
878-
// would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
879-
// span to suggest that. When written as `&dyn Trait + Other`, an appropriate
880-
// suggestion is given.
878+
// Someone has written something like `&dyn (Trait + Other)`. The correct code
879+
// would be `&(dyn Trait + Other)`
880+
if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
881881
let bounds = vec![];
882882
self.parse_remaining_bounds(bounds, true)?;
883883
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
884-
let sp = vec![lo, self.prev_token.span];
885-
self.sess.emit_err(errors::IncorrectBracesTraitBounds {
886-
span: sp,
887-
sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
884+
self.sess.emit_err(errors::IncorrectParensTraitBounds {
885+
span: vec![lo, self.prev_token.span],
886+
sugg: errors::IncorrectParensTraitBoundsSugg {
887+
wrong_span: leading_token.span.shrink_to_hi().to(lo),
888+
new_span: leading_token.span.shrink_to_lo(),
889+
},
888890
});
889891
} else {
890892
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;

Diff for: tests/ui/parser/trait-object-delimiters.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
44
//~^ ERROR only auto traits can be used as additional traits in a trait object
55

6-
fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
6+
fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
77

8-
fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
8+
fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
99

1010
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
1111
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`

Diff for: tests/ui/parser/trait-object-delimiters.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,28 @@ error: ambiguous `+` in a type
44
LL | fn foo1(_: &dyn Drop + AsRef<str>) {}
55
| ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef<str>)`
66

7-
error: incorrect braces around trait bounds
7+
error: incorrect parentheses around trait bounds
88
--> $DIR/trait-object-delimiters.rs:6:17
99
|
1010
LL | fn foo2(_: &dyn (Drop + AsRef<str>)) {}
1111
| ^ ^
1212
|
13-
help: remove the parentheses
13+
help: fix the parentheses
1414
|
1515
LL - fn foo2(_: &dyn (Drop + AsRef<str>)) {}
16-
LL + fn foo2(_: &dyn Drop + AsRef<str>) {}
16+
LL + fn foo2(_: &(dyn Drop + AsRef<str>)) {}
1717
|
1818

19-
error: incorrect braces around trait bounds
19+
error: incorrect parentheses around trait bounds
2020
--> $DIR/trait-object-delimiters.rs:8:25
2121
|
2222
LL | fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
2323
| ^ ^
2424
|
25-
help: remove the parentheses
25+
help: fix the parentheses
2626
|
2727
LL - fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
28-
LL + fn foo2_no_space(_: &dyn Drop + AsRef<str>) {}
28+
LL + fn foo2_no_space(_: &(dyn Drop + AsRef<str>)) {}
2929
|
3030

3131
error: expected parameter name, found `{`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//run-rustfix
2+
#![allow(dead_code)]
3+
4+
trait Trait {}
5+
6+
fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
7+
//~^ ERROR incorrect parentheses around trait bounds
8+
ptr as _
9+
}
10+
11+
fn foo2(_: &(dyn Trait + Send)) {}
12+
//~^ ERROR incorrect parentheses around trait bounds
13+
14+
fn foo3(_: &(dyn Trait + Send)) {}
15+
//~^ ERROR incorrect parentheses around trait bounds
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//run-rustfix
2+
#![allow(dead_code)]
3+
4+
trait Trait {}
5+
6+
fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
7+
//~^ ERROR incorrect parentheses around trait bounds
8+
ptr as _
9+
}
10+
11+
fn foo2(_: &dyn (Trait + Send)) {}
12+
//~^ ERROR incorrect parentheses around trait bounds
13+
14+
fn foo3(_: &dyn(Trait + Send)) {}
15+
//~^ ERROR incorrect parentheses around trait bounds
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: incorrect parentheses around trait bounds
2+
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:49
3+
|
4+
LL | fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
5+
| ^ ^
6+
|
7+
help: fix the parentheses
8+
|
9+
LL - fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
10+
LL + fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
11+
|
12+
13+
error: incorrect parentheses around trait bounds
14+
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:11:17
15+
|
16+
LL | fn foo2(_: &dyn (Trait + Send)) {}
17+
| ^ ^
18+
|
19+
help: fix the parentheses
20+
|
21+
LL - fn foo2(_: &dyn (Trait + Send)) {}
22+
LL + fn foo2(_: &(dyn Trait + Send)) {}
23+
|
24+
25+
error: incorrect parentheses around trait bounds
26+
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:14:16
27+
|
28+
LL | fn foo3(_: &dyn(Trait + Send)) {}
29+
| ^ ^
30+
|
31+
help: fix the parentheses
32+
|
33+
LL - fn foo3(_: &dyn(Trait + Send)) {}
34+
LL + fn foo3(_: &(dyn Trait + Send)) {}
35+
|
36+
37+
error: aborting due to 3 previous errors
38+

0 commit comments

Comments
 (0)