about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs42
-rw-r--r--tests/ui/impl-trait/precise-capturing/parenthesized.rs8
-rw-r--r--tests/ui/impl-trait/precise-capturing/parenthesized.stderr14
3 files changed, 48 insertions, 16 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 0d479731e73..b02eeeb93a8 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -849,8 +849,9 @@ impl<'a> Parser<'a> {
 
     fn parse_precise_capturing_args(
         &mut self,
-    ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
-        let lo = self.token.span;
+        lo: Span,
+        parens: ast::Parens,
+    ) -> PResult<'a, GenericBound> {
         self.expect_lt()?;
         let (args, _, _) = self.parse_seq_to_before_tokens(
             &[exp!(Gt)],
@@ -876,7 +877,22 @@ impl<'a> Parser<'a> {
             },
         )?;
         self.expect_gt()?;
-        Ok((args, lo.to(self.prev_token.span)))
+
+        if let ast::Parens::Yes = parens {
+            self.expect(exp!(CloseParen))?;
+            let hi = self.prev_token.span;
+            let mut diag = self
+                .dcx()
+                .struct_span_err(lo.to(hi), "precise capturing lists may not be parenthesized");
+            diag.multipart_suggestion(
+                "remove the parentheses",
+                vec![(lo, String::new()), (hi, String::new())],
+                Applicability::MachineApplicable,
+            );
+            diag.emit();
+        }
+
+        Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
     }
 
     /// Is a `dyn B0 + ... + Bn` type allowed here?
@@ -987,24 +1003,18 @@ impl<'a> Parser<'a> {
     /// BOUND = TY_BOUND | LT_BOUND
     /// ```
     fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
-        let lo = self.token.span;
         let leading_token = self.prev_token;
+        let lo = self.token.span;
+
         let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
 
-        let bound = if self.token.is_lifetime() {
-            self.parse_generic_lt_bound(lo, parens)?
+        if self.token.is_lifetime() {
+            self.parse_generic_lt_bound(lo, parens)
         } else if self.eat_keyword(exp!(Use)) {
-            // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of
-            // lifetimes and ident params (including SelfUpper). These are validated later
-            // for order, duplication, and whether they actually reference params.
-            let use_span = self.prev_token.span;
-            let (args, args_span) = self.parse_precise_capturing_args()?;
-            GenericBound::Use(args, use_span.to(args_span))
+            self.parse_precise_capturing_args(lo, parens)
         } else {
-            self.parse_generic_ty_bound(lo, parens, &leading_token)?
-        };
-
-        Ok(bound)
+            self.parse_generic_ty_bound(lo, parens, &leading_token)
+        }
     }
 
     /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
diff --git a/tests/ui/impl-trait/precise-capturing/parenthesized.rs b/tests/ui/impl-trait/precise-capturing/parenthesized.rs
new file mode 100644
index 00000000000..e3f80fc1d9f
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/parenthesized.rs
@@ -0,0 +1,8 @@
+// Ensure that we forbid parenthesized use-bounds. In the future we might want
+// to lift this restriction but for now they bear no use whatsoever.
+
+fn f() -> impl Sized + (use<>) {}
+//~^ ERROR precise capturing lists may not be parenthesized
+//~| HELP remove the parentheses
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/parenthesized.stderr b/tests/ui/impl-trait/precise-capturing/parenthesized.stderr
new file mode 100644
index 00000000000..c97fa9972ef
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/parenthesized.stderr
@@ -0,0 +1,14 @@
+error: precise capturing lists may not be parenthesized
+  --> $DIR/parenthesized.rs:4:24
+   |
+LL | fn f() -> impl Sized + (use<>) {}
+   |                        ^^^^^^^
+   |
+help: remove the parentheses
+   |
+LL - fn f() -> impl Sized + (use<>) {}
+LL + fn f() -> impl Sized + use<> {}
+   |
+
+error: aborting due to 1 previous error
+