Skip to content

Commit

Permalink
Auto merge of rust-lang#114802 - chenyukang:yukang-fix-114979-bad-par…
Browse files Browse the repository at this point in the history
…ens-dyn, r=estebank

Fix bad suggestion when wrong parentheses around a dyn trait

Fixes rust-lang#114797
  • Loading branch information
bors committed Aug 17, 2023
2 parents 4a0402c + ddcd7ca commit 0768872
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 28 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ parse_inclusive_range_no_end = inclusive range with no end
.suggestion_open_range = use `..` instead
.note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
.suggestion = remove the parentheses
parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds
parse_incorrect_parens_trait_bounds_sugg = fix the parentheses
parse_incorrect_semicolon =
expected item, found `;`
Expand Down
19 changes: 11 additions & 8 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2636,21 +2636,24 @@ pub(crate) struct MissingPlusBounds {
}

#[derive(Diagnostic)]
#[diag(parse_incorrect_braces_trait_bounds)]
pub(crate) struct IncorrectBracesTraitBounds {
#[diag(parse_incorrect_parens_trait_bounds)]
pub(crate) struct IncorrectParensTraitBounds {
#[primary_span]
pub span: Vec<Span>,
#[subdiagnostic]
pub sugg: IncorrectBracesTraitBoundsSugg,
pub sugg: IncorrectParensTraitBoundsSugg,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct IncorrectBracesTraitBoundsSugg {
#[multipart_suggestion(
parse_incorrect_parens_trait_bounds_sugg,
applicability = "machine-applicable"
)]
pub(crate) struct IncorrectParensTraitBoundsSugg {
#[suggestion_part(code = " ")]
pub l: Span,
#[suggestion_part(code = "")]
pub r: Span,
pub wrong_span: Span,
#[suggestion_part(code = "(")]
pub new_span: Span,
}

#[derive(Diagnostic)]
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ impl<'a> Parser<'a> {
/// ```
fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
let lo = self.token.span;
let leading_token = self.prev_token.clone();
let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
let inner_lo = self.token.span;

Expand All @@ -722,7 +723,7 @@ impl<'a> Parser<'a> {
self.error_lt_bound_with_modifiers(modifiers);
self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
} else {
self.parse_generic_ty_bound(lo, has_parens, modifiers)?
self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)?
};

Ok(bound)
Expand Down Expand Up @@ -827,6 +828,7 @@ impl<'a> Parser<'a> {
lo: Span,
has_parens: bool,
modifiers: BoundModifiers,
leading_token: &Token,
) -> PResult<'a, GenericBound> {
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
let mut path = if self.token.is_keyword(kw::Fn)
Expand Down Expand Up @@ -873,18 +875,18 @@ impl<'a> Parser<'a> {
}

if has_parens {
if self.token.is_like_plus() {
// Someone has written something like `&dyn (Trait + Other)`. The correct code
// would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
// span to suggest that. When written as `&dyn Trait + Other`, an appropriate
// suggestion is given.
// Someone has written something like `&dyn (Trait + Other)`. The correct code
// would be `&(dyn Trait + Other)`
if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
let bounds = vec![];
self.parse_remaining_bounds(bounds, true)?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let sp = vec![lo, self.prev_token.span];
self.sess.emit_err(errors::IncorrectBracesTraitBounds {
span: sp,
sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
self.sess.emit_err(errors::IncorrectParensTraitBounds {
span: vec![lo, self.prev_token.span],
sugg: errors::IncorrectParensTraitBoundsSugg {
wrong_span: leading_token.span.shrink_to_hi().to(lo),
new_span: leading_token.span.shrink_to_lo(),
},
});
} else {
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/parser/trait-object-delimiters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
//~^ ERROR only auto traits can be used as additional traits in a trait object

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

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

fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/parser/trait-object-delimiters.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ error: ambiguous `+` in a type
LL | fn foo1(_: &dyn Drop + AsRef<str>) {}
| ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef<str>)`

error: incorrect braces around trait bounds
error: incorrect parentheses around trait bounds
--> $DIR/trait-object-delimiters.rs:6:17
|
LL | fn foo2(_: &dyn (Drop + AsRef<str>)) {}
| ^ ^
|
help: remove the parentheses
help: fix the parentheses
|
LL - fn foo2(_: &dyn (Drop + AsRef<str>)) {}
LL + fn foo2(_: &dyn Drop + AsRef<str>) {}
LL + fn foo2(_: &(dyn Drop + AsRef<str>)) {}
|

error: incorrect braces around trait bounds
error: incorrect parentheses around trait bounds
--> $DIR/trait-object-delimiters.rs:8:25
|
LL | fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
| ^ ^
|
help: remove the parentheses
help: fix the parentheses
|
LL - fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
LL + fn foo2_no_space(_: &dyn Drop + AsRef<str>) {}
LL + fn foo2_no_space(_: &(dyn Drop + AsRef<str>)) {}
|

error: expected parameter name, found `{`
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//run-rustfix
#![allow(dead_code)]

trait Trait {}

fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
//~^ ERROR incorrect parentheses around trait bounds
ptr as _
}

fn foo2(_: &(dyn Trait + Send)) {}
//~^ ERROR incorrect parentheses around trait bounds

fn foo3(_: &(dyn Trait + Send)) {}
//~^ ERROR incorrect parentheses around trait bounds

fn main() {}
17 changes: 17 additions & 0 deletions tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//run-rustfix
#![allow(dead_code)]

trait Trait {}

fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
//~^ ERROR incorrect parentheses around trait bounds
ptr as _
}

fn foo2(_: &dyn (Trait + Send)) {}
//~^ ERROR incorrect parentheses around trait bounds

fn foo3(_: &dyn(Trait + Send)) {}
//~^ ERROR incorrect parentheses around trait bounds

fn main() {}
38 changes: 38 additions & 0 deletions tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
error: incorrect parentheses around trait bounds
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:49
|
LL | fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
| ^ ^
|
help: fix the parentheses
|
LL - fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
LL + fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
|

error: incorrect parentheses around trait bounds
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:11:17
|
LL | fn foo2(_: &dyn (Trait + Send)) {}
| ^ ^
|
help: fix the parentheses
|
LL - fn foo2(_: &dyn (Trait + Send)) {}
LL + fn foo2(_: &(dyn Trait + Send)) {}
|

error: incorrect parentheses around trait bounds
--> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:14:16
|
LL | fn foo3(_: &dyn(Trait + Send)) {}
| ^ ^
|
help: fix the parentheses
|
LL - fn foo3(_: &dyn(Trait + Send)) {}
LL + fn foo3(_: &(dyn Trait + Send)) {}
|

error: aborting due to 3 previous errors

0 comments on commit 0768872

Please sign in to comment.