Move parse_macro_input to a different trait
diff --git a/src/lib.rs b/src/lib.rs
index d8031f5..00d5e1d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -446,6 +446,15 @@
 #[doc(hidden)]
 pub mod parse_quote;
 
+// Not public API except the `parse_macro_input!` macro.
+#[cfg(all(
+    not(all(target_arch = "wasm32", target_os = "unknown")),
+    feature = "parsing",
+    feature = "proc-macro"
+))]
+#[doc(hidden)]
+pub mod parse_macro_input;
+
 #[cfg(all(feature = "parsing", feature = "printing"))]
 pub mod spanned;
 
@@ -763,58 +772,3 @@
     file.shebang = shebang;
     Ok(file)
 }
-
-/// Parse the input TokenStream of a macro, triggering a compile error if the
-/// tokens fail to parse.
-///
-/// Refer to the [`parse` module] documentation for more details about parsing
-/// in Syn.
-///
-/// [`parse` module]: parse/index.html
-///
-/// # Intended usage
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// extern crate proc_macro;
-///
-/// use proc_macro::TokenStream;
-/// use syn::parse::{Parse, ParseStream, Result};
-///
-/// struct MyMacroInput {
-///     /* ... */
-/// }
-///
-/// impl Parse for MyMacroInput {
-///     fn parse(input: ParseStream) -> Result<Self> {
-///         /* ... */
-/// #       Ok(MyMacroInput {})
-///     }
-/// }
-///
-/// # const IGNORE: &str = stringify! {
-/// #[proc_macro]
-/// # };
-/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
-///     let input = parse_macro_input!(tokens as MyMacroInput);
-///
-///     /* ... */
-/// #   "".parse().unwrap()
-/// }
-/// #
-/// # fn main() {}
-/// ```
-#[cfg(feature = "proc-macro")]
-#[macro_export]
-macro_rules! parse_macro_input {
-    ($tokenstream:ident as $ty:ty) => {
-        match $crate::parse::<$ty>($tokenstream) {
-            $crate::export::Ok(data) => data,
-            $crate::export::Err(err) => {
-                return $crate::export::TokenStream::from(err.to_compile_error());
-            }
-        };
-    };
-}
diff --git a/src/parse_macro_input.rs b/src/parse_macro_input.rs
new file mode 100644
index 0000000..e66d1d4
--- /dev/null
+++ b/src/parse_macro_input.rs
@@ -0,0 +1,102 @@
+/// Parse the input TokenStream of a macro, triggering a compile error if the
+/// tokens fail to parse.
+///
+/// Refer to the [`parse` module] documentation for more details about parsing
+/// in Syn.
+///
+/// [`parse` module]: parse/index.html
+///
+/// # Intended usage
+///
+/// ```rust
+/// #[macro_use]
+/// extern crate syn;
+///
+/// extern crate proc_macro;
+///
+/// use proc_macro::TokenStream;
+/// use syn::parse::{Parse, ParseStream, Result};
+///
+/// struct MyMacroInput {
+///     /* ... */
+/// }
+///
+/// impl Parse for MyMacroInput {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         /* ... */
+/// #       Ok(MyMacroInput {})
+///     }
+/// }
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro]
+/// # };
+/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
+///     let input = parse_macro_input!(tokens as MyMacroInput);
+///
+///     /* ... */
+/// #   "".parse().unwrap()
+/// }
+/// #
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! parse_macro_input {
+    ($tokenstream:ident as $ty:ty) => {
+        match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
+            $crate::export::Ok(data) => data,
+            $crate::export::Err(err) => {
+                return $crate::export::TokenStream::from(err.to_compile_error());
+            }
+        };
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Can parse any type that implements Parse.
+
+use parse::{Parse, ParseStream, Parser, Result};
+use proc_macro::TokenStream;
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
+    T::parse.parse(token_stream)
+}
+
+// Not public API.
+#[doc(hidden)]
+pub trait ParseMacroInput: Sized {
+    fn parse(input: ParseStream) -> Result<Self>;
+}
+
+impl<T: Parse> ParseMacroInput for T {
+    fn parse(input: ParseStream) -> Result<Self> {
+        <T as Parse>::parse(input)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Any other types that we want `parse_macro_input!` to be able to parse.
+
+use NestedMeta;
+
+impl ParseMacroInput for Vec<NestedMeta> {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let mut metas = Vec::new();
+
+        loop {
+            if input.is_empty() {
+                break;
+            }
+            let value = input.parse()?;
+            metas.push(value);
+            if input.is_empty() {
+                break;
+            }
+            input.parse::<Token![,]>()?;
+        }
+
+        Ok(metas)
+    }
+}
diff --git a/src/parse_quote.rs b/src/parse_quote.rs
index 9e0084c..93e2759 100644
--- a/src/parse_quote.rs
+++ b/src/parse_quote.rs
@@ -139,9 +139,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Any other types that we want `parse_quote!` to be able to parse.
 
-use NestedMeta;
 use punctuated::Punctuated;
-use token;
 #[cfg(any(feature = "full", feature = "derive"))]
 use {attr, Attribute};
 
@@ -161,13 +159,3 @@
         Self::parse_terminated(input)
     }
 }
-
-impl ParseQuote for Vec<NestedMeta> {
-    fn parse(input: ParseStream) -> Result<Self> {
-        let items = input.parse_terminated::<_, token::Comma>(<NestedMeta as Parse>::parse)?
-            .into_iter()
-            .collect();
-
-        Ok(items)
-    }
-}
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
index 79fe90f..30b06cc 100644
--- a/tests/test_meta_item.rs
+++ b/tests/test_meta_item.rs
@@ -10,7 +10,6 @@
 
 extern crate proc_macro2;
 extern crate syn;
-#[macro_use]
 extern crate quote;
 
 use proc_macro2::{Ident, Literal, Span};
@@ -304,60 +303,6 @@
     assert_eq!(expected, syn::parse_str(raw).unwrap());
 }
 
-#[test]
-fn test_parse_quote_nested_meta() {
-    let actual: Vec<NestedMeta> = parse_quote!(5);
-
-    let expected = vec![
-        NestedMeta::Literal(lit(Literal::i32_unsuffixed(5)))
-    ];
-
-    assert_eq!(expected, actual);
-
-    let actual: Vec<NestedMeta> = parse_quote!(list(name2 = 6));
-
-    let expected = vec![
-        NestedMeta::Meta(
-            MetaList {
-                ident: ident("list").into(),
-                paren_token: Default::default(),
-                nested: punctuated![NestedMeta::Meta(
-                    MetaNameValue {
-                        ident: ident("name2").into(),
-                        eq_token: Default::default(),
-                        lit: lit(Literal::i32_unsuffixed(6)),
-                    }
-                    .into(),
-                )],
-            }
-            .into(),
-        )
-    ];
-
-    assert_eq!(expected, actual);
-
-    let actual: Vec<NestedMeta> = parse_quote!(5, list(name2 = 6));
-
-    let expected = vec![
-        NestedMeta::Literal(lit(Literal::i32_unsuffixed(5))),
-        NestedMeta::Meta(
-            MetaList {
-                ident: ident("list").into(),
-                paren_token: Default::default(),
-                nested: punctuated![NestedMeta::Meta(
-                    MetaNameValue {
-                        ident: ident("name2").into(),
-                        eq_token: Default::default(),
-                        lit: lit(Literal::i32_unsuffixed(6)),
-                    }
-                    .into(),
-                )],
-            }
-            .into(),
-        )
-    ];
-}
-
 fn run_test<T: Into<Meta>>(input: &str, expected: T) {
     let attrs = Attribute::parse_outer.parse_str(input).unwrap();
     assert_eq!(attrs.len(), 1);