Upgrade rust/crates/syn-mid to 0.5.1 am: 0d7fd466c4

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/syn-mid/+/1474976

Change-Id: Ic00b31230565492d3b77105702ba4a4d10c11108
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 69b0ee6..0a9485e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "4cc7697b87772a2eab48efd9dec4e293276dbc20"
+    "sha1": "cfaea705004ac99a16ece15de392541f20312f12"
   }
 }
diff --git a/.editorconfig b/.editorconfig
index 2d145b1..c93ffc7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,19 +4,13 @@
 # Top-most EditorConfig file
 root = true
 
-# Unix-style newlines with a newline ending every file, utf-8 charset
 [*]
 end_of_line = lf
 insert_final_newline = true
 trim_trailing_whitespace = true
 charset = utf-8
-
-# Match rust/toml, set 4 space indentation
-[*.{rs,toml}]
 indent_style = space
 indent_size = 4
 
-# Match json/yaml/markdown, set 2 space indentation
 [*.{json,yml,md}]
-indent_style = space
 indent_size = 2
diff --git a/.github/bors.toml b/.github/bors.toml
index b44dd8c..1779788 100644
--- a/.github/bors.toml
+++ b/.github/bors.toml
@@ -1,10 +1,2 @@
-status = [
-    "test (1.31.0)",
-    "test (stable)",
-    "test (beta)",
-    "test (nightly)",
-    "style (clippy)",
-    "style (rustfmt)",
-    "style (rustdoc)",
-]
+status = ["ci"]
 delete_merged_branches = true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c20c9dd..510417e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: ci
+name: CI
 
 on:
   pull_request:
@@ -8,33 +8,33 @@
       - staging
       - trying
   schedule:
-    - cron: '00 01 * * *'
+    - cron: '0 1 * * *'
 
 env:
   RUSTFLAGS: -Dwarnings
+  RUST_BACKTRACE: 1
+
+defaults:
+  run:
+    shell: bash
 
 jobs:
   test:
     name: test
-    runs-on: ubuntu-latest
     strategy:
       matrix:
         rust:
           # This is the minimum supported Rust version of this crate.
-          # When updating this, the reminder to update the minimum supported
-          # Rust version in README.md.
-          #
-          # Tests are not run as tests may require newer versions of Rust.
+          # When updating this, the reminder to update the minimum supported Rust version in README.md.
           - 1.31.0
           - stable
           - beta
           - nightly
+    runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@master
+      - uses: actions/checkout@v2
       - name: Install Rust
-        shell: bash
-        run: |
-          . ./ci/install-rust.sh ${{ matrix.rust }}
+        run: ci/install-rust.sh ${{ matrix.rust }}
       - name: Install cargo-hack
         if: matrix.rust != '1.31.0'
         run: |
@@ -51,45 +51,84 @@
         if: matrix.rust != '1.31.0'
         run: |
           cargo hack check --all --each-feature --no-dev-deps
-      # Refs: https://github.com/rust-lang/cargo/issues/5657
-      - name: cargo check -Zminimal-versions
+      - name: cargo check (minimal versions)
         if: matrix.rust == 'nightly'
         run: |
-          cargo update -Zminimal-versions
-          cargo hack check --all --all-features --no-dev-deps --ignore-private
+          bash scripts/check-minimal-versions.sh
 
-  style:
-    name: style
+  clippy:
+    name: clippy
     runs-on: ubuntu-latest
-    strategy:
-      fail-fast: false
-      matrix:
-        component:
-          - clippy
-          - rustfmt
-          - rustdoc
     steps:
-      - uses: actions/checkout@master
-      - name: Install Rust
-        shell: bash
-        run: |
-          . ./ci/install-rust.sh
-      - name: Install component
-        if: matrix.component != 'rustdoc'
-        shell: bash
-        run: |
-          . ./ci/install-component.sh ${{ matrix.component }}
+      - uses: actions/checkout@v2
+      - name: Install Rust and Clippy
+        run: ci/install-component.sh clippy
       - name: cargo clippy
-        if: matrix.component == 'clippy'
         run: |
-          cargo clippy --all --all-features
-      - name: cargo fmt -- --check
-        if: matrix.component == 'rustfmt'
+          cargo clippy --all --all-features --all-targets
+
+  rustfmt:
+    name: rustfmt
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Rust and Rustfmt
+        run: ci/install-component.sh rustfmt
+      - name: cargo fmt --check
         run: |
           cargo fmt --all -- --check
+
+  rustdoc:
+    name: rustdoc
+    env:
+      RUSTDOCFLAGS: -Dwarnings
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Rust
+        run: ci/install-rust.sh
       - name: cargo doc
-        if: matrix.component == 'rustdoc'
-        env:
-          RUSTDOCFLAGS: -Dwarnings
         run: |
           cargo doc --no-deps --all --all-features
+
+  shellcheck:
+    name: shellcheck
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: shellcheck
+        run: |
+          shellcheck ci/*.sh scripts/*.sh
+
+  # These jobs don't actually test anything, but they're used to tell bors the
+  # build completed, as there is no practical way to detect when a workflow is
+  # successful listening to webhooks only.
+  #
+  # ALL THE PREVIOUS JOBS NEEDS TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+
+  ci-success:
+    name: ci
+    if: github.event_name == 'push' && success()
+    needs:
+      - test
+      - clippy
+      - rustfmt
+      - rustdoc
+      - shellcheck
+    runs-on: ubuntu-latest
+    steps:
+      - name: Mark the job as a success
+        run: exit 0
+  ci-failure:
+    name: ci
+    if: github.event_name == 'push' && !success()
+    needs:
+      - test
+      - clippy
+      - rustfmt
+      - rustdoc
+      - shellcheck
+    runs-on: ubuntu-latest
+    steps:
+      - name: Mark the job as a failure
+        run: exit 1
diff --git a/.gitignore b/.gitignore
index 6a57018..ad0f684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
 target
-**/*.rs.bk
 Cargo.lock
 
 # For platform and editor specific settings, it is recommended to add to
 # a global .gitignore file.
-# Refs: https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore
+# Refs: https://docs.github.com/en/free-pro-team@latest/github/using-git/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
diff --git a/.rustfmt.toml b/.rustfmt.toml
deleted file mode 100644
index dc49733..0000000
--- a/.rustfmt.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-# Rustfmt configuration
-# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
-
-# This is required for bug-fixes, which technically can't be made to the stable
-# first version.
-version = "Two" # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3383
-
-# Refs: https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/72
-use_small_heuristics = "Max"
-
-# Apply rustfmt to more places.
-merge_imports = true # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3362
-format_code_in_doc_comments = true # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3348
-
-# Set the default settings again to always apply the proper formatting without
-# being affected by the editor settings.
-# Refs: https://github.com/rust-lang/rls/issues/501#issuecomment-333717736
-edition = "2018"
-tab_spaces = 4
diff --git a/Android.bp b/Android.bp
index ab8c9b2..87fcda0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -28,7 +28,7 @@
 }
 
 // dependent_library ["feature_list"]
-//   proc-macro2-1.0.19 "default,proc-macro"
-//   quote-1.0.7 "default,proc-macro"
-//   syn-1.0.36 "derive,parsing,printing,quote"
+//   proc-macro2-1.0.24
+//   quote-1.0.7
+//   syn-1.0.48 "derive,parsing,printing,quote"
 //   unicode-xid-0.2.1 "default"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f404310..9b17ce1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,14 @@
 
 ## [Unreleased]
 
+## [0.5.1] - 2020-10-14
+
+* Implement `Parse` for `Signature`.
+
+* Update parser implementations based on `syn` 1.0.44. This includes some bugfixes.
+
+* Disable default features of `proc-macro2` and `quote`.
+
 ## [0.5.0] - 2019-12-09
 
 * [Added `Signature` type.][13]
@@ -44,7 +52,8 @@
 
 Initial release
 
-[Unreleased]: https://github.com/taiki-e/syn-mid/compare/v0.5.0...HEAD
+[Unreleased]: https://github.com/taiki-e/syn-mid/compare/v0.5.1...HEAD
+[0.5.1]: https://github.com/taiki-e/syn-mid/compare/v0.5.0...v0.5.1
 [0.5.0]: https://github.com/taiki-e/syn-mid/compare/v0.4.0...v0.5.0
 [0.4.0]: https://github.com/taiki-e/syn-mid/compare/v0.3.0...v0.4.0
 [0.3.0]: https://github.com/taiki-e/syn-mid/compare/v0.2.0...v0.3.0
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..70c2090
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+# Code of Conduct
+
+This project adheres to the [Rust Code of Conduct].
+
+## Enforcement
+
+If you believe someone is violating the code of conduct, we ask that you report it by contacting taiki-e (te316e89@gmail.com).
+
+[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct
diff --git a/Cargo.toml b/Cargo.toml
index 7191c3e..d4bceb9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "syn-mid"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["Taiki Endo <te316e89@gmail.com>"]
 description = "Providing the features between \"full\" and \"derive\" of syn.\n"
 homepage = "https://github.com/taiki-e/syn-mid"
@@ -23,14 +23,19 @@
 categories = ["development-tools::procedural-macro-helpers"]
 license = "Apache-2.0 OR MIT"
 repository = "https://github.com/taiki-e/syn-mid"
+[package.metadata.docs.rs]
+all-features = true
+targets = ["x86_64-unknown-linux-gnu"]
 [dependencies.proc-macro2]
-version = "1.0"
+version = "1"
+default-features = false
 
 [dependencies.quote]
-version = "1.0"
+version = "1"
+default-features = false
 
 [dependencies.syn]
-version = "1.0.5"
+version = "1.0.44"
 features = ["parsing", "printing", "derive"]
 default-features = false
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 55cd2a6..8712673 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "syn-mid"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["Taiki Endo <te316e89@gmail.com>"]
 edition = "2018"
 license = "Apache-2.0 OR MIT"
@@ -14,6 +14,10 @@
 Providing the features between \"full\" and \"derive\" of syn.
 """
 
+[package.metadata.docs.rs]
+all-features = true
+targets = ["x86_64-unknown-linux-gnu"]
+
 [workspace]
 members = ["examples/const_fn", "examples/const_fn_test"]
 
@@ -21,6 +25,6 @@
 clone-impls = ["syn/clone-impls"]
 
 [dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0.5", default-features = false, features = ["parsing", "printing", "derive"] }
+proc-macro2 = { version = "1", default-features = false }
+quote = { version = "1", default-features = false }
+syn = { version = "1.0.44", default-features = false, features = ["parsing", "printing", "derive"] }
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index d645695..f433b1a 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -175,28 +175,3 @@
       of your accepting any such warranty or additional liability.
 
    END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/METADATA b/METADATA
index 5029778..b7d6e2a 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/syn-mid/syn-mid-0.5.0.crate"
+    value: "https://static.crates.io/crates/syn-mid/syn-mid-0.5.1.crate"
   }
-  version: "0.5.0"
+  version: "0.5.1"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 5
-    day: 6
+    month: 10
+    day: 26
   }
 }
diff --git a/README.md b/README.md
index 68c0dbd..fe93e5c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
 [crates-url]: https://crates.io/crates/syn-mid
 [docs-badge]: https://docs.rs/syn-mid/badge.svg
 [docs-url]: https://docs.rs/syn-mid
-[license-badge]: https://img.shields.io/crates/l/syn-mid.svg
+[license-badge]: https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg
 [license]: #license
 [rustc-badge]: https://img.shields.io/badge/rustc-1.31+-lightgray.svg
 [rustc-url]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
@@ -49,8 +49,6 @@
 
 [**Examples**](examples)
 
-[**Documentation**](https://docs.rs/syn-mid/)
-
 ## Optional features
 
 * **`clone-impls`** — Clone impls for all syntax tree types.
diff --git a/ci/install-component.sh b/ci/install-component.sh
old mode 100644
new mode 100755
index 943755c..dbba7b1
--- a/ci/install-component.sh
+++ b/ci/install-component.sh
@@ -1,29 +1,27 @@
 #!/bin/bash
 
+# Install nightly Rust with a given component.
+#
+# If the component is unavailable on the latest nightly,
+# use the latest toolchain with the component available.
+#
+# When using stable Rust, this script is basically unnecessary as almost components available.
+#
+# Refs: https://github.com/rust-lang/rustup-components-history#the-web-part
+
 set -euo pipefail
 
-component="${1}"
+package="${1:?}"
+target="${2:-x86_64-unknown-linux-gnu}"
 
-if ! rustup component add "${component}" 2>/dev/null; then
-    # If the component is unavailable on the latest nightly,
-    # use the latest toolchain with the component available.
-    # Refs: https://github.com/rust-lang/rustup-components-history#the-web-part
-    target=$(curl -sSf "https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/${component}")
-    echo "'${component}' is unavailable on the default toolchain, use the toolchain 'nightly-${target}' instead"
+date=$(curl -sSf https://rust-lang.github.io/rustup-components-history/"${target}"/"${package}")
 
-    rustup update "nightly-${target}" --no-self-update
-    rustup default "nightly-${target}"
+# shellcheck disable=1090
+"$(cd "$(dirname "${0}")" && pwd)"/install-rust.sh nightly-"${date}"
 
-    echo "Query rust and cargo versions:"
-    rustup -V
-    rustc -V
-    cargo -V
+rustup component add "${package}"
 
-    rustup component add "${component}"
-fi
-
-echo "Query component versions:"
-case "${component}" in
-    clippy | miri) cargo "${component}" -V ;;
-    rustfmt) "${component}" -V ;;
+case "${package}" in
+    rustfmt) "${package}" -V ;;
+    *) cargo "${package}" -V ;;
 esac
diff --git a/ci/install-rust.sh b/ci/install-rust.sh
old mode 100644
new mode 100755
index 3e0b27a..92c5877
--- a/ci/install-rust.sh
+++ b/ci/install-rust.sh
@@ -4,17 +4,9 @@
 
 toolchain="${1:-nightly}"
 
-if rustup -V 2>/dev/null; then
-    rustup set profile minimal
-    rustup update "${toolchain}" --no-self-update
-    rustup default "${toolchain}"
-else
-    curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${toolchain}"
-    export PATH=${PATH}:${HOME}/.cargo/bin
-    echo "##[add-path]${HOME}/.cargo/bin"
-fi
+rustup toolchain install "${toolchain}" --no-self-update --profile minimal
+rustup default "${toolchain}"
 
-echo "Query rust and cargo versions:"
 rustup -V
 rustc -V
 cargo -V
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..18c6d2a
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,27 @@
+# Rustfmt configuration
+# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
+
+# This is required for bug-fixes, which technically can't be made to the stable
+# first version.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3383).
+version = "Two"
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3391)
+error_on_line_overflow = true
+
+# Override the default formatting style.
+# See https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/81.
+use_small_heuristics = "Max"
+# See https://github.com/rust-dev-tools/fmt-rfcs/issues/149.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3370)
+overflow_delimited_expr = true
+
+# Apply rustfmt to more places.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3362).
+merge_imports = true
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3348).
+format_code_in_doc_comments = true
+
+# Set the default settings again to always apply the proper formatting without
+# being affected by the editor settings.
+edition = "2018"
+tab_spaces = 4
diff --git a/scripts/README.md b/scripts/README.md
new file mode 100644
index 0000000..671a9b1
--- /dev/null
+++ b/scripts/README.md
@@ -0,0 +1,3 @@
+This directory contains scripts used by the developers of this project.
+
+Some scripts in this directory are also used in CI, but scripts intended to be used only in CI and scripts not intended to be used directly by the developers are basically in the `ci` directory.
diff --git a/scripts/check-minimal-versions.sh b/scripts/check-minimal-versions.sh
new file mode 100755
index 0000000..6c7fa7b
--- /dev/null
+++ b/scripts/check-minimal-versions.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+# Check all public crates with minimal version dependencies.
+#
+# Usage:
+#    bash scripts/check-minimal-versions.sh
+#
+# Note:
+# - This script modifies Cargo.toml and Cargo.lock while running
+# - This script exits with 1 if there are any unstaged changes
+# - This script requires nightly Rust and cargo-hack
+#
+# Refs: https://github.com/rust-lang/cargo/issues/5657
+
+set -euo pipefail
+
+cd "$(cd "$(dirname "${0}")" && pwd)"/..
+
+if [[ "${1:-none}" == "+"* ]]; then
+    toolchain="${1}"
+elif [[ "${CI:-false}" != "true" ]]; then
+    cargo +nightly -V >/dev/null || exit 1
+    toolchain="+nightly"
+fi
+
+if [[ "${toolchain:-+nightly}" != "+nightly"* ]] || ! cargo hack -V &>/dev/null; then
+    echo "error: check-minimal-versions.sh requires nightly Rust and cargo-hack"
+    exit 1
+fi
+
+# This script modifies Cargo.toml and Cargo.lock, so make sure there are no
+# unstaged changes.
+git diff --exit-code
+# Restore original Cargo.toml and Cargo.lock on exit.
+trap 'git checkout .' EXIT
+
+# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
+# from determining minimal versions based on dev-dependencies.
+cargo hack --remove-dev-deps --workspace
+
+# Update Cargo.lock to minimal version dependencies.
+cargo ${toolchain:-} update -Zminimal-versions
+# Run check for all public members of the workspace.
+cargo ${toolchain:-} hack check --workspace --all-features --ignore-private -Zfeatures=all
diff --git a/src/arg.rs b/src/arg.rs
deleted file mode 100644
index 593a1ac..0000000
--- a/src/arg.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use syn::{Attribute, Lifetime, Token};
-
-use super::PatType;
-
-ast_enum_of_structs! {
-    /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
-    pub enum FnArg {
-        /// The `self` argument of an associated method, whether taken by value
-        /// or by reference.
-        Receiver(Receiver),
-
-        /// A function argument accepted by pattern and type.
-        Typed(PatType),
-    }
-}
-
-ast_struct! {
-    /// The `self` argument of an associated method, whether taken by value
-    /// or by reference.
-    pub struct Receiver {
-        pub attrs: Vec<Attribute>,
-        pub reference: Option<(Token![&], Option<Lifetime>)>,
-        pub mutability: Option<Token![mut]>,
-        pub self_token: Token![self],
-    }
-}
-
-mod parsing {
-    use syn::{
-        parse::{discouraged::Speculative, Parse, ParseStream, Result},
-        Attribute, Token,
-    };
-
-    use super::{FnArg, PatType, Receiver};
-
-    impl Parse for FnArg {
-        fn parse(input: ParseStream<'_>) -> Result<Self> {
-            let attrs = input.call(Attribute::parse_outer)?;
-
-            let ahead = input.fork();
-            if let Ok(mut receiver) = ahead.parse::<Receiver>() {
-                if !ahead.peek(Token![:]) {
-                    input.advance_to(&ahead);
-                    receiver.attrs = attrs;
-                    return Ok(FnArg::Receiver(receiver));
-                }
-            }
-
-            let mut typed = input.call(fn_arg_typed)?;
-            typed.attrs = attrs;
-            Ok(FnArg::Typed(typed))
-        }
-    }
-
-    impl Parse for Receiver {
-        fn parse(input: ParseStream<'_>) -> Result<Self> {
-            Ok(Self {
-                attrs: Vec::new(),
-                reference: {
-                    if input.peek(Token![&]) {
-                        Some((input.parse()?, input.parse()?))
-                    } else {
-                        None
-                    }
-                },
-                mutability: input.parse()?,
-                self_token: input.parse()?,
-            })
-        }
-    }
-
-    fn fn_arg_typed(input: ParseStream<'_>) -> Result<PatType> {
-        Ok(PatType {
-            attrs: Vec::new(),
-            pat: input.parse()?,
-            colon_token: input.parse()?,
-            ty: Box::new(input.parse()?),
-        })
-    }
-}
-
-mod printing {
-    use proc_macro2::TokenStream;
-    use quote::{ToTokens, TokenStreamExt};
-
-    use super::Receiver;
-
-    impl ToTokens for Receiver {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            tokens.append_all(&self.attrs);
-            if let Some((ampersand, lifetime)) = &self.reference {
-                ampersand.to_tokens(tokens);
-                lifetime.to_tokens(tokens);
-            }
-            self.mutability.to_tokens(tokens);
-            self.self_token.to_tokens(tokens);
-        }
-    }
-}
diff --git a/src/func.rs b/src/func.rs
new file mode 100644
index 0000000..19336f3
--- /dev/null
+++ b/src/func.rs
@@ -0,0 +1,266 @@
+use proc_macro2::TokenStream;
+use syn::{
+    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, Lifetime, ReturnType, Token,
+    Variadic, Visibility,
+};
+
+use super::PatType;
+
+ast_struct! {
+    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
+    /// }`.
+    pub struct ItemFn {
+        pub attrs: Vec<Attribute>,
+        pub vis: Visibility,
+        pub sig: Signature,
+        pub block: Box<Block>,
+    }
+}
+
+ast_struct! {
+    /// A braced block containing Rust statements.
+    pub struct Block {
+        pub brace_token: token::Brace,
+        /// Statements in a block
+        pub stmts: TokenStream,
+    }
+}
+
+ast_struct! {
+    /// A function signature in a trait or implementation: `unsafe fn
+    /// initialize(&self)`.
+    pub struct Signature {
+        pub constness: Option<Token![const]>,
+        pub asyncness: Option<Token![async]>,
+        pub unsafety: Option<Token![unsafe]>,
+        pub abi: Option<Abi>,
+        pub fn_token: Token![fn],
+        pub ident: Ident,
+        pub generics: Generics,
+        pub paren_token: token::Paren,
+        pub inputs: Punctuated<FnArg, Token![,]>,
+        pub variadic: Option<Variadic>,
+        pub output: ReturnType,
+    }
+}
+
+ast_enum_of_structs! {
+    /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
+    pub enum FnArg {
+        /// The `self` argument of an associated method, whether taken by value
+        /// or by reference.
+        Receiver(Receiver),
+
+        /// A function argument accepted by pattern and type.
+        Typed(PatType),
+    }
+}
+
+ast_struct! {
+    /// The `self` argument of an associated method, whether taken by value
+    /// or by reference.
+    pub struct Receiver {
+        pub attrs: Vec<Attribute>,
+        pub reference: Option<(Token![&], Option<Lifetime>)>,
+        pub mutability: Option<Token![mut]>,
+        pub self_token: Token![self],
+    }
+}
+
+mod parsing {
+    use syn::{
+        braced, parenthesized,
+        parse::{discouraged::Speculative, Parse, ParseStream, Result},
+        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
+    };
+
+    use super::{Block, FnArg, ItemFn, PatType, Receiver, Signature};
+
+    impl Parse for Block {
+        fn parse(input: ParseStream<'_>) -> Result<Self> {
+            let content;
+            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
+        }
+    }
+
+    impl Parse for Signature {
+        fn parse(input: ParseStream<'_>) -> Result<Self> {
+            let constness: Option<Token![const]> = input.parse()?;
+            let asyncness: Option<Token![async]> = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let abi: Option<Abi> = input.parse()?;
+            let fn_token: Token![fn] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let mut generics: Generics = input.parse()?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inputs = content.parse_terminated(FnArg::parse)?;
+            let variadic = inputs.last().as_ref().and_then(get_variadic);
+
+            fn get_variadic(input: &&FnArg) -> Option<Variadic> {
+                if let FnArg::Typed(PatType { ty, .. }) = input {
+                    if let Type::Verbatim(tokens) = &**ty {
+                        if let Ok(dots) = parse2(tokens.clone()) {
+                            return Some(Variadic { attrs: Vec::new(), dots });
+                        }
+                    }
+                }
+                None
+            }
+
+            let output: ReturnType = input.parse()?;
+            generics.where_clause = input.parse()?;
+
+            Ok(Self {
+                constness,
+                asyncness,
+                unsafety,
+                abi,
+                fn_token,
+                ident,
+                paren_token,
+                inputs,
+                output,
+                variadic,
+                generics,
+            })
+        }
+    }
+
+    impl Parse for ItemFn {
+        fn parse(input: ParseStream<'_>) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let sig = input.parse()?;
+            let block = input.parse()?;
+            Ok(Self { attrs, vis, sig, block: Box::new(block) })
+        }
+    }
+
+    impl Parse for FnArg {
+        fn parse(input: ParseStream<'_>) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+
+            let ahead = input.fork();
+            if let Ok(mut receiver) = ahead.parse::<Receiver>() {
+                if !ahead.peek(Token![:]) {
+                    input.advance_to(&ahead);
+                    receiver.attrs = attrs;
+                    return Ok(FnArg::Receiver(receiver));
+                }
+            }
+
+            let mut typed = input.call(fn_arg_typed)?;
+            typed.attrs = attrs;
+            Ok(FnArg::Typed(typed))
+        }
+    }
+
+    impl Parse for Receiver {
+        fn parse(input: ParseStream<'_>) -> Result<Self> {
+            Ok(Self {
+                attrs: Vec::new(),
+                reference: {
+                    if input.peek(Token![&]) {
+                        Some((input.parse()?, input.parse()?))
+                    } else {
+                        None
+                    }
+                },
+                mutability: input.parse()?,
+                self_token: input.parse()?,
+            })
+        }
+    }
+
+    fn fn_arg_typed(input: ParseStream<'_>) -> Result<PatType> {
+        Ok(PatType {
+            attrs: Vec::new(),
+            pat: input.parse()?,
+            colon_token: input.parse()?,
+            ty: Box::new(input.parse()?),
+        })
+    }
+}
+
+mod printing {
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+    use syn::{punctuated::Punctuated, Token, Type};
+
+    use super::{Block, FnArg, ItemFn, Receiver, Signature};
+
+    impl ToTokens for Block {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.stmts.clone());
+            });
+        }
+    }
+
+    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
+        let last = match inputs.last() {
+            Some(last) => last,
+            None => return false,
+        };
+
+        let pat = match last {
+            FnArg::Typed(pat) => pat,
+            FnArg::Receiver(_) => return false,
+        };
+
+        let tokens = match pat.ty.as_ref() {
+            Type::Verbatim(tokens) => tokens,
+            _ => return false,
+        };
+
+        tokens.to_string() == "..."
+    }
+
+    impl ToTokens for Signature {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.constness.to_tokens(tokens);
+            self.asyncness.to_tokens(tokens);
+            self.unsafety.to_tokens(tokens);
+            self.abi.to_tokens(tokens);
+            self.fn_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.inputs.to_tokens(tokens);
+                if self.variadic.is_some() && !has_variadic(&self.inputs) {
+                    if !self.inputs.empty_or_trailing() {
+                        <Token![,]>::default().to_tokens(tokens);
+                    }
+                    self.variadic.to_tokens(tokens);
+                }
+            });
+            self.output.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemFn {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(&self.attrs);
+            self.vis.to_tokens(tokens);
+            self.sig.to_tokens(tokens);
+            self.block.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.block.stmts.clone());
+            });
+        }
+    }
+
+    impl ToTokens for Receiver {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(&self.attrs);
+            if let Some((ampersand, lifetime)) = &self.reference {
+                ampersand.to_tokens(tokens);
+                lifetime.to_tokens(tokens);
+            }
+            self.mutability.to_tokens(tokens);
+            self.self_token.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 3b21506..4c271ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -19,25 +19,31 @@
 //! Other data structures are the same as data structures of [syn]. These are defined in this crate
 //! because they cannot be used in [syn] without "full" feature.
 //!
-//! ## Optional features
+//! # Optional features
 //!
 //! syn-mid in the default features aims to provide the features between "full"
 //! and "derive" of [syn].
 //!
 //! * **`clone-impls`** — Clone impls for all syntax tree types.
 //!
-//! [`syn_mid::ItemFn`]: struct.ItemFn.html
-//! [`syn_mid::Block`]: struct.Block.html
+//! [`syn_mid::ItemFn`]: ItemFn
+//! [`syn_mid::Block`]: Block
 //! [syn]: https://github.com/dtolnay/syn
 
-#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.0")]
+#![doc(html_root_url = "https://docs.rs/syn-mid/0.5.1")]
 #![doc(test(
     no_crate_inject,
     attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
 ))]
 #![forbid(unsafe_code)]
-#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
-#![warn(clippy::all)]
+#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![warn(clippy::all, clippy::default_trait_access)]
+// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
+#![allow(
+    clippy::mem_replace_with_default,
+    clippy::manual_non_exhaustive,
+    clippy::match_like_matches_macro
+)]
 #![allow(clippy::eval_order_dependence, clippy::large_enum_variant)]
 
 // Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.
@@ -45,194 +51,14 @@
 #[macro_use]
 mod macros;
 
-mod arg;
+mod func;
 mod pat;
 mod path;
 
-pub use self::{arg::*, pat::*};
-
-use proc_macro2::TokenStream;
-use syn::{
-    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Variadic,
-    Visibility,
+pub use crate::{
+    func::{Block, FnArg, ItemFn, Receiver, Signature},
+    pat::{
+        FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
+        PatType, PatWild,
+    },
 };
-
-ast_struct! {
-    /// A braced block containing Rust statements.
-    pub struct Block {
-        pub brace_token: token::Brace,
-        /// Statements in a block
-        pub stmts: TokenStream,
-    }
-}
-
-ast_struct! {
-    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
-    /// }`.
-    pub struct ItemFn {
-        pub attrs: Vec<Attribute>,
-        pub vis: Visibility,
-        pub sig: Signature,
-        pub block: Box<Block>,
-    }
-}
-
-ast_struct! {
-    /// A function signature in a trait or implementation: `unsafe fn
-    /// initialize(&self)`.
-    pub struct Signature {
-        pub constness: Option<Token![const]>,
-        pub asyncness: Option<Token![async]>,
-        pub unsafety: Option<Token![unsafe]>,
-        pub abi: Option<Abi>,
-        pub fn_token: Token![fn],
-        pub ident: Ident,
-        pub generics: Generics,
-        pub paren_token: token::Paren,
-        pub inputs: Punctuated<FnArg, Token![,]>,
-        pub variadic: Option<Variadic>,
-        pub output: ReturnType,
-    }
-}
-
-mod parsing {
-    use syn::{
-        braced, parenthesized,
-        parse::{Parse, ParseStream, Result},
-        parse2, Abi, Attribute, Generics, Ident, ReturnType, Token, Type, Variadic, Visibility,
-        WhereClause,
-    };
-
-    use super::{Block, FnArg, ItemFn, PatType, Signature};
-
-    impl Parse for Block {
-        fn parse(input: ParseStream<'_>) -> Result<Self> {
-            let content;
-            Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
-        }
-    }
-
-    impl Parse for ItemFn {
-        fn parse(input: ParseStream<'_>) -> Result<Self> {
-            let attrs = input.call(Attribute::parse_outer)?;
-            let vis: Visibility = input.parse()?;
-            let constness: Option<Token![const]> = input.parse()?;
-            let asyncness: Option<Token![async]> = input.parse()?;
-            let unsafety: Option<Token![unsafe]> = input.parse()?;
-            let abi: Option<Abi> = input.parse()?;
-            let fn_token: Token![fn] = input.parse()?;
-            let ident: Ident = input.parse()?;
-            let generics: Generics = input.parse()?;
-
-            let content;
-            let paren_token = parenthesized!(content in input);
-            let inputs = content.parse_terminated(FnArg::parse)?;
-            let variadic = inputs.last().as_ref().and_then(get_variadic);
-
-            #[allow(clippy::trivially_copy_pass_by_ref)]
-            fn get_variadic(input: &&FnArg) -> Option<Variadic> {
-                if let FnArg::Typed(PatType { ty, .. }) = input {
-                    if let Type::Verbatim(tokens) = &**ty {
-                        if let Ok(dots) = parse2(tokens.clone()) {
-                            return Some(Variadic { attrs: Vec::new(), dots });
-                        }
-                    }
-                }
-                None
-            }
-
-            let output: ReturnType = input.parse()?;
-            let where_clause: Option<WhereClause> = input.parse()?;
-
-            let block = input.parse()?;
-
-            Ok(Self {
-                attrs,
-                vis,
-                sig: Signature {
-                    constness,
-                    asyncness,
-                    unsafety,
-                    abi,
-                    fn_token,
-                    ident,
-                    paren_token,
-                    inputs,
-                    output,
-                    variadic,
-                    generics: Generics { where_clause, ..generics },
-                },
-                block: Box::new(block),
-            })
-        }
-    }
-}
-
-mod printing {
-    use proc_macro2::TokenStream;
-    use quote::{ToTokens, TokenStreamExt};
-    use syn::{punctuated::Punctuated, Token, Type};
-
-    use super::{Block, FnArg, ItemFn, Signature};
-
-    impl ToTokens for Block {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            self.brace_token.surround(tokens, |tokens| {
-                tokens.append_all(self.stmts.clone());
-            });
-        }
-    }
-
-    fn has_variadic(inputs: &Punctuated<FnArg, Token![,]>) -> bool {
-        let last = match inputs.last() {
-            Some(last) => last,
-            None => return false,
-        };
-
-        let pat = match last {
-            FnArg::Typed(pat) => pat,
-            FnArg::Receiver(_) => return false,
-        };
-
-        let tokens = match pat.ty.as_ref() {
-            Type::Verbatim(tokens) => tokens,
-            _ => return false,
-        };
-
-        tokens.to_string() == "..."
-    }
-
-    impl ToTokens for Signature {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            self.constness.to_tokens(tokens);
-            self.asyncness.to_tokens(tokens);
-            self.unsafety.to_tokens(tokens);
-            self.abi.to_tokens(tokens);
-            self.fn_token.to_tokens(tokens);
-            self.ident.to_tokens(tokens);
-            self.generics.to_tokens(tokens);
-            self.paren_token.surround(tokens, |tokens| {
-                self.inputs.to_tokens(tokens);
-                if self.variadic.is_some() && !has_variadic(&self.inputs) {
-                    if !self.inputs.empty_or_trailing() {
-                        <Token![,]>::default().to_tokens(tokens);
-                    }
-                    self.variadic.to_tokens(tokens);
-                }
-            });
-            self.output.to_tokens(tokens);
-            self.generics.where_clause.to_tokens(tokens);
-        }
-    }
-
-    impl ToTokens for ItemFn {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            tokens.append_all(&self.attrs);
-            self.vis.to_tokens(tokens);
-            self.sig.to_tokens(tokens);
-            self.block.brace_token.surround(tokens, |tokens| {
-                tokens.append_all(self.block.stmts.clone());
-            });
-        }
-    }
-}
diff --git a/src/pat.rs b/src/pat.rs
index ff1277f..78bf890 100644
--- a/src/pat.rs
+++ b/src/pat.rs
@@ -8,7 +8,7 @@
     ///
     /// This type is a [syntax tree enum].
     ///
-    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    /// [syntax tree enum]: https://docs.rs/syn/1/syn/enum.Expr.html#syntax-tree-enums
     pub enum Pat {
         /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
         Ident(PatIdent),
@@ -134,27 +134,28 @@
         parenthesized,
         parse::{Parse, ParseStream, Result},
         punctuated::Punctuated,
-        token, Ident, Member, Path, Token,
+        token, Attribute, Ident, Member, Path, Token,
     };
 
-    use crate::path;
-
     use super::{
         FieldPat, Pat, PatIdent, PatPath, PatReference, PatStruct, PatTuple, PatTupleStruct,
         PatWild,
     };
+    use crate::path;
 
     impl Parse for Pat {
         fn parse(input: ParseStream<'_>) -> Result<Self> {
             let lookahead = input.lookahead1();
-            if lookahead.peek(Ident)
-                && ({
-                    input.peek2(Token![::])
-                        || input.peek2(token::Brace)
-                        || input.peek2(token::Paren)
-                })
-                || input.peek(Token![self]) && input.peek2(Token![::])
-                || lookahead.peek(Token![::])
+            if {
+                let ahead = input.fork();
+                ahead.parse::<Option<Ident>>()?.is_some()
+                    && (ahead.peek(Token![::])
+                        || ahead.peek(token::Brace)
+                        || ahead.peek(token::Paren))
+            } || {
+                let ahead = input.fork();
+                ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::])
+            } || lookahead.peek(Token![::])
                 || lookahead.peek(Token![<])
                 || input.peek(Token![Self])
                 || input.peek(Token![super])
@@ -217,7 +218,7 @@
         while !content.is_empty() && !content.peek(Token![..]) {
             let value = content.call(field_pat)?;
             fields.push_value(value);
-            if !content.peek(Token![,]) {
+            if content.is_empty() {
                 break;
             }
             let punct: Token![,] = content.parse()?;
@@ -234,6 +235,7 @@
     }
 
     fn field_pat(input: ParseStream<'_>) -> Result<FieldPat> {
+        let attrs = input.call(Attribute::parse_outer)?;
         let boxed: Option<Token![box]> = input.parse()?;
         let by_ref: Option<Token![ref]> = input.parse()?;
         let mutability: Option<Token![mut]> = input.parse()?;
@@ -243,7 +245,7 @@
             || is_unnamed(&member)
         {
             return Ok(FieldPat {
-                attrs: Vec::new(),
+                attrs,
                 member,
                 colon_token: input.parse()?,
                 pat: input.parse()?,
@@ -258,12 +260,7 @@
         let pat =
             Pat::Ident(PatIdent { attrs: Vec::new(), by_ref, mutability, ident: ident.clone() });
 
-        Ok(FieldPat {
-            member: Member::Named(ident),
-            pat: Box::new(pat),
-            attrs: Vec::new(),
-            colon_token: None,
-        })
+        Ok(FieldPat { attrs, member: Member::Named(ident), colon_token: None, pat: Box::new(pat) })
     }
 
     fn pat_tuple(input: ParseStream<'_>) -> Result<PatTuple> {
diff --git a/src/path.rs b/src/path.rs
index 408cda7..c58a0c1 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -6,11 +6,7 @@
 };
 
 fn parse_path_segment(input: ParseStream<'_>) -> Result<PathSegment> {
-    if input.peek(Token![super])
-        || input.peek(Token![self])
-        || input.peek(Token![crate])
-        || input.peek(Token![extern])
-    {
+    if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) {
         let ident = input.call(Ident::parse_any)?;
         return Ok(PathSegment::from(ident));
     }