about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs19
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs22
-rw-r--r--tests/ui/parser/trait-object-delimiters.rs4
-rw-r--r--tests/ui/parser/trait-object-delimiters.stderr12
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr38
8 files changed, 105 insertions, 28 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 6888127f36c..34cc0998c9b 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -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 `;`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 26f38c9156a..e0b1e3678e4 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -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)]
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 3bb50b05aa3..27b1e9c0f11 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -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;
 
@@ -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)
@@ -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)
@@ -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))?;
diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs
index c41cda18743..e9b13defe03 100644
--- a/tests/ui/parser/trait-object-delimiters.rs
+++ b/tests/ui/parser/trait-object-delimiters.rs
@@ -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 `{`
diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr
index ccce3a8053e..51954675093 100644
--- a/tests/ui/parser/trait-object-delimiters.stderr
+++ b/tests/ui/parser/trait-object-delimiters.stderr
@@ -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 `{`
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
new file mode 100644
index 00000000000..57387936a4c
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
@@ -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() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
new file mode 100644
index 00000000000..8a1939bcfe9
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
@@ -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() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
new file mode 100644
index 00000000000..2d1abe91a1e
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
@@ -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
+