about summary refs log tree commit diff
path: root/crates/parser
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2021-03-17 18:20:32 +0100
committerJonas Schievink <jonasschievink@gmail.com>2021-03-17 18:28:27 +0100
commit022a0f061e887bd27f54c028f9a23018b8eb2b8b (patch)
tree6f1f7c1c7ba6300c87350946f0033d73c02f9546 /crates/parser
parent0a6471384529bd8861c628756695c52be4c6837f (diff)
downloadrust-022a0f061e887bd27f54c028f9a23018b8eb2b8b.tar.gz
rust-022a0f061e887bd27f54c028f9a23018b8eb2b8b.zip
Correctly parse attributes on fn parameters
Diffstat (limited to 'crates/parser')
-rw-r--r--crates/parser/src/grammar/params.rs29
1 files changed, 22 insertions, 7 deletions
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index e313f6fb7f1..9e2f02d4356 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -41,22 +41,32 @@ fn list_(p: &mut Parser, flavor: Flavor) {
         FnDef | FnTrait | FnPointer => (T!['('], T![')']),
     };
 
-    let m = p.start();
+    let list_marker = p.start();
     p.bump(bra);
 
+    let mut param_marker = None;
     if let FnDef = flavor {
         // test self_param_outer_attr
         // fn f(#[must_use] self) {}
         let m = p.start();
         attributes::outer_attrs(p);
-        opt_self_param(p, m);
+        match opt_self_param(p, m) {
+            Ok(()) => {}
+            Err(m) => param_marker = Some(m),
+        }
     }
 
     while !p.at(EOF) && !p.at(ket) {
         // test param_outer_arg
         // fn f(#[attr1] pat: Type) {}
-        let m = p.start();
-        attributes::outer_attrs(p);
+        let m = match param_marker.take() {
+            Some(m) => m,
+            None => {
+                let m = p.start();
+                attributes::outer_attrs(p);
+                m
+            }
+        };
 
         if !p.at_ts(PARAM_FIRST) {
             p.error("expected value parameter");
@@ -72,8 +82,12 @@ fn list_(p: &mut Parser, flavor: Flavor) {
         }
     }
 
+    if let Some(m) = param_marker {
+        m.abandon(p);
+    }
+
     p.expect(ket);
-    m.complete(p, PARAM_LIST);
+    list_marker.complete(p, PARAM_LIST);
 }
 
 const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
@@ -153,7 +167,7 @@ fn variadic_param(p: &mut Parser) -> bool {
 //     fn d(&'a mut self, x: i32) {}
 //     fn e(mut self) {}
 // }
-fn opt_self_param(p: &mut Parser, m: Marker) {
+fn opt_self_param(p: &mut Parser, m: Marker) -> Result<(), Marker> {
     if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
         p.eat(T![mut]);
         self_as_name(p);
@@ -176,7 +190,7 @@ fn opt_self_param(p: &mut Parser, m: Marker) {
                 | (T![&], LIFETIME_IDENT, T![self], _)
                 | (T![&], LIFETIME_IDENT, T![mut], T![self])
         ) {
-            return m.abandon(p);
+            return Err(m);
         }
         p.bump(T![&]);
         if p.at(LIFETIME_IDENT) {
@@ -189,6 +203,7 @@ fn opt_self_param(p: &mut Parser, m: Marker) {
     if !p.at(T![')']) {
         p.expect(T![,]);
     }
+    Ok(())
 }
 
 fn self_as_name(p: &mut Parser) {