about summary refs log tree commit diff
path: root/tests/ui/parser
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-19 13:58:21 +0000
committerbors <bors@rust-lang.org>2024-06-19 13:58:21 +0000
commit894f7a4ba6554d3797404bbf550d9919df060b97 (patch)
treec5bc9c152c3f53208a4bf9b093e5c49df499291f /tests/ui/parser
parent3186d17d56f9803b739a2c0aabd23aafd8791485 (diff)
parent64c2e9ed3bfb6d6e8f9463f90d4eefa736242b8e (diff)
Auto merge of #126678 - nnethercote:fix-duplicated-attrs-on-nt-expr, r=petrochenkov
Fix duplicated attributes on nonterminal expressions

This PR fixes a long-standing bug (#86055) whereby expression attributes can be duplicated when expanded through declarative macros.

First, consider how items are parsed in declarative macros:
```
Items:
- parse_nonterminal
  - parse_item(ForceCollect::Yes)
    - parse_item_
      - attrs = parse_outer_attributes
      - parse_item_common(attrs)
        - maybe_whole!
        - collect_tokens_trailing_token
```
The important thing is that the parsing of outer attributes is outside token collection, so the item's tokens don't include the attributes. This is how it's supposed to be.

Now consider how expression are parsed in declarative macros:
```
Exprs:
- parse_nonterminal
  - parse_expr_force_collect
    - collect_tokens_no_attrs
      - collect_tokens_trailing_token
        - parse_expr
          - parse_expr_res(None)
            - parse_expr_assoc_with
              - parse_expr_prefix
                - parse_or_use_outer_attributes
                - parse_expr_dot_or_call
```
The important thing is that the parsing of outer attributes is inside token collection, so the the expr's tokens do include the attributes, i.e. in `AttributesData::tokens`.

This PR fixes the bug by rearranging expression parsing to that outer attribute parsing happens outside of token collection. This requires a number of small refactorings because expression parsing is somewhat complicated. While doing so the PR makes the code a bit cleaner and simpler, by eliminating `parse_or_use_outer_attributes` and `Option<AttrWrapper>` arguments (in favour of the simpler `parse_outer_attributes` and `AttrWrapper` arguments), and simplifying `LhsExpr`.

r? `@petrochenkov`
Diffstat (limited to 'tests/ui/parser')
-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
2 files changed, 6 insertions, 6 deletions
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