about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2024-06-19 15:37:31 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2024-06-19 19:12:00 +1000
commitaaa220e8757d1d2bb3a7b4742db9e289c8454dc2 (patch)
tree2eec7d6fe436be5faf45bfe15110d4039c780d0e
parent802779f77ddaac18865e5e52e01c5e4d122e9090 (diff)
downloadrust-aaa220e8757d1d2bb3a7b4742db9e289c8454dc2.tar.gz
rust-aaa220e8757d1d2bb3a7b4742db9e289c8454dc2.zip
Move `parse_or_use_outer_attributes` out of `parse_expr_prefix_range`.
This eliminates another `Option<AttrWrapper>` argument and changes one
obscure error message.
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs7
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs19
-rw-r--r--tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs4
-rw-r--r--tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr8
5 files changed, 25 insertions, 15 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index f678d11213c..efb9526eabc 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -133,6 +133,8 @@ parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_
 parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
     .suggestion = use `..=` instead
 
+parse_dot_dot_range_attribute = attributes are not allowed on range expressions starting with `..`
+
 parse_dotdotdot = unexpected token: `...`
     .suggest_exclusive_range = use `..` for an exclusive range
     .suggest_inclusive_range = or `..=` for an inclusive range
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 6c1fcbe06fc..f0ef1112f9e 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2989,3 +2989,10 @@ pub(crate) struct ExprRArrowCall {
     #[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_dot_dot_range_attribute)]
+pub(crate) struct DotDotRangeAttribute {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e96b97da9fd..ab3f8a5dbeb 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -152,10 +152,10 @@ impl<'a> Parser<'a> {
                 expr
             }
             LhsExpr::Unparsed { attrs } => {
+                let attrs = self.parse_or_use_outer_attributes(attrs)?;
                 if self.token.is_range_separator() {
                     return self.parse_expr_prefix_range(attrs);
                 } else {
-                    let attrs = self.parse_or_use_outer_attributes(attrs)?;
                     self.parse_expr_prefix(attrs)?
                 }
             }
@@ -499,7 +499,12 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
-    fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
+    fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
+        if !attrs.is_empty() {
+            let err = errors::DotDotRangeAttribute { span: self.token.span };
+            self.dcx().emit_err(err);
+        }
+
         // Check for deprecated `...` syntax.
         if self.token == token::DotDotDot {
             self.err_dotdotdot_syntax(self.token.span);
@@ -516,11 +521,7 @@ impl<'a> Parser<'a> {
             _ => RangeLimits::Closed,
         };
         let op = AssocOp::from_token(&self.token);
-        // FIXME: `parse_prefix_range_expr` is called when the current
-        // token is `DotDot`, `DotDotDot`, or `DotDotEq`. If we haven't already
-        // parsed attributes, then trying to parse them here will always fail.
-        // We should figure out how we want attributes on range expressions to work.
-        let attrs = self.parse_or_use_outer_attributes(attrs)?;
+        let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_for_expr(attrs, |this, attrs| {
             let lo = this.token.span;
             let maybe_lt = this.look_ahead(1, |t| t.clone());
@@ -871,10 +872,10 @@ impl<'a> Parser<'a> {
         let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
         let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
         let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
+        let attrs = self.parse_outer_attributes()?;
         let expr = if self.token.is_range_separator() {
-            self.parse_expr_prefix_range(None)
+            self.parse_expr_prefix_range(attrs)
         } else {
-            let attrs = self.parse_outer_attributes()?;
             self.parse_expr_prefix(attrs)
         }?;
         let hi = self.interpolated_or_expr_span(&expr);
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
index d1950087c4c..26761a1d254 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
@@ -28,9 +28,9 @@ fn main() {}
 #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
-//~^ ERROR expected expression, found `..`
+//~^ ERROR attributes are not allowed on range expressions starting with `..`
 #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
-//~^ ERROR expected expression, found `..`
+//~^ ERROR attributes are not allowed on range expressions starting with `..`
 #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
 //~^ ERROR an inner attribute is not permitted in this context
 #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
index e46c591080d..3593c5182ce 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
@@ -119,17 +119,17 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
    = note: outer attributes, like `#[test]`, annotate the item following them
 
-error: expected expression, found `..`
+error: attributes are not allowed on range expressions starting with `..`
   --> $DIR/attr-stmt-expr-attr-bad.rs:30:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
-   |                                        ^^ expected expression
+   |                                        ^^
 
-error: expected expression, found `..`
+error: attributes are not allowed on range expressions starting with `..`
   --> $DIR/attr-stmt-expr-attr-bad.rs:32:40
    |
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
-   |                                        ^^ expected expression
+   |                                        ^^
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:34:41