Auto merge of #114802 - chenyukang:yukang-fix-114979-bad-parens-dyn, r=estebank

Fix bad suggestion when wrong parentheses around a dyn trait

Fixes #114797
This commit is contained in:
bors 2023-08-17 17:54:50 +00:00
commit 0768872680
8 changed files with 105 additions and 28 deletions

View file

@ -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 `;`

View file

@ -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)]

View file

@ -714,6 +714,7 @@ fn can_begin_bound(&mut self) -> bool {
/// ```
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;
@ -722,7 +723,7 @@ fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
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)
@ -827,6 +828,7 @@ fn parse_generic_ty_bound(
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)
@ -873,18 +875,18 @@ fn parse_generic_ty_bound(
}
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))?;

View file

@ -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 `{`

View file

@ -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 `{`

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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