From f2904674e8d0dbb6f7b02ae74aa81d930a0e8617 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 00:20:03 +0200
Subject: [PATCH 01/21] syntax: cleanup method parsing.

---
 src/libsyntax/parse/diagnostics.rs |   2 +-
 src/libsyntax/parse/parser/item.rs | 138 ++++++++++++++---------------
 2 files changed, 66 insertions(+), 74 deletions(-)

diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index ec5d00e0952d7..e8d7b7663ed52 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -1180,7 +1180,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> {
+    crate fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> {
         let token_str = self.this_token_descr();
         let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
         err.span_label(self.token.span, "expected `;` or `{`");
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 64c494416ff34..69fbb343ff3b6 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -7,7 +7,7 @@ use crate::ast::{
     Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
     UseTree, UseTreeKind, PathSegment,
     IsAuto, Constness, IsAsync, Unsafety, Defaultness,
-    Visibility, VisibilityKind, Mutability, FnDecl, FnHeader,
+    Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
     ForeignItem, ForeignItemKind,
     Ty, TyKind, Generics, GenericBounds, TraitRef,
     EnumDef, VariantData, StructField, AnonConst,
@@ -848,29 +848,38 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a method or a macro invocation in a trait impl.
-    fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
-                         -> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
+    fn parse_impl_method(
+        &mut self,
+        vis: &Visibility,
+        at_end: &mut bool
+    ) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
         // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
         if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
             // method macro
-            Ok((Ident::invalid(), vec![], Generics::default(),
-                ast::ImplItemKind::Macro(mac)))
+            Ok((Ident::invalid(), vec![], Generics::default(), ast::ImplItemKind::Macro(mac)))
         } else {
-            let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
-            let ident = self.parse_ident()?;
-            let mut generics = self.parse_generics()?;
-            let decl = self.parse_fn_decl_with_self(|_| true)?;
-            generics.where_clause = self.parse_where_clause()?;
+            let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
             *at_end = true;
             let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-            let header = ast::FnHeader { abi, unsafety, constness, asyncness };
-            Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(
-                ast::MethodSig { header, decl },
-                body
-            )))
+            Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
         }
     }
 
+    /// Parse the "signature", including the identifier, parameters, and generics
+    /// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
+    fn parse_method_sig(
+        &mut self,
+        is_name_required: impl Copy + Fn(&token::Token) -> bool,
+    ) -> PResult<'a, (Ident, MethodSig, Generics)> {
+        let header = self.parse_fn_front_matter()?;
+        let ident = self.parse_ident()?;
+        let mut generics = self.parse_generics()?;
+        let decl = self.parse_fn_decl_with_self(is_name_required)?;
+        let sig = MethodSig { header, decl };
+        generics.where_clause = self.parse_where_clause()?;
+        Ok((ident, sig, generics))
+    }
+
     /// Parses all the "front matter" for a `fn` declaration, up to
     /// and including the `fn` keyword:
     ///
@@ -879,14 +888,7 @@ impl<'a> Parser<'a> {
     /// - `const unsafe fn`
     /// - `extern fn`
     /// - etc.
-    fn parse_fn_front_matter(&mut self)
-        -> PResult<'a, (
-            Spanned<Constness>,
-            Unsafety,
-            Spanned<IsAsync>,
-            Abi
-        )>
-    {
+    fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
         let is_const_fn = self.eat_keyword(kw::Const);
         let const_span = self.prev_span;
         let asyncness = self.parse_asyncness();
@@ -911,7 +913,7 @@ impl<'a> Parser<'a> {
             // account for this.
             if !self.expect_one_of(&[], &[])? { unreachable!() }
         }
-        Ok((constness, unsafety, asyncness, abi))
+        Ok(FnHeader { constness, unsafety, asyncness, abi })
     }
 
     /// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
@@ -1025,59 +1027,12 @@ impl<'a> Parser<'a> {
             // trait item macro.
             (Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
         } else {
-            let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
-
-            let ident = self.parse_ident()?;
-            let mut generics = self.parse_generics()?;
-
             // This is somewhat dubious; We don't want to allow
             // argument names to be left off if there is a definition...
             //
             // We don't allow argument names to be left off in edition 2018.
-            let decl = self.parse_fn_decl_with_self(|t| t.span.rust_2018())?;
-            generics.where_clause = self.parse_where_clause()?;
-
-            let sig = ast::MethodSig {
-                header: FnHeader {
-                    unsafety,
-                    constness,
-                    abi,
-                    asyncness,
-                },
-                decl,
-            };
-
-            let body = match self.token.kind {
-                token::Semi => {
-                    self.bump();
-                    *at_end = true;
-                    debug!("parse_trait_methods(): parsing required method");
-                    None
-                }
-                token::OpenDelim(token::Brace) => {
-                    debug!("parse_trait_methods(): parsing provided method");
-                    *at_end = true;
-                    let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-                    attrs.extend(inner_attrs.iter().cloned());
-                    Some(body)
-                }
-                token::Interpolated(ref nt) => {
-                    match **nt {
-                        token::NtBlock(..) => {
-                            *at_end = true;
-                            let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-                            attrs.extend(inner_attrs.iter().cloned());
-                            Some(body)
-                        }
-                        _ => {
-                            return self.expected_semi_or_open_brace();
-                        }
-                    }
-                }
-                _ => {
-                    return self.expected_semi_or_open_brace();
-                }
-            };
+            let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
+            let body = self.parse_trait_method_body(at_end, &mut attrs)?;
             (ident, ast::TraitItemKind::Method(sig, body), generics)
         };
 
@@ -1092,6 +1047,43 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Parse the "body" of a method in a trait item definition.
+    /// This can either be `;` when there's no body,
+    /// or e.g. a block when the method is a provided one.
+    fn parse_trait_method_body(
+        &mut self,
+        at_end: &mut bool,
+        attrs: &mut Vec<Attribute>,
+    ) -> PResult<'a, Option<P<Block>>> {
+        Ok(match self.token.kind {
+            token::Semi => {
+                debug!("parse_trait_method_body(): parsing required method");
+                self.bump();
+                *at_end = true;
+                None
+            }
+            token::OpenDelim(token::Brace) => {
+                debug!("parse_trait_method_body(): parsing provided method");
+                *at_end = true;
+                let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
+                attrs.extend(inner_attrs.iter().cloned());
+                Some(body)
+            }
+            token::Interpolated(ref nt) => {
+                match **nt {
+                    token::NtBlock(..) => {
+                        *at_end = true;
+                        let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
+                        attrs.extend(inner_attrs.iter().cloned());
+                        Some(body)
+                    }
+                    _ => return self.expected_semi_or_open_brace(),
+                }
+            }
+            _ => return self.expected_semi_or_open_brace(),
+        })
+    }
+
     /// Parses the following grammar:
     ///
     ///     TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]

From 378cc98cd9dce625331503e8e439ce25671a4d3e Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 01:19:37 +0200
Subject: [PATCH 02/21] syntax: `is_named_argument` -> `is_named_param`.

---
 src/libsyntax/parse/parser.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2fb6f197dad7c..c183160168f84 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -954,7 +954,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn is_named_argument(&self) -> bool {
+    fn is_named_param(&self) -> bool {
         let offset = match self.token.kind {
             token::Interpolated(ref nt) => match **nt {
                 token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
@@ -993,7 +993,7 @@ impl<'a> Parser<'a> {
         }
 
         let is_name_required = is_name_required(&self.token);
-        let (pat, ty) = if is_name_required || self.is_named_argument() {
+        let (pat, ty) = if is_name_required || self.is_named_param() {
             debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
 
             let pat = self.parse_fn_param_pat()?;

From 4fa9c3bca3b0b3fe7d33648bc6bc69df57deb7db Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 01:21:42 +0200
Subject: [PATCH 03/21] syntax refactor `parse_fn_params`

---
 src/libsyntax/parse/parser.rs | 57 ++++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index c183160168f84..a6694cea73138 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1031,13 +1031,10 @@ impl<'a> Parser<'a> {
                     let pat = self.mk_pat_ident(ty.span, bm, ident);
                     (pat, ty)
                 }
+                // If this is a C-variadic argument and we hit an error, return the error.
+                Err(err) if self.token == token::DotDotDot => return Err(err),
+                // Recover from attempting to parse the argument as a type without pattern.
                 Err(mut err) => {
-                    // If this is a C-variadic argument and we hit an error, return the
-                    // error.
-                    if self.token == token::DotDotDot {
-                        return Err(err);
-                    }
-                    // Recover from attempting to parse the argument as a type without pattern.
                     err.cancel();
                     mem::replace(self, parser_snapshot_before_ty);
                     self.recover_arg_parse()?
@@ -1200,42 +1197,44 @@ impl<'a> Parser<'a> {
 
     }
 
-    fn parse_fn_params(&mut self, named_params: bool, allow_c_variadic: bool)
-                     -> PResult<'a, Vec<Param>> {
+    fn parse_fn_params(
+        &mut self,
+        named_params: bool,
+        allow_c_variadic: bool,
+    ) -> PResult<'a, Vec<Param>> {
         let sp = self.token.span;
+        let do_not_enforce_named_params_for_c_variadic = |token: &token::Token| {
+            match token.kind {
+                token::DotDotDot => false,
+                _ => named_params,
+            }
+        };
         let mut c_variadic = false;
-        let (params, _): (Vec<Option<Param>>, _) = self.parse_paren_comma_seq(|p| {
-            let do_not_enforce_named_arguments_for_c_variadic =
-                |token: &token::Token| -> bool {
-                    if token == &token::DotDotDot {
-                        false
-                    } else {
-                        named_params
-                    }
-                };
+        let (params, _) = self.parse_paren_comma_seq(|p| {
             match p.parse_param_general(
                 false,
                 false,
                 allow_c_variadic,
-                do_not_enforce_named_arguments_for_c_variadic
+                do_not_enforce_named_params_for_c_variadic,
             ) {
-                Ok(param) => {
+                Ok(param) => Ok(
                     if let TyKind::CVarArgs = param.ty.kind {
                         c_variadic = true;
                         if p.token != token::CloseDelim(token::Paren) {
-                            let span = p.token.span;
-                            p.span_err(span,
-                                "`...` must be the last argument of a C-variadic function");
+                            p.span_err(
+                                p.token.span,
+                                "`...` must be the last argument of a C-variadic function",
+                            );
                             // FIXME(eddyb) this should probably still push `CVarArgs`.
                             // Maybe AST validation/HIR lowering should emit the above error?
-                            Ok(None)
+                            None
                         } else {
-                            Ok(Some(param))
+                            Some(param)
                         }
                     } else {
-                        Ok(Some(param))
+                        Some(param)
                     }
-                },
+                ),
                 Err(mut e) => {
                     e.emit();
                     let lo = p.prev_span;
@@ -1251,8 +1250,10 @@ impl<'a> Parser<'a> {
         let params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
 
         if c_variadic && params.len() <= 1 {
-            self.span_err(sp,
-                          "C-variadic function must be declared with at least one named argument");
+            self.span_err(
+                sp,
+                "C-variadic function must be declared with at least one named argument",
+            );
         }
 
         Ok(params)

From 40dc9da44c146cb959a34700426d29d7037cfee6 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 01:49:22 +0200
Subject: [PATCH 04/21] syntax refactor `parse_self_param` (1)

---
 src/libsyntax/parse/parser.rs | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a6694cea73138..93de890b222e2 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1259,6 +1259,11 @@ impl<'a> Parser<'a> {
         Ok(params)
     }
 
+    fn is_isolated_self(&self, n: usize) -> bool {
+        self.is_keyword_ahead(n, &[kw::SelfLower])
+        && self.look_ahead(n + 1, |t| t != &token::ModSep)
+    }
+
     /// Returns the parsed optional self parameter and whether a self shortcut was used.
     ///
     /// See `parse_self_param_with_attrs` to collect attributes.
@@ -1269,10 +1274,6 @@ impl<'a> Parser<'a> {
                 { let span = this.token.span; this.bump(); Ident::new(name, span) }
             _ => unreachable!()
         };
-        let isolated_self = |this: &mut Self, n| {
-            this.look_ahead(n, |t| t.is_keyword(kw::SelfLower)) &&
-            this.look_ahead(n + 1, |t| t != &token::ModSep)
-        };
 
         // Parse optional `self` parameter of a method.
         // Only a limited set of initial token sequences is considered `self` parameters; anything
@@ -1285,22 +1286,22 @@ impl<'a> Parser<'a> {
                 // `&'lt self`
                 // `&'lt mut self`
                 // `&not_self`
-                (if isolated_self(self, 1) {
+                (if self.is_isolated_self(1) {
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
                 } else if self.is_keyword_ahead(1, &[kw::Mut]) &&
-                          isolated_self(self, 2) {
+                          self.is_isolated_self(2) {
                     self.bump();
                     self.bump();
                     SelfKind::Region(None, Mutability::Mutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
-                          isolated_self(self, 2) {
+                          self.is_isolated_self(2) {
                     self.bump();
                     let lt = self.expect_lifetime();
                     SelfKind::Region(Some(lt), Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
                           self.is_keyword_ahead(2, &[kw::Mut]) &&
-                          isolated_self(self, 3) {
+                          self.is_isolated_self(3) {
                     self.bump();
                     let lt = self.expect_lifetime();
                     self.bump();
@@ -1316,14 +1317,14 @@ impl<'a> Parser<'a> {
                 // `*not_self`
                 // Emit special error for `self` cases.
                 let msg = "cannot pass `self` by raw pointer";
-                (if isolated_self(self, 1) {
+                (if self.is_isolated_self(1) {
                     self.bump();
                     self.struct_span_err(self.token.span, msg)
                         .span_label(self.token.span, msg)
                         .emit();
                     SelfKind::Value(Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_mutability()) &&
-                          isolated_self(self, 2) {
+                          self.is_isolated_self(2) {
                     self.bump();
                     self.bump();
                     self.struct_span_err(self.token.span, msg)
@@ -1335,7 +1336,7 @@ impl<'a> Parser<'a> {
                 }, expect_ident(self), self.prev_span)
             }
             token::Ident(..) => {
-                if isolated_self(self, 0) {
+                if self.is_isolated_self(0) {
                     // `self`
                     // `self: TYPE`
                     let eself_ident = expect_ident(self);
@@ -1347,7 +1348,7 @@ impl<'a> Parser<'a> {
                         SelfKind::Value(Mutability::Immutable)
                     }, eself_ident, eself_hi)
                 } else if self.token.is_keyword(kw::Mut) &&
-                          isolated_self(self, 1) {
+                          self.is_isolated_self(1) {
                     // `mut self`
                     // `mut self: TYPE`
                     self.bump();

From f688f8aedffcd802012b355c182dafbdf5e819f5 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 01:57:50 +0200
Subject: [PATCH 05/21] syntax refactor `parse_self_param` (2)

---
 src/libsyntax/parse/parser.rs | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 93de890b222e2..70a7b4b01d8a0 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1264,17 +1264,22 @@ impl<'a> Parser<'a> {
         && self.look_ahead(n + 1, |t| t != &token::ModSep)
     }
 
+    fn expect_self_ident(&mut self) -> Ident {
+        match self.token.kind {
+            // Preserve hygienic context.
+            token::Ident(name, _) => {
+                let span = self.token.span;
+                self.bump();
+                Ident::new(name, span)
+            }
+            _ => unreachable!(),
+        }
+    }
+
     /// Returns the parsed optional self parameter and whether a self shortcut was used.
     ///
     /// See `parse_self_param_with_attrs` to collect attributes.
     fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
-        let expect_ident = |this: &mut Self| match this.token.kind {
-            // Preserve hygienic context.
-            token::Ident(name, _) =>
-                { let span = this.token.span; this.bump(); Ident::new(name, span) }
-            _ => unreachable!()
-        };
-
         // Parse optional `self` parameter of a method.
         // Only a limited set of initial token sequences is considered `self` parameters; anything
         // else is parsed as a normal function parameter list, so some lookahead is required.
@@ -1308,7 +1313,7 @@ impl<'a> Parser<'a> {
                     SelfKind::Region(Some(lt), Mutability::Mutable)
                 } else {
                     return Ok(None);
-                }, expect_ident(self), self.prev_span)
+                }, self.expect_self_ident(), self.prev_span)
             }
             token::BinOp(token::Star) => {
                 // `*self`
@@ -1333,13 +1338,13 @@ impl<'a> Parser<'a> {
                     SelfKind::Value(Mutability::Immutable)
                 } else {
                     return Ok(None);
-                }, expect_ident(self), self.prev_span)
+                }, self.expect_self_ident(), self.prev_span)
             }
             token::Ident(..) => {
                 if self.is_isolated_self(0) {
                     // `self`
                     // `self: TYPE`
-                    let eself_ident = expect_ident(self);
+                    let eself_ident = self.expect_self_ident();
                     let eself_hi = self.prev_span;
                     (if self.eat(&token::Colon) {
                         let ty = self.parse_ty()?;
@@ -1352,7 +1357,7 @@ impl<'a> Parser<'a> {
                     // `mut self`
                     // `mut self: TYPE`
                     self.bump();
-                    let eself_ident = expect_ident(self);
+                    let eself_ident = self.expect_self_ident();
                     let eself_hi = self.prev_span;
                     (if self.eat(&token::Colon) {
                         let ty = self.parse_ty()?;

From ac454e9af9389bb41a06ab620599771dcb2e59b6 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 02:06:55 +0200
Subject: [PATCH 06/21] syntax refactor `parse_self_param` (3)

---
 src/libsyntax/parse/parser.rs | 48 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 28 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 70a7b4b01d8a0..ae4f181a11940 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1276,6 +1276,18 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Parse `self` or `self: TYPE`. We already know the current token is `self`.
+    fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
+        let eself_ident = self.expect_self_ident();
+        let eself_hi = self.prev_span;
+        let eself = if self.eat(&token::Colon) {
+            SelfKind::Explicit(self.parse_ty()?, m)
+        } else {
+            SelfKind::Value(m)
+        };
+        Ok((eself, eself_ident, eself_hi))
+    }
+
     /// Returns the parsed optional self parameter and whether a self shortcut was used.
     ///
     /// See `parse_self_param_with_attrs` to collect attributes.
@@ -1340,34 +1352,14 @@ impl<'a> Parser<'a> {
                     return Ok(None);
                 }, self.expect_self_ident(), self.prev_span)
             }
-            token::Ident(..) => {
-                if self.is_isolated_self(0) {
-                    // `self`
-                    // `self: TYPE`
-                    let eself_ident = self.expect_self_ident();
-                    let eself_hi = self.prev_span;
-                    (if self.eat(&token::Colon) {
-                        let ty = self.parse_ty()?;
-                        SelfKind::Explicit(ty, Mutability::Immutable)
-                    } else {
-                        SelfKind::Value(Mutability::Immutable)
-                    }, eself_ident, eself_hi)
-                } else if self.token.is_keyword(kw::Mut) &&
-                          self.is_isolated_self(1) {
-                    // `mut self`
-                    // `mut self: TYPE`
-                    self.bump();
-                    let eself_ident = self.expect_self_ident();
-                    let eself_hi = self.prev_span;
-                    (if self.eat(&token::Colon) {
-                        let ty = self.parse_ty()?;
-                        SelfKind::Explicit(ty, Mutability::Mutable)
-                    } else {
-                        SelfKind::Value(Mutability::Mutable)
-                    }, eself_ident, eself_hi)
-                } else {
-                    return Ok(None);
-                }
+            // `self` and `self: TYPE`
+            token::Ident(..) if self.is_isolated_self(0) => {
+                self.parse_self_possibly_typed(Mutability::Immutable)?
+            }
+            // `mut self` and `mut self: TYPE`
+            token::Ident(..) if self.token.is_keyword(kw::Mut) && self.is_isolated_self(1) => {
+                self.bump();
+                self.parse_self_possibly_typed(Mutability::Mutable)?
             }
             _ => return Ok(None),
         };

From 4306d0037e961825abc08bfa39af0b64d1ed52aa Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 02:36:08 +0200
Subject: [PATCH 07/21] syntax refactor `parse_self_param` (4)

---
 src/libsyntax/parse/parser.rs    | 59 +++++++++++++++++++-------------
 src/libsyntax/parse/parser/ty.rs |  8 ++---
 2 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ae4f181a11940..fd6ffb800739d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1063,6 +1063,17 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Possibly parses mutability (`const` or `mut`).
+    fn parse_const_or_mut(&mut self) -> Option<Mutability> {
+        if self.eat_keyword(kw::Mut) {
+            Some(Mutability::Mutable)
+        } else if self.eat_keyword(kw::Const) {
+            Some(Mutability::Immutable)
+        } else {
+            None
+        }
+    }
+
     fn parse_field_name(&mut self) -> PResult<'a, Ident> {
         if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
                 self.token.kind {
@@ -1276,6 +1287,17 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Recover for the grammar `*self`, `*const self`, and `*mut self`.
+    fn recover_self_ptr(&mut self) -> PResult<'a, (ast::SelfKind, Ident, Span)> {
+        let msg = "cannot pass `self` by raw pointer";
+        let span = self.token.span;
+        self.struct_span_err(span, msg)
+            .span_label(span, msg)
+            .emit();
+
+        Ok((SelfKind::Value(Mutability::Immutable), self.expect_self_ident(), self.prev_span))
+    }
+
     /// Parse `self` or `self: TYPE`. We already know the current token is `self`.
     fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
         let eself_ident = self.expect_self_ident();
@@ -1327,30 +1349,19 @@ impl<'a> Parser<'a> {
                     return Ok(None);
                 }, self.expect_self_ident(), self.prev_span)
             }
-            token::BinOp(token::Star) => {
-                // `*self`
-                // `*const self`
-                // `*mut self`
-                // `*not_self`
-                // Emit special error for `self` cases.
-                let msg = "cannot pass `self` by raw pointer";
-                (if self.is_isolated_self(1) {
-                    self.bump();
-                    self.struct_span_err(self.token.span, msg)
-                        .span_label(self.token.span, msg)
-                        .emit();
-                    SelfKind::Value(Mutability::Immutable)
-                } else if self.look_ahead(1, |t| t.is_mutability()) &&
-                          self.is_isolated_self(2) {
-                    self.bump();
-                    self.bump();
-                    self.struct_span_err(self.token.span, msg)
-                        .span_label(self.token.span, msg)
-                        .emit();
-                    SelfKind::Value(Mutability::Immutable)
-                } else {
-                    return Ok(None);
-                }, self.expect_self_ident(), self.prev_span)
+            // `*self`
+            token::BinOp(token::Star) if self.is_isolated_self(1) => {
+                self.bump();
+                self.recover_self_ptr()?
+            }
+            // `*mut self` and `*const self`
+            token::BinOp(token::Star) if
+                self.look_ahead(1, |t| t.is_mutability())
+                && self.is_isolated_self(2) =>
+            {
+                self.bump();
+                self.bump();
+                self.recover_self_ptr()?
             }
             // `self` and `self: TYPE`
             token::Ident(..) if self.is_isolated_self(0) => {
diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs
index c52d3733b5e0a..41ee2a1599d74 100644
--- a/src/libsyntax/parse/parser/ty.rs
+++ b/src/libsyntax/parse/parser/ty.rs
@@ -231,11 +231,7 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
-        let mutbl = if self.eat_keyword(kw::Mut) {
-            Mutability::Mutable
-        } else if self.eat_keyword(kw::Const) {
-            Mutability::Immutable
-        } else {
+        let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
             let span = self.prev_span;
             let msg = "expected mut or const in raw pointer type";
             self.struct_span_err(span, msg)
@@ -243,7 +239,7 @@ impl<'a> Parser<'a> {
                 .help("use `*mut T` or `*const T` as appropriate")
                 .emit();
             Mutability::Immutable
-        };
+        });
         let t = self.parse_ty_no_plus()?;
         Ok(MutTy { ty: t, mutbl })
     }

From 0492302dbdef106956545b3faaa4b9ee54d99526 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 03:29:41 +0200
Subject: [PATCH 08/21] syntax refactor `parse_self_param` (5)

---
 src/libsyntax/parse/parser.rs | 43 +++++++++++++++++------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fd6ffb800739d..5ba1d1a9f0323 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1197,15 +1197,12 @@ impl<'a> Parser<'a> {
     /// Evaluates the closure with restrictions in place.
     ///
     /// Afters the closure is evaluated, restrictions are reset.
-    fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T
-        where F: FnOnce(&mut Self) -> T
-    {
+    fn with_res<T>(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> T {
         let old = self.restrictions;
-        self.restrictions = r;
-        let r = f(self);
+        self.restrictions = res;
+        let res = f(self);
         self.restrictions = old;
-        return r;
-
+        res
     }
 
     fn parse_fn_params(
@@ -1275,6 +1272,11 @@ impl<'a> Parser<'a> {
         && self.look_ahead(n + 1, |t| t != &token::ModSep)
     }
 
+    fn is_isolated_mut_self(&self, n: usize) -> bool {
+        self.is_keyword_ahead(n, &[kw::Mut])
+        && self.is_isolated_self(n + 1)
+    }
+
     fn expect_self_ident(&mut self) -> Ident {
         match self.token.kind {
             // Preserve hygienic context.
@@ -1320,34 +1322,31 @@ impl<'a> Parser<'a> {
         let eself_lo = self.token.span;
         let (eself, eself_ident, eself_hi) = match self.token.kind {
             token::BinOp(token::And) => {
-                // `&self`
-                // `&mut self`
-                // `&'lt self`
-                // `&'lt mut self`
-                // `&not_self`
-                (if self.is_isolated_self(1) {
+                let eself = if self.is_isolated_self(1) {
+                    // `&self`
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
-                } else if self.is_keyword_ahead(1, &[kw::Mut]) &&
-                          self.is_isolated_self(2) {
+                } else if self.is_isolated_mut_self(1) {
+                    // `&mut self`
                     self.bump();
                     self.bump();
                     SelfKind::Region(None, Mutability::Mutable)
-                } else if self.look_ahead(1, |t| t.is_lifetime()) &&
-                          self.is_isolated_self(2) {
+                } else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_self(2) {
+                    // `&'lt self`
                     self.bump();
                     let lt = self.expect_lifetime();
                     SelfKind::Region(Some(lt), Mutability::Immutable)
-                } else if self.look_ahead(1, |t| t.is_lifetime()) &&
-                          self.is_keyword_ahead(2, &[kw::Mut]) &&
-                          self.is_isolated_self(3) {
+                } else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_mut_self(2) {
+                    // `&'lt mut self`
                     self.bump();
                     let lt = self.expect_lifetime();
                     self.bump();
                     SelfKind::Region(Some(lt), Mutability::Mutable)
                 } else {
+                    // `&not_self`
                     return Ok(None);
-                }, self.expect_self_ident(), self.prev_span)
+                };
+                (eself, self.expect_self_ident(), self.prev_span)
             }
             // `*self`
             token::BinOp(token::Star) if self.is_isolated_self(1) => {
@@ -1368,7 +1367,7 @@ impl<'a> Parser<'a> {
                 self.parse_self_possibly_typed(Mutability::Immutable)?
             }
             // `mut self` and `mut self: TYPE`
-            token::Ident(..) if self.token.is_keyword(kw::Mut) && self.is_isolated_self(1) => {
+            token::Ident(..) if self.is_isolated_mut_self(0) => {
                 self.bump();
                 self.parse_self_possibly_typed(Mutability::Mutable)?
             }

From 347deac455c5365e6e74de3ca44b83ed77de41f3 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 05:32:46 +0200
Subject: [PATCH 09/21] syntax: reorder param  parsing to make more sense.

---
 src/libsyntax/parse/parser.rs | 306 +++++++++++++++++-----------------
 1 file changed, 153 insertions(+), 153 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5ba1d1a9f0323..cbeaab5a4d328 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -954,106 +954,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn is_named_param(&self) -> bool {
-        let offset = match self.token.kind {
-            token::Interpolated(ref nt) => match **nt {
-                token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
-                _ => 0,
-            }
-            token::BinOp(token::And) | token::AndAnd => 1,
-            _ if self.token.is_keyword(kw::Mut) => 1,
-            _ => 0,
-        };
-
-        self.look_ahead(offset, |t| t.is_ident()) &&
-        self.look_ahead(offset + 1, |t| t == &token::Colon)
-    }
-
-    /// Skips unexpected attributes and doc comments in this position and emits an appropriate
-    /// error.
-    /// This version of parse param doesn't necessarily require identifier names.
-    fn parse_param_general(
-        &mut self,
-        is_self_allowed: bool,
-        is_trait_item: bool,
-        allow_c_variadic: bool,
-        is_name_required: impl Fn(&token::Token) -> bool,
-    ) -> PResult<'a, Param> {
-        let lo = self.token.span;
-        let attrs = self.parse_outer_attributes()?;
-
-        // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
-        if let Some(mut param) = self.parse_self_param()? {
-            param.attrs = attrs.into();
-            return if is_self_allowed {
-                Ok(param)
-            } else {
-                self.recover_bad_self_param(param, is_trait_item)
-            };
-        }
-
-        let is_name_required = is_name_required(&self.token);
-        let (pat, ty) = if is_name_required || self.is_named_param() {
-            debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
-
-            let pat = self.parse_fn_param_pat()?;
-            if let Err(mut err) = self.expect(&token::Colon) {
-                if let Some(ident) = self.parameter_without_type(
-                    &mut err,
-                    pat,
-                    is_name_required,
-                    is_trait_item,
-                ) {
-                    err.emit();
-                    return Ok(dummy_arg(ident));
-                } else {
-                    return Err(err);
-                }
-            }
-
-            self.eat_incorrect_doc_comment_for_param_type();
-            (pat, self.parse_ty_common(true, true, allow_c_variadic)?)
-        } else {
-            debug!("parse_param_general ident_to_pat");
-            let parser_snapshot_before_ty = self.clone();
-            self.eat_incorrect_doc_comment_for_param_type();
-            let mut ty = self.parse_ty_common(true, true, allow_c_variadic);
-            if ty.is_ok() && self.token != token::Comma &&
-               self.token != token::CloseDelim(token::Paren) {
-                // This wasn't actually a type, but a pattern looking like a type,
-                // so we are going to rollback and re-parse for recovery.
-                ty = self.unexpected();
-            }
-            match ty {
-                Ok(ty) => {
-                    let ident = Ident::new(kw::Invalid, self.prev_span);
-                    let bm = BindingMode::ByValue(Mutability::Immutable);
-                    let pat = self.mk_pat_ident(ty.span, bm, ident);
-                    (pat, ty)
-                }
-                // If this is a C-variadic argument and we hit an error, return the error.
-                Err(err) if self.token == token::DotDotDot => return Err(err),
-                // Recover from attempting to parse the argument as a type without pattern.
-                Err(mut err) => {
-                    err.cancel();
-                    mem::replace(self, parser_snapshot_before_ty);
-                    self.recover_arg_parse()?
-                }
-            }
-        };
-
-        let span = lo.to(self.token.span);
-
-        Ok(Param {
-            attrs: attrs.into(),
-            id: ast::DUMMY_NODE_ID,
-            is_placeholder: false,
-            pat,
-            span,
-            ty,
-        })
-    }
-
     /// Parses mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
         if self.eat_keyword(kw::Mut) {
@@ -1267,49 +1167,112 @@ impl<'a> Parser<'a> {
         Ok(params)
     }
 
-    fn is_isolated_self(&self, n: usize) -> bool {
-        self.is_keyword_ahead(n, &[kw::SelfLower])
-        && self.look_ahead(n + 1, |t| t != &token::ModSep)
-    }
+    /// Parses the parameter list and result type of a function that may have a `self` parameter.
+    fn parse_fn_decl_with_self(
+        &mut self,
+        is_name_required: impl Copy + Fn(&token::Token) -> bool,
+    ) -> PResult<'a, P<FnDecl>> {
+        // Parse the arguments, starting out with `self` being allowed...
+        let mut is_self_allowed = true;
+        let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| {
+            let res = p.parse_param_general(is_self_allowed, true, false, is_name_required);
+            // ...but now that we've parsed the first argument, `self` is no longer allowed.
+            is_self_allowed = false;
+            res
+        })?;
 
-    fn is_isolated_mut_self(&self, n: usize) -> bool {
-        self.is_keyword_ahead(n, &[kw::Mut])
-        && self.is_isolated_self(n + 1)
+        // Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
+        self.deduplicate_recovered_params_names(&mut inputs);
+
+        Ok(P(FnDecl {
+            inputs,
+            output: self.parse_ret_ty(true)?,
+        }))
     }
 
-    fn expect_self_ident(&mut self) -> Ident {
-        match self.token.kind {
-            // Preserve hygienic context.
-            token::Ident(name, _) => {
-                let span = self.token.span;
-                self.bump();
-                Ident::new(name, span)
-            }
-            _ => unreachable!(),
+    /// Skips unexpected attributes and doc comments in this position and emits an appropriate
+    /// error.
+    /// This version of parse param doesn't necessarily require identifier names.
+    fn parse_param_general(
+        &mut self,
+        is_self_allowed: bool,
+        is_trait_item: bool,
+        allow_c_variadic: bool,
+        is_name_required: impl Fn(&token::Token) -> bool,
+    ) -> PResult<'a, Param> {
+        let lo = self.token.span;
+        let attrs = self.parse_outer_attributes()?;
+
+        // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
+        if let Some(mut param) = self.parse_self_param()? {
+            param.attrs = attrs.into();
+            return if is_self_allowed {
+                Ok(param)
+            } else {
+                self.recover_bad_self_param(param, is_trait_item)
+            };
         }
-    }
 
-    /// Recover for the grammar `*self`, `*const self`, and `*mut self`.
-    fn recover_self_ptr(&mut self) -> PResult<'a, (ast::SelfKind, Ident, Span)> {
-        let msg = "cannot pass `self` by raw pointer";
-        let span = self.token.span;
-        self.struct_span_err(span, msg)
-            .span_label(span, msg)
-            .emit();
+        let is_name_required = is_name_required(&self.token);
+        let (pat, ty) = if is_name_required || self.is_named_param() {
+            debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
 
-        Ok((SelfKind::Value(Mutability::Immutable), self.expect_self_ident(), self.prev_span))
-    }
+            let pat = self.parse_fn_param_pat()?;
+            if let Err(mut err) = self.expect(&token::Colon) {
+                if let Some(ident) = self.parameter_without_type(
+                    &mut err,
+                    pat,
+                    is_name_required,
+                    is_trait_item,
+                ) {
+                    err.emit();
+                    return Ok(dummy_arg(ident));
+                } else {
+                    return Err(err);
+                }
+            }
 
-    /// Parse `self` or `self: TYPE`. We already know the current token is `self`.
-    fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
-        let eself_ident = self.expect_self_ident();
-        let eself_hi = self.prev_span;
-        let eself = if self.eat(&token::Colon) {
-            SelfKind::Explicit(self.parse_ty()?, m)
+            self.eat_incorrect_doc_comment_for_param_type();
+            (pat, self.parse_ty_common(true, true, allow_c_variadic)?)
         } else {
-            SelfKind::Value(m)
+            debug!("parse_param_general ident_to_pat");
+            let parser_snapshot_before_ty = self.clone();
+            self.eat_incorrect_doc_comment_for_param_type();
+            let mut ty = self.parse_ty_common(true, true, allow_c_variadic);
+            if ty.is_ok() && self.token != token::Comma &&
+               self.token != token::CloseDelim(token::Paren) {
+                // This wasn't actually a type, but a pattern looking like a type,
+                // so we are going to rollback and re-parse for recovery.
+                ty = self.unexpected();
+            }
+            match ty {
+                Ok(ty) => {
+                    let ident = Ident::new(kw::Invalid, self.prev_span);
+                    let bm = BindingMode::ByValue(Mutability::Immutable);
+                    let pat = self.mk_pat_ident(ty.span, bm, ident);
+                    (pat, ty)
+                }
+                // If this is a C-variadic argument and we hit an error, return the error.
+                Err(err) if self.token == token::DotDotDot => return Err(err),
+                // Recover from attempting to parse the argument as a type without pattern.
+                Err(mut err) => {
+                    err.cancel();
+                    mem::replace(self, parser_snapshot_before_ty);
+                    self.recover_arg_parse()?
+                }
+            }
         };
-        Ok((eself, eself_ident, eself_hi))
+
+        let span = lo.to(self.token.span);
+
+        Ok(Param {
+            attrs: attrs.into(),
+            id: ast::DUMMY_NODE_ID,
+            is_placeholder: false,
+            pat,
+            span,
+            ty,
+        })
     }
 
     /// Returns the parsed optional self parameter and whether a self shortcut was used.
@@ -1378,27 +1341,64 @@ impl<'a> Parser<'a> {
         Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
     }
 
-    /// Parses the parameter list and result type of a function that may have a `self` parameter.
-    fn parse_fn_decl_with_self(
-        &mut self,
-        is_name_required: impl Copy + Fn(&token::Token) -> bool,
-    ) -> PResult<'a, P<FnDecl>> {
-        // Parse the arguments, starting out with `self` being allowed...
-        let mut is_self_allowed = true;
-        let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| {
-            let res = p.parse_param_general(is_self_allowed, true, false, is_name_required);
-            // ...but now that we've parsed the first argument, `self` is no longer allowed.
-            is_self_allowed = false;
-            res
-        })?;
+    fn is_named_param(&self) -> bool {
+        let offset = match self.token.kind {
+            token::Interpolated(ref nt) => match **nt {
+                token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
+                _ => 0,
+            }
+            token::BinOp(token::And) | token::AndAnd => 1,
+            _ if self.token.is_keyword(kw::Mut) => 1,
+            _ => 0,
+        };
 
-        // Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
-        self.deduplicate_recovered_params_names(&mut inputs);
+        self.look_ahead(offset, |t| t.is_ident()) &&
+        self.look_ahead(offset + 1, |t| t == &token::Colon)
+    }
 
-        Ok(P(FnDecl {
-            inputs,
-            output: self.parse_ret_ty(true)?,
-        }))
+    fn is_isolated_self(&self, n: usize) -> bool {
+        self.is_keyword_ahead(n, &[kw::SelfLower])
+        && self.look_ahead(n + 1, |t| t != &token::ModSep)
+    }
+
+    fn is_isolated_mut_self(&self, n: usize) -> bool {
+        self.is_keyword_ahead(n, &[kw::Mut])
+        && self.is_isolated_self(n + 1)
+    }
+
+    fn expect_self_ident(&mut self) -> Ident {
+        match self.token.kind {
+            // Preserve hygienic context.
+            token::Ident(name, _) => {
+                let span = self.token.span;
+                self.bump();
+                Ident::new(name, span)
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    /// Recover for the grammar `*self`, `*const self`, and `*mut self`.
+    fn recover_self_ptr(&mut self) -> PResult<'a, (ast::SelfKind, Ident, Span)> {
+        let msg = "cannot pass `self` by raw pointer";
+        let span = self.token.span;
+        self.struct_span_err(span, msg)
+            .span_label(span, msg)
+            .emit();
+
+        Ok((SelfKind::Value(Mutability::Immutable), self.expect_self_ident(), self.prev_span))
+    }
+
+    /// Parse `self` or `self: TYPE`. We already know the current token is `self`.
+    fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
+        let eself_ident = self.expect_self_ident();
+        let eself_hi = self.prev_span;
+        let eself = if self.eat(&token::Colon) {
+            SelfKind::Explicit(self.parse_ty()?, m)
+        } else {
+            SelfKind::Value(m)
+        };
+        Ok((eself, eself_ident, eself_hi))
     }
 
     fn is_crate_vis(&self) -> bool {

From d9d0e5d36bb6b3e23b4869196788bd10b5220f31 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 05:46:16 +0200
Subject: [PATCH 10/21] syntax: cleanup `parse_fn_decl`.

---
 src/libsyntax/parse/parser/item.rs | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 69fbb343ff3b6..2f353b65783ee 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -1274,14 +1274,11 @@ impl<'a> Parser<'a> {
         Ok((id, generics))
     }
 
-    /// Parses the argument list and result type of a function declaration.
+    /// Parses the parameter list and result type of a function declaration.
     fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P<FnDecl>> {
-        let args = self.parse_fn_params(true, allow_c_variadic)?;
-        let ret_ty = self.parse_ret_ty(true)?;
-
         Ok(P(FnDecl {
-            inputs: args,
-            output: ret_ty,
+            inputs: self.parse_fn_params(true, allow_c_variadic)?,
+            output: self.parse_ret_ty(true)?,
         }))
     }
 

From 5b80ead489beab6ed1e8f0f4951b7d982bd789ab Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 06:21:30 +0200
Subject: [PATCH 11/21] syntax: misc cleanup

---
 src/libsyntax/parse/parser.rs | 74 ++++++++++++++---------------------
 1 file changed, 30 insertions(+), 44 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cbeaab5a4d328..4853da865645f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -547,40 +547,38 @@ impl<'a> Parser<'a> {
         }
     }
 
-    crate fn check_ident(&mut self) -> bool {
-        if self.token.is_ident() {
+    fn check_or_expected(&mut self, ok: bool, mk_type: impl FnOnce() -> TokenType) -> bool {
+        if ok {
             true
         } else {
-            self.expected_tokens.push(TokenType::Ident);
+            self.expected_tokens.push(mk_type());
             false
         }
     }
 
+    crate fn check_ident(&mut self) -> bool {
+        self.check_or_expected(self.token.is_ident(), || TokenType::Ident)
+    }
+
     fn check_path(&mut self) -> bool {
-        if self.token.is_path_start() {
-            true
-        } else {
-            self.expected_tokens.push(TokenType::Path);
-            false
-        }
+        self.check_or_expected(self.token.is_path_start(), || TokenType::Path)
     }
 
     fn check_type(&mut self) -> bool {
-        if self.token.can_begin_type() {
-            true
-        } else {
-            self.expected_tokens.push(TokenType::Type);
-            false
-        }
+        self.check_or_expected(self.token.can_begin_type(), || TokenType::Type)
     }
 
     fn check_const_arg(&mut self) -> bool {
-        if self.token.can_begin_const_arg() {
-            true
-        } else {
-            self.expected_tokens.push(TokenType::Const);
-            false
-        }
+        self.check_or_expected(self.token.can_begin_const_arg(), || TokenType::Const)
+    }
+
+    /// Checks to see if the next token is either `+` or `+=`.
+    /// Otherwise returns `false`.
+    fn check_plus(&mut self) -> bool {
+        self.check_or_expected(
+            self.token.is_like_plus(),
+            || TokenType::Token(token::BinOp(token::Plus)),
+        )
     }
 
     /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=`
@@ -604,18 +602,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Checks to see if the next token is either `+` or `+=`.
-    /// Otherwise returns `false`.
-    fn check_plus(&mut self) -> bool {
-        if self.token.is_like_plus() {
-            true
-        }
-        else {
-            self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus)));
-            false
-        }
-    }
-
     /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single
     /// `&` and continues. If an `&` is not seen, signals an error.
     fn expect_and(&mut self) -> PResult<'a, ()> {
@@ -910,15 +896,13 @@ impl<'a> Parser<'a> {
         self.expected_tokens.clear();
     }
 
-    pub fn look_ahead<R, F>(&self, dist: usize, f: F) -> R where
-        F: FnOnce(&Token) -> R,
-    {
+    pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
         if dist == 0 {
-            return f(&self.token);
+            return looker(&self.token);
         }
 
         let frame = &self.token_cursor.frame;
-        f(&match frame.tree_cursor.look_ahead(dist - 1) {
+        looker(&match frame.tree_cursor.look_ahead(dist - 1) {
             Some(tree) => match tree {
                 TokenTree::Token(token) => token,
                 TokenTree::Delimited(dspan, delim, _) =>
@@ -1008,9 +992,10 @@ impl<'a> Parser<'a> {
         Ok((delim, tts.into()))
     }
 
-    fn parse_or_use_outer_attributes(&mut self,
-                                     already_parsed_attrs: Option<ThinVec<Attribute>>)
-                                     -> PResult<'a, ThinVec<Attribute>> {
+    fn parse_or_use_outer_attributes(
+        &mut self,
+        already_parsed_attrs: Option<ThinVec<Attribute>>,
+    ) -> PResult<'a, ThinVec<Attribute>> {
         if let Some(attrs) = already_parsed_attrs {
             Ok(attrs)
         } else {
@@ -1539,9 +1524,10 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
-        where F: FnOnce(&mut Self) -> PResult<'a, R>
-    {
+    fn collect_tokens<R>(
+        &mut self,
+        f: impl FnOnce(&mut Self) -> PResult<'a, R>,
+    ) -> PResult<'a, (R, TokenStream)> {
         // Record all tokens we parse when parsing this item.
         let mut tokens = Vec::new();
         let prev_collecting = match self.token_cursor.frame.last_token {

From 66bf323a3bb8aaa6162cf02ce9e3db2aa44f4779 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 06:42:56 +0200
Subject: [PATCH 12/21] syntax: cleanup `parse_visibility`.

---
 src/libsyntax/parse/parser.rs | 122 +++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 53 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 4853da865645f..438466851856f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1417,68 +1417,84 @@ impl<'a> Parser<'a> {
             // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
             // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
             // by the following tokens.
-            if self.is_keyword_ahead(1, &[kw::Crate]) &&
-                self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
+            if self.is_keyword_ahead(1, &[kw::Crate])
+                && self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
             {
-                // `pub(crate)`
-                self.bump(); // `(`
-                self.bump(); // `crate`
-                self.expect(&token::CloseDelim(token::Paren))?; // `)`
-                let vis = respan(
-                    lo.to(self.prev_span),
-                    VisibilityKind::Crate(CrateSugar::PubCrate),
-                );
-                return Ok(vis)
+                return self.parse_vis_pub_crate(lo);
             } else if self.is_keyword_ahead(1, &[kw::In]) {
-                // `pub(in path)`
-                self.bump(); // `(`
-                self.bump(); // `in`
-                let path = self.parse_path(PathStyle::Mod)?; // `path`
-                self.expect(&token::CloseDelim(token::Paren))?; // `)`
-                let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
-                    path: P(path),
-                    id: ast::DUMMY_NODE_ID,
-                });
-                return Ok(vis)
-            } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
-                      self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
+                return self.parse_vis_pub_in(lo);
+            } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren))
+                && self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
             {
-                // `pub(self)` or `pub(super)`
-                self.bump(); // `(`
-                let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
-                self.expect(&token::CloseDelim(token::Paren))?; // `)`
-                let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
-                    path: P(path),
-                    id: ast::DUMMY_NODE_ID,
-                });
-                return Ok(vis)
-            } else if !can_take_tuple {  // Provide this diagnostic if this is not a tuple struct
-                // `pub(something) fn ...` or `struct X { pub(something) y: Z }`
-                self.bump(); // `(`
-                let msg = "incorrect visibility restriction";
-                let suggestion = r##"some possible visibility restrictions are:
-`pub(crate)`: visible only on the current crate
-`pub(super)`: visible only in the current module's parent
-`pub(in path::to::module)`: visible only on the specified path"##;
-                let path = self.parse_path(PathStyle::Mod)?;
-                let sp = path.span;
-                let help_msg = format!("make this visible only to module `{}` with `in`", path);
-                self.expect(&token::CloseDelim(token::Paren))?;  // `)`
-                struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg)
-                    .help(suggestion)
-                    .span_suggestion(
-                        sp,
-                        &help_msg,
-                        format!("in {}", path),
-                        Applicability::MachineApplicable,
-                    )
-                    .emit(); // Emit diagnostic, but continue with public visibility.
+                return self.parse_vis_self_super(lo);
+            } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
+                self.recover_incorrect_vis_restriction()?;
+                // Emit diagnostic, but continue with public visibility.
             }
         }
 
         Ok(respan(lo, VisibilityKind::Public))
     }
 
+    /// Parse `pub(crate)`.
+    fn parse_vis_pub_crate(&mut self, lo: Span) -> PResult<'a, Visibility> {
+        self.bump(); // `(`
+        self.bump(); // `crate`
+        self.expect(&token::CloseDelim(token::Paren))?; // `)`
+        Ok(respan(
+            lo.to(self.prev_span),
+            VisibilityKind::Crate(CrateSugar::PubCrate),
+        ))
+    }
+
+    /// Parse `pub(in path)`.
+    fn parse_vis_pub_in(&mut self, lo: Span) -> PResult<'a, Visibility> {
+        self.bump(); // `(`
+        self.bump(); // `in`
+        let path = self.parse_path(PathStyle::Mod)?; // `path`
+        self.expect(&token::CloseDelim(token::Paren))?; // `)`
+        Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
+            path: P(path),
+            id: ast::DUMMY_NODE_ID,
+        }))
+    }
+
+    /// Parse `pub(self)` or `pub(super)`.
+    fn parse_vis_self_super(&mut self, lo: Span) -> PResult<'a, Visibility> {
+        self.bump(); // `(`
+        let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
+        self.expect(&token::CloseDelim(token::Paren))?; // `)`
+        Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
+            path: P(path),
+            id: ast::DUMMY_NODE_ID,
+        }))
+    }
+
+    /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
+    fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
+        self.bump(); // `(`
+        let path = self.parse_path(PathStyle::Mod)?;
+        self.expect(&token::CloseDelim(token::Paren))?;  // `)`
+
+        let msg = "incorrect visibility restriction";
+        let suggestion = r##"some possible visibility restrictions are:
+`pub(crate)`: visible only on the current crate
+`pub(super)`: visible only in the current module's parent
+`pub(in path::to::module)`: visible only on the specified path"##;
+
+        struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg)
+            .help(suggestion)
+            .span_suggestion(
+                path.span,
+                &format!("make this visible only to module `{}` with `in`", path),
+                format!("in {}", path),
+                Applicability::MachineApplicable,
+            )
+            .emit();
+
+        Ok(())
+    }
+
     /// Parses a string as an ABI spec on an extern type or module. Consumes
     /// the `extern` keyword, if one is found.
     fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {

From 573a8d8d30723592030c4eb22ebea637a58ac411 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 06:47:35 +0200
Subject: [PATCH 13/21] syntax: extract `error_on_invalid_abi`.

---
 src/libsyntax/parse/parser.rs | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 438466851856f..722f8969fb09e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1501,32 +1501,35 @@ impl<'a> Parser<'a> {
         match self.token.kind {
             token::Literal(token::Lit { kind: token::Str, symbol, suffix }) |
             token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => {
-                let sp = self.token.span;
-                self.expect_no_suffix(sp, "an ABI spec", suffix);
+                self.expect_no_suffix(self.token.span, "an ABI spec", suffix);
                 self.bump();
                 match abi::lookup(&symbol.as_str()) {
                     Some(abi) => Ok(Some(abi)),
                     None => {
-                        let prev_span = self.prev_span;
-                        struct_span_err!(
-                            self.sess.span_diagnostic,
-                            prev_span,
-                            E0703,
-                            "invalid ABI: found `{}`",
-                            symbol
-                        )
-                        .span_label(prev_span, "invalid ABI")
-                        .help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
-                        .emit();
+                        self.error_on_invalid_abi(symbol);
                         Ok(None)
                     }
                 }
             }
-
             _ => Ok(None),
         }
     }
 
+    /// Emit an error where `symbol` is an invalid ABI.
+    fn error_on_invalid_abi(&self, symbol: Symbol) {
+        let prev_span = self.prev_span;
+        struct_span_err!(
+            self.sess.span_diagnostic,
+            prev_span,
+            E0703,
+            "invalid ABI: found `{}`",
+            symbol
+        )
+        .span_label(prev_span, "invalid ABI")
+        .help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
+        .emit();
+    }
+
     /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
     fn ban_async_in_2015(&self, async_span: Span) {
         if async_span.rust_2015() {

From 258e86a5833588ffb2443a80b4e3c42300c4b278 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 08:53:59 +0200
Subject: [PATCH 14/21] syntax: fuse more code paths together.

---
 src/libsyntax/parse/parser/item.rs | 99 +++++++++++++++---------------
 1 file changed, 51 insertions(+), 48 deletions(-)

diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 2f353b65783ee..eaa04668b7a47 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -18,7 +18,7 @@ use crate::parse::token;
 use crate::parse::parser::maybe_append;
 use crate::parse::diagnostics::Error;
 use crate::tokenstream::{TokenTree, TokenStream};
-use crate::source_map::{respan, Span, Spanned};
+use crate::source_map::{respan, Span};
 use crate::symbol::{kw, sym};
 
 use std::mem;
@@ -122,12 +122,12 @@ impl<'a> Parser<'a> {
             if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
                 let fn_span = self.prev_span;
-                let abi = opt_abi.unwrap_or(Abi::C);
-                let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(Unsafety::Normal,
-                                       respan(fn_span, IsAsync::NotAsync),
-                                       respan(fn_span, Constness::NotConst),
-                                       abi)?;
+                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                    unsafety: Unsafety::Normal,
+                    asyncness: respan(fn_span, IsAsync::NotAsync),
+                    constness: respan(fn_span, Constness::NotConst),
+                    abi: opt_abi.unwrap_or(Abi::C),
+                })?;
                 let prev_span = self.prev_span;
                 let item = self.mk_item(lo.to(prev_span),
                                         ident,
@@ -165,11 +165,12 @@ impl<'a> Parser<'a> {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
                 self.bump();
-                let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(unsafety,
-                                       respan(const_span, IsAsync::NotAsync),
-                                       respan(const_span, Constness::Const),
-                                       Abi::Rust)?;
+                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                    unsafety,
+                    asyncness: respan(const_span, IsAsync::NotAsync),
+                    constness: respan(const_span, Constness::Const),
+                    abi: Abi::Rust,
+                })?;
                 let prev_span = self.prev_span;
                 let item = self.mk_item(lo.to(prev_span),
                                         ident,
@@ -213,14 +214,16 @@ impl<'a> Parser<'a> {
                 let unsafety = self.parse_unsafety(); // `unsafe`?
                 self.expect_keyword(kw::Fn)?; // `fn`
                 let fn_span = self.prev_span;
-                let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(unsafety,
-                                    respan(async_span, IsAsync::Async {
-                                        closure_id: DUMMY_NODE_ID,
-                                        return_impl_trait_id: DUMMY_NODE_ID,
-                                    }),
-                                    respan(fn_span, Constness::NotConst),
-                                    Abi::Rust)?;
+                let asyncness = respan(async_span, IsAsync::Async {
+                    closure_id: DUMMY_NODE_ID,
+                    return_impl_trait_id: DUMMY_NODE_ID,
+                });
+                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                    unsafety,
+                    asyncness,
+                    constness: respan(fn_span, Constness::NotConst),
+                    abi: Abi::Rust,
+                })?;
                 let prev_span = self.prev_span;
                 let item = self.mk_item(lo.to(prev_span),
                                         ident,
@@ -271,11 +274,12 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             self.bump();
             let fn_span = self.prev_span;
-            let (ident, item_, extra_attrs) =
-                self.parse_item_fn(Unsafety::Normal,
-                                   respan(fn_span, IsAsync::NotAsync),
-                                   respan(fn_span, Constness::NotConst),
-                                   Abi::Rust)?;
+            let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                unsafety: Unsafety::Normal,
+                asyncness: respan(fn_span, IsAsync::NotAsync),
+                constness: respan(fn_span, Constness::NotConst),
+                abi: Abi::Rust,
+            })?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
@@ -297,11 +301,12 @@ impl<'a> Parser<'a> {
             };
             self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
-            let (ident, item_, extra_attrs) =
-                self.parse_item_fn(Unsafety::Unsafe,
-                                   respan(fn_span, IsAsync::NotAsync),
-                                   respan(fn_span, Constness::NotConst),
-                                   abi)?;
+            let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                unsafety: Unsafety::Unsafe,
+                asyncness: respan(fn_span, IsAsync::NotAsync),
+                constness: respan(fn_span, Constness::NotConst),
+                abi,
+            })?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
@@ -872,8 +877,7 @@ impl<'a> Parser<'a> {
         is_name_required: impl Copy + Fn(&token::Token) -> bool,
     ) -> PResult<'a, (Ident, MethodSig, Generics)> {
         let header = self.parse_fn_front_matter()?;
-        let ident = self.parse_ident()?;
-        let mut generics = self.parse_generics()?;
+        let (ident, mut generics) = self.parse_fn_header()?;
         let decl = self.parse_fn_decl_with_self(is_name_required)?;
         let sig = MethodSig { header, decl };
         generics.where_clause = self.parse_where_clause()?;
@@ -1251,20 +1255,22 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an item-position function declaration.
-    fn parse_item_fn(
+    fn parse_item_fn(&mut self, header: FnHeader) -> PResult<'a, ItemInfo> {
+        let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe;
+        let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?;
+        let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
+        Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
+    }
+
+    /// Parse the "signature", including the identifier, parameters, and generics of a function.
+    fn parse_fn_sig(
         &mut self,
-        unsafety: Unsafety,
-        asyncness: Spanned<IsAsync>,
-        constness: Spanned<Constness>,
-        abi: Abi
-    ) -> PResult<'a, ItemInfo> {
+        allow_c_variadic: bool,
+    ) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
         let (ident, mut generics) = self.parse_fn_header()?;
-        let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe;
         let decl = self.parse_fn_decl(allow_c_variadic)?;
         generics.where_clause = self.parse_where_clause()?;
-        let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-        let header = FnHeader { unsafety, asyncness, constness, abi };
-        Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
+        Ok((ident, decl, generics))
     }
 
     /// Parses the name and optional generic types of a function header.
@@ -1386,18 +1392,15 @@ impl<'a> Parser<'a> {
         extern_sp: Span,
     ) -> PResult<'a, ForeignItem> {
         self.expect_keyword(kw::Fn)?;
-
-        let (ident, mut generics) = self.parse_fn_header()?;
-        let decl = self.parse_fn_decl(true)?;
-        generics.where_clause = self.parse_where_clause()?;
-        let hi = self.token.span;
+        let (ident, decl, generics) = self.parse_fn_sig(true)?;
+        let span = lo.to(self.token.span);
         self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
         Ok(ast::ForeignItem {
             ident,
             attrs,
             kind: ForeignItemKind::Fn(decl, generics),
             id: DUMMY_NODE_ID,
-            span: lo.to(hi),
+            span,
             vis,
         })
     }

From bea404f292f0ec60a990de28433b9eaa1dfecb4c Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 09:13:42 +0200
Subject: [PATCH 15/21] syntax: stylistic cleanup in item parsing.

---
 src/libsyntax/parse/parser/item.rs | 154 +++++++++--------------------
 1 file changed, 47 insertions(+), 107 deletions(-)

diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index eaa04668b7a47..68f0357abd03c 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -128,13 +128,9 @@ impl<'a> Parser<'a> {
                     constness: respan(fn_span, Constness::NotConst),
                     abi: opt_abi.unwrap_or(Abi::C),
                 })?;
-                let prev_span = self.prev_span;
-                let item = self.mk_item(lo.to(prev_span),
-                                        ident,
-                                        item_,
-                                        visibility,
-                                        maybe_append(attrs, extra_attrs));
-                return Ok(Some(item));
+                let span = lo.to(self.prev_span);
+                let attrs = maybe_append(attrs, extra_attrs);
+                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
             } else if self.check(&token::OpenDelim(token::Brace)) {
                 return Ok(Some(
                     self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?,
@@ -149,13 +145,9 @@ impl<'a> Parser<'a> {
             // STATIC ITEM
             let m = self.parse_mutability();
             let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.eat_keyword(kw::Const) {
             let const_span = self.prev_span;
@@ -171,13 +163,9 @@ impl<'a> Parser<'a> {
                     constness: respan(const_span, Constness::Const),
                     abi: Abi::Rust,
                 })?;
-                let prev_span = self.prev_span;
-                let item = self.mk_item(lo.to(prev_span),
-                                        ident,
-                                        item_,
-                                        visibility,
-                                        maybe_append(attrs, extra_attrs));
-                return Ok(Some(item));
+                let span = lo.to(self.prev_span);
+                let attrs = maybe_append(attrs, extra_attrs);
+                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
             }
 
             // CONST ITEM
@@ -194,13 +182,9 @@ impl<'a> Parser<'a> {
                     .emit();
             }
             let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
 
         // Parses `async unsafe? fn`.
@@ -224,14 +208,10 @@ impl<'a> Parser<'a> {
                     constness: respan(fn_span, Constness::NotConst),
                     abi: Abi::Rust,
                 })?;
-                let prev_span = self.prev_span;
-                let item = self.mk_item(lo.to(prev_span),
-                                        ident,
-                                        item_,
-                                        visibility,
-                                        maybe_append(attrs, extra_attrs));
                 self.ban_async_in_2015(async_span);
-                return Ok(Some(item));
+                let span = lo.to(self.prev_span);
+                let attrs = maybe_append(attrs, extra_attrs);
+                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
             }
         }
         if self.check_keyword(kw::Unsafe) &&
@@ -246,15 +226,10 @@ impl<'a> Parser<'a> {
                 self.expect_keyword(kw::Trait)?;
                 IsAuto::Yes
             };
-            let (ident, item_, extra_attrs) =
-                self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.check_keyword(kw::Impl) ||
            self.check_keyword(kw::Unsafe) &&
@@ -265,10 +240,10 @@ impl<'a> Parser<'a> {
             let defaultness = self.parse_defaultness();
             let unsafety = self.parse_unsafety();
             self.expect_keyword(kw::Impl)?;
-            let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
+            let (ident, item_, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
             let span = lo.to(self.prev_span);
-            return Ok(Some(self.mk_item(span, ident, item, visibility,
-                                        maybe_append(attrs, extra_attrs))));
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.check_keyword(kw::Fn) {
             // FUNCTION ITEM
@@ -280,13 +255,9 @@ impl<'a> Parser<'a> {
                 constness: respan(fn_span, Constness::NotConst),
                 abi: Abi::Rust,
             })?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.check_keyword(kw::Unsafe)
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
@@ -307,25 +278,16 @@ impl<'a> Parser<'a> {
                 constness: respan(fn_span, Constness::NotConst),
                 abi,
             })?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
-            let (ident, item_, extra_attrs) =
-                self.parse_item_mod(&attrs[..])?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let (ident, item_, extra_attrs) = self.parse_item_mod(&attrs[..])?;
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if let Some(type_) = self.eat_type() {
             let (ident, alias, generics) = type_?;
@@ -334,24 +296,15 @@ impl<'a> Parser<'a> {
                 AliasKind::Weak(ty) => ItemKind::TyAlias(ty, generics),
                 AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics),
             };
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    attrs);
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.eat_keyword(kw::Enum) {
             // ENUM ITEM
             let (ident, item_, extra_attrs) = self.parse_item_enum()?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.check_keyword(kw::Trait)
             || (self.check_keyword(kw::Auto)
@@ -365,38 +318,25 @@ impl<'a> Parser<'a> {
                 IsAuto::Yes
             };
             // TRAIT ITEM
-            let (ident, item_, extra_attrs) =
-                self.parse_item_trait(is_auto, Unsafety::Normal)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Normal)?;
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.eat_keyword(kw::Struct) {
             // STRUCT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_struct()?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if self.is_union_item() {
             // UNION ITEM
             self.bump();
             let (ident, item_, extra_attrs) = self.parse_item_union()?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            return Ok(Some(item));
+            let span = lo.to(self.prev_span);
+            let attrs = maybe_append(attrs, extra_attrs);
+            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
         }
         if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility, lo)? {
             return Ok(Some(macro_def));

From 151ce96e3e6c909ec071a313eaddc5e9f3b8f6bd Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Mon, 30 Sep 2019 09:32:51 +0200
Subject: [PATCH 16/21] syntax: reduce repetition in fn parsing.

---
 src/libsyntax/parse/parser/item.rs | 47 +++++++++++++-----------------
 1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 68f0357abd03c..e8ca264f1c5ff 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -122,15 +122,12 @@ impl<'a> Parser<'a> {
             if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
                 let fn_span = self.prev_span;
-                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                return self.parse_item_fn(lo, visibility, attrs, FnHeader {
                     unsafety: Unsafety::Normal,
                     asyncness: respan(fn_span, IsAsync::NotAsync),
                     constness: respan(fn_span, Constness::NotConst),
                     abi: opt_abi.unwrap_or(Abi::C),
-                })?;
-                let span = lo.to(self.prev_span);
-                let attrs = maybe_append(attrs, extra_attrs);
-                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
+                });
             } else if self.check(&token::OpenDelim(token::Brace)) {
                 return Ok(Some(
                     self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?,
@@ -157,15 +154,12 @@ impl<'a> Parser<'a> {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
                 self.bump();
-                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                return self.parse_item_fn(lo, visibility, attrs, FnHeader {
                     unsafety,
                     asyncness: respan(const_span, IsAsync::NotAsync),
                     constness: respan(const_span, Constness::Const),
                     abi: Abi::Rust,
-                })?;
-                let span = lo.to(self.prev_span);
-                let attrs = maybe_append(attrs, extra_attrs);
-                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
+                });
             }
 
             // CONST ITEM
@@ -202,16 +196,14 @@ impl<'a> Parser<'a> {
                     closure_id: DUMMY_NODE_ID,
                     return_impl_trait_id: DUMMY_NODE_ID,
                 });
-                let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+                let item = self.parse_item_fn(lo, visibility, attrs, FnHeader {
                     unsafety,
                     asyncness,
                     constness: respan(fn_span, Constness::NotConst),
                     abi: Abi::Rust,
                 })?;
                 self.ban_async_in_2015(async_span);
-                let span = lo.to(self.prev_span);
-                let attrs = maybe_append(attrs, extra_attrs);
-                return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
+                return Ok(item);
             }
         }
         if self.check_keyword(kw::Unsafe) &&
@@ -249,15 +241,12 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             self.bump();
             let fn_span = self.prev_span;
-            let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+            return self.parse_item_fn(lo, visibility, attrs, FnHeader {
                 unsafety: Unsafety::Normal,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
                 abi: Abi::Rust,
-            })?;
-            let span = lo.to(self.prev_span);
-            let attrs = maybe_append(attrs, extra_attrs);
-            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
+            });
         }
         if self.check_keyword(kw::Unsafe)
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
@@ -272,15 +261,12 @@ impl<'a> Parser<'a> {
             };
             self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
-            let (ident, item_, extra_attrs) = self.parse_item_fn(FnHeader {
+            return self.parse_item_fn(lo, visibility, attrs, FnHeader {
                 unsafety: Unsafety::Unsafe,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
                 abi,
-            })?;
-            let span = lo.to(self.prev_span);
-            let attrs = maybe_append(attrs, extra_attrs);
-            return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs)));
+            });
         }
         if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
@@ -1195,11 +1181,20 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an item-position function declaration.
-    fn parse_item_fn(&mut self, header: FnHeader) -> PResult<'a, ItemInfo> {
+    fn parse_item_fn(
+        &mut self,
+        lo: Span,
+        vis: Visibility,
+        attrs: Vec<Attribute>,
+        header: FnHeader,
+    ) -> PResult<'a, Option<P<Item>>> {
         let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe;
         let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-        Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
+        let span = lo.to(self.prev_span);
+        let kind = ItemKind::Fn(decl, header, generics, body);
+        let attrs = maybe_append(attrs, Some(inner_attrs));
+        Ok(Some(self.mk_item(span, ident, kind, vis, attrs)))
     }
 
     /// Parse the "signature", including the identifier, parameters, and generics of a function.

From df298b49f2eeb8497805359e360232c4b1030f51 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 1 Oct 2019 05:13:42 +0200
Subject: [PATCH 17/21] syntax: document some methods.

---
 src/libsyntax/parse/parser.rs | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 722f8969fb09e..75ab768d55df8 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -511,13 +511,15 @@ impl<'a> Parser<'a> {
         is_present
     }
 
+    /// If the next token is the given keyword, returns `true` without eating it.
+    /// An expectation is also added for diagnostics purposes.
     fn check_keyword(&mut self, kw: Symbol) -> bool {
         self.expected_tokens.push(TokenType::Keyword(kw));
         self.token.is_keyword(kw)
     }
 
-    /// If the next token is the given keyword, eats it and returns
-    /// `true`. Otherwise, returns `false`.
+    /// If the next token is the given keyword, eats it and returns `true`.
+    /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
     pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
         if self.check_keyword(kw) {
             self.bump();
@@ -896,6 +898,8 @@ impl<'a> Parser<'a> {
         self.expected_tokens.clear();
     }
 
+    /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
+    /// When `dist == 0` then the current token is looked at.
     pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
         if dist == 0 {
             return looker(&self.token);

From 30647d1a851336582fcc45f9460aab46371f98af Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 1 Oct 2019 05:45:41 +0200
Subject: [PATCH 18/21] syntax: put helpers of `parse_self_param` in the
 method.

---
 src/libsyntax/parse/parser.rs | 115 +++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 58 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 75ab768d55df8..a4420e4a0f394 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1268,27 +1268,71 @@ impl<'a> Parser<'a> {
     ///
     /// See `parse_self_param_with_attrs` to collect attributes.
     fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
+        // Extract an identifier *after* having confirmed that the token is one.
+        let expect_self_ident = |this: &mut Self| {
+            match this.token.kind {
+                // Preserve hygienic context.
+                token::Ident(name, _) => {
+                    let span = this.token.span;
+                    this.bump();
+                    Ident::new(name, span)
+                }
+                _ => unreachable!(),
+            }
+        };
+        // Is `self` `n` tokens ahead?
+        let is_isolated_self = |this: &Self, n| {
+            this.is_keyword_ahead(n, &[kw::SelfLower])
+            && this.look_ahead(n + 1, |t| t != &token::ModSep)
+        };
+        // Is `mut self` `n` tokens ahead?
+        let is_isolated_mut_self = |this: &Self, n| {
+            this.is_keyword_ahead(n, &[kw::Mut])
+            && is_isolated_self(this, n + 1)
+        };
+        // Parse `self` or `self: TYPE`. We already know the current token is `self`.
+        let parse_self_possibly_typed = |this: &mut Self, m| {
+            let eself_ident = expect_self_ident(this);
+            let eself_hi = this.prev_span;
+            let eself = if this.eat(&token::Colon) {
+                SelfKind::Explicit(this.parse_ty()?, m)
+            } else {
+                SelfKind::Value(m)
+            };
+            Ok((eself, eself_ident, eself_hi))
+        };
+        // Recover for the grammar `*self`, `*const self`, and `*mut self`.
+        let recover_self_ptr = |this: &mut Self| {
+            let msg = "cannot pass `self` by raw pointer";
+            let span = this.token.span;
+            this.struct_span_err(span, msg)
+                .span_label(span, msg)
+                .emit();
+
+            Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
+        };
+
         // Parse optional `self` parameter of a method.
         // Only a limited set of initial token sequences is considered `self` parameters; anything
         // else is parsed as a normal function parameter list, so some lookahead is required.
         let eself_lo = self.token.span;
         let (eself, eself_ident, eself_hi) = match self.token.kind {
             token::BinOp(token::And) => {
-                let eself = if self.is_isolated_self(1) {
+                let eself = if is_isolated_self(self, 1) {
                     // `&self`
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
-                } else if self.is_isolated_mut_self(1) {
+                } else if is_isolated_mut_self(self, 1) {
                     // `&mut self`
                     self.bump();
                     self.bump();
                     SelfKind::Region(None, Mutability::Mutable)
-                } else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_self(2) {
+                } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
                     // `&'lt self`
                     self.bump();
                     let lt = self.expect_lifetime();
                     SelfKind::Region(Some(lt), Mutability::Immutable)
-                } else if self.look_ahead(1, |t| t.is_lifetime()) && self.is_isolated_mut_self(2) {
+                } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
                     // `&'lt mut self`
                     self.bump();
                     let lt = self.expect_lifetime();
@@ -1298,30 +1342,30 @@ impl<'a> Parser<'a> {
                     // `&not_self`
                     return Ok(None);
                 };
-                (eself, self.expect_self_ident(), self.prev_span)
+                (eself, expect_self_ident(self), self.prev_span)
             }
             // `*self`
-            token::BinOp(token::Star) if self.is_isolated_self(1) => {
+            token::BinOp(token::Star) if is_isolated_self(self, 1) => {
                 self.bump();
-                self.recover_self_ptr()?
+                recover_self_ptr(self)?
             }
             // `*mut self` and `*const self`
             token::BinOp(token::Star) if
                 self.look_ahead(1, |t| t.is_mutability())
-                && self.is_isolated_self(2) =>
+                && is_isolated_self(self, 2) =>
             {
                 self.bump();
                 self.bump();
-                self.recover_self_ptr()?
+                recover_self_ptr(self)?
             }
             // `self` and `self: TYPE`
-            token::Ident(..) if self.is_isolated_self(0) => {
-                self.parse_self_possibly_typed(Mutability::Immutable)?
+            token::Ident(..) if is_isolated_self(self, 0) => {
+                parse_self_possibly_typed(self, Mutability::Immutable)?
             }
             // `mut self` and `mut self: TYPE`
-            token::Ident(..) if self.is_isolated_mut_self(0) => {
+            token::Ident(..) if is_isolated_mut_self(self, 0) => {
                 self.bump();
-                self.parse_self_possibly_typed(Mutability::Mutable)?
+                parse_self_possibly_typed(self, Mutability::Mutable)?
             }
             _ => return Ok(None),
         };
@@ -1345,51 +1389,6 @@ impl<'a> Parser<'a> {
         self.look_ahead(offset + 1, |t| t == &token::Colon)
     }
 
-    fn is_isolated_self(&self, n: usize) -> bool {
-        self.is_keyword_ahead(n, &[kw::SelfLower])
-        && self.look_ahead(n + 1, |t| t != &token::ModSep)
-    }
-
-    fn is_isolated_mut_self(&self, n: usize) -> bool {
-        self.is_keyword_ahead(n, &[kw::Mut])
-        && self.is_isolated_self(n + 1)
-    }
-
-    fn expect_self_ident(&mut self) -> Ident {
-        match self.token.kind {
-            // Preserve hygienic context.
-            token::Ident(name, _) => {
-                let span = self.token.span;
-                self.bump();
-                Ident::new(name, span)
-            }
-            _ => unreachable!(),
-        }
-    }
-
-    /// Recover for the grammar `*self`, `*const self`, and `*mut self`.
-    fn recover_self_ptr(&mut self) -> PResult<'a, (ast::SelfKind, Ident, Span)> {
-        let msg = "cannot pass `self` by raw pointer";
-        let span = self.token.span;
-        self.struct_span_err(span, msg)
-            .span_label(span, msg)
-            .emit();
-
-        Ok((SelfKind::Value(Mutability::Immutable), self.expect_self_ident(), self.prev_span))
-    }
-
-    /// Parse `self` or `self: TYPE`. We already know the current token is `self`.
-    fn parse_self_possibly_typed(&mut self, m: Mutability) -> PResult<'a, (SelfKind, Ident, Span)> {
-        let eself_ident = self.expect_self_ident();
-        let eself_hi = self.prev_span;
-        let eself = if self.eat(&token::Colon) {
-            SelfKind::Explicit(self.parse_ty()?, m)
-        } else {
-            SelfKind::Value(m)
-        };
-        Ok((eself, eself_ident, eself_hi))
-    }
-
     fn is_crate_vis(&self) -> bool {
         self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
     }

From 49780d21b63e0557627e185ed71c84e33eed0c4b Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 1 Oct 2019 05:53:23 +0200
Subject: [PATCH 19/21] syntax: merge things back into `parse_visibility`.

---
 src/libsyntax/parse/parser.rs | 62 ++++++++++++++---------------------
 1 file changed, 25 insertions(+), 37 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a4420e4a0f394..0369e0a9e153c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1423,13 +1423,35 @@ impl<'a> Parser<'a> {
             if self.is_keyword_ahead(1, &[kw::Crate])
                 && self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
             {
-                return self.parse_vis_pub_crate(lo);
+                // Parse `pub(crate)`.
+                self.bump(); // `(`
+                self.bump(); // `crate`
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                let vis = VisibilityKind::Crate(CrateSugar::PubCrate);
+                return Ok(respan(lo.to(self.prev_span), vis));
             } else if self.is_keyword_ahead(1, &[kw::In]) {
-                return self.parse_vis_pub_in(lo);
+                // Parse `pub(in path)`.
+                self.bump(); // `(`
+                self.bump(); // `in`
+                let path = self.parse_path(PathStyle::Mod)?; // `path`
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                let vis = VisibilityKind::Restricted {
+                    path: P(path),
+                    id: ast::DUMMY_NODE_ID,
+                };
+                return Ok(respan(lo.to(self.prev_span), vis));
             } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren))
                 && self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
             {
-                return self.parse_vis_self_super(lo);
+                // Parse `pub(self)` or `pub(super)`.
+                self.bump(); // `(`
+                let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                let vis = VisibilityKind::Restricted {
+                    path: P(path),
+                    id: ast::DUMMY_NODE_ID,
+                };
+                return Ok(respan(lo.to(self.prev_span), vis));
             } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
                 self.recover_incorrect_vis_restriction()?;
                 // Emit diagnostic, but continue with public visibility.
@@ -1439,40 +1461,6 @@ impl<'a> Parser<'a> {
         Ok(respan(lo, VisibilityKind::Public))
     }
 
-    /// Parse `pub(crate)`.
-    fn parse_vis_pub_crate(&mut self, lo: Span) -> PResult<'a, Visibility> {
-        self.bump(); // `(`
-        self.bump(); // `crate`
-        self.expect(&token::CloseDelim(token::Paren))?; // `)`
-        Ok(respan(
-            lo.to(self.prev_span),
-            VisibilityKind::Crate(CrateSugar::PubCrate),
-        ))
-    }
-
-    /// Parse `pub(in path)`.
-    fn parse_vis_pub_in(&mut self, lo: Span) -> PResult<'a, Visibility> {
-        self.bump(); // `(`
-        self.bump(); // `in`
-        let path = self.parse_path(PathStyle::Mod)?; // `path`
-        self.expect(&token::CloseDelim(token::Paren))?; // `)`
-        Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
-            path: P(path),
-            id: ast::DUMMY_NODE_ID,
-        }))
-    }
-
-    /// Parse `pub(self)` or `pub(super)`.
-    fn parse_vis_self_super(&mut self, lo: Span) -> PResult<'a, Visibility> {
-        self.bump(); // `(`
-        let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
-        self.expect(&token::CloseDelim(token::Paren))?; // `)`
-        Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
-            path: P(path),
-            id: ast::DUMMY_NODE_ID,
-        }))
-    }
-
     /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
     fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
         self.bump(); // `(`

From e04690440b6d77b4da9bfcf593a641133033ae44 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 1 Oct 2019 05:55:28 +0200
Subject: [PATCH 20/21] syntax: de-closure-ify `check_or_expected`.

---
 src/libsyntax/parse/parser.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 0369e0a9e153c..95f84d5cb3314 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -549,29 +549,29 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn check_or_expected(&mut self, ok: bool, mk_type: impl FnOnce() -> TokenType) -> bool {
+    fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool {
         if ok {
             true
         } else {
-            self.expected_tokens.push(mk_type());
+            self.expected_tokens.push(typ);
             false
         }
     }
 
     crate fn check_ident(&mut self) -> bool {
-        self.check_or_expected(self.token.is_ident(), || TokenType::Ident)
+        self.check_or_expected(self.token.is_ident(), TokenType::Ident)
     }
 
     fn check_path(&mut self) -> bool {
-        self.check_or_expected(self.token.is_path_start(), || TokenType::Path)
+        self.check_or_expected(self.token.is_path_start(), TokenType::Path)
     }
 
     fn check_type(&mut self) -> bool {
-        self.check_or_expected(self.token.can_begin_type(), || TokenType::Type)
+        self.check_or_expected(self.token.can_begin_type(), TokenType::Type)
     }
 
     fn check_const_arg(&mut self) -> bool {
-        self.check_or_expected(self.token.can_begin_const_arg(), || TokenType::Const)
+        self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const)
     }
 
     /// Checks to see if the next token is either `+` or `+=`.
@@ -579,7 +579,7 @@ impl<'a> Parser<'a> {
     fn check_plus(&mut self) -> bool {
         self.check_or_expected(
             self.token.is_like_plus(),
-            || TokenType::Token(token::BinOp(token::Plus)),
+            TokenType::Token(token::BinOp(token::Plus)),
         )
     }
 

From 5c5dd8069d0aeeb97ef6b6099767f97aec1edee4 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 1 Oct 2019 06:10:06 +0200
Subject: [PATCH 21/21] syntax: reformat passing of `FnHeader` to
 `parse_item_fn`.

---
 src/libsyntax/parse/parser/item.rs            | 28 +++++++++++--------
 .../edition-deny-async-fns-2015.stderr        | 12 ++++----
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index e8ca264f1c5ff..c00a5807d52c5 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -122,12 +122,13 @@ impl<'a> Parser<'a> {
             if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
                 let fn_span = self.prev_span;
-                return self.parse_item_fn(lo, visibility, attrs, FnHeader {
+                let header = FnHeader {
                     unsafety: Unsafety::Normal,
                     asyncness: respan(fn_span, IsAsync::NotAsync),
                     constness: respan(fn_span, Constness::NotConst),
                     abi: opt_abi.unwrap_or(Abi::C),
-                });
+                };
+                return self.parse_item_fn(lo, visibility, attrs, header);
             } else if self.check(&token::OpenDelim(token::Brace)) {
                 return Ok(Some(
                     self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?,
@@ -154,12 +155,13 @@ impl<'a> Parser<'a> {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
                 self.bump();
-                return self.parse_item_fn(lo, visibility, attrs, FnHeader {
+                let header = FnHeader {
                     unsafety,
                     asyncness: respan(const_span, IsAsync::NotAsync),
                     constness: respan(const_span, Constness::Const),
                     abi: Abi::Rust,
-                });
+                };
+                return self.parse_item_fn(lo, visibility, attrs, header);
             }
 
             // CONST ITEM
@@ -196,14 +198,14 @@ impl<'a> Parser<'a> {
                     closure_id: DUMMY_NODE_ID,
                     return_impl_trait_id: DUMMY_NODE_ID,
                 });
-                let item = self.parse_item_fn(lo, visibility, attrs, FnHeader {
+                self.ban_async_in_2015(async_span);
+                let header = FnHeader {
                     unsafety,
                     asyncness,
                     constness: respan(fn_span, Constness::NotConst),
                     abi: Abi::Rust,
-                })?;
-                self.ban_async_in_2015(async_span);
-                return Ok(item);
+                };
+                return self.parse_item_fn(lo, visibility, attrs, header);
             }
         }
         if self.check_keyword(kw::Unsafe) &&
@@ -241,12 +243,13 @@ impl<'a> Parser<'a> {
             // FUNCTION ITEM
             self.bump();
             let fn_span = self.prev_span;
-            return self.parse_item_fn(lo, visibility, attrs, FnHeader {
+            let header = FnHeader {
                 unsafety: Unsafety::Normal,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
                 abi: Abi::Rust,
-            });
+            };
+            return self.parse_item_fn(lo, visibility, attrs, header);
         }
         if self.check_keyword(kw::Unsafe)
             && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
@@ -261,12 +264,13 @@ impl<'a> Parser<'a> {
             };
             self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
-            return self.parse_item_fn(lo, visibility, attrs, FnHeader {
+            let header = FnHeader {
                 unsafety: Unsafety::Unsafe,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
                 abi,
-            });
+            };
+            return self.parse_item_fn(lo, visibility, attrs, header);
         }
         if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index d3f88af09d134..7633825eb32ab 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -10,18 +10,18 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
 LL | fn baz() { async fn foo() {} }
    |            ^^^^^
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
-  --> $DIR/edition-deny-async-fns-2015.rs:8:5
-   |
-LL |     async fn bar() {}
-   |     ^^^^^
-
 error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:7:1
    |
 LL | async fn async_baz() {
    | ^^^^^
 
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:8:5
+   |
+LL |     async fn bar() {}
+   |     ^^^^^
+
 error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:14:5
    |