Untersuchungsergebnis.rs Download desUnknown {[0] [0] [0]}zum Wurzelverzeichnis wechseln
use crate::attr::Attribute;
use crate::data::{Fields, FieldsNamed, Variant};
use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
use crate::expr::Expr;
use crate::generics::{Generics, TypeParamBound};
use crate::ident::Ident;
use crate::lifetime::Lifetime;
use crate::mac::Macro;
use crate::pat::{Pat, PatType};
use crate::path::Path;
use crate::punctuated::Punctuated;
use crate::restriction::Visibility;
use crate::stmt::Block;
use crate::token;
use crate::ty::{Abi, ReturnType, Type};
use proc_macro2::TokenStream;
#[cfg(feature = "parsing")]
use std::mem;
ast_enum_of_structs! {
/// Things that can appear directly inside of a module or scope.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum Item {
/// A constant item: `const MAX: u16 = 65535`.
Const(ItemConst),
/// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
Enum(ItemEnum),
/// An `extern crate` item: `extern crate serde`.
ExternCrate(ItemExternCrate),
/// A free-standing function: `fn process(n: usize) -> Result<()> { ...
/// }`.
Fn(ItemFn),
/// A block of foreign items: `extern "C" { ... }`.
ForeignMod(ItemForeignMod),
/// An impl block providing trait or associated items: `impl<A> Trait
/// for Data<A> { ... }`.
Impl(ItemImpl),
/// A macro invocation, which includes `macro_rules!` definitions.
Macro(ItemMacro),
/// A module or module declaration: `mod m` or `mod m { ... }`.
Mod(ItemMod),
/// A static item: `static BIKE: Shed = Shed(42)`.
Static(ItemStatic),
/// A struct definition: `struct Foo<A> { x: A }`.
Struct(ItemStruct),
/// A trait definition: `pub trait Iterator { ... }`.
Trait(ItemTrait),
/// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
TraitAlias(ItemTraitAlias),
/// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
Type(ItemType),
/// A union definition: `union Foo<A, B> { x: A, y: B }`.
Union(ItemUnion),
/// A use declaration: `use std::collections::HashMap`.
Use(ItemUse),
/// Tokens forming an item not interpreted by Syn.
Verbatim(TokenStream),
// For testing exhaustiveness in downstream code, use the following idiom:
//
// match item {
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
//
// Item::Const(item) => {...}
// Item::Enum(item) => {...}
// ...
// Item::Verbatim(item) => {...}
//
// _ => { /* some sane fallback */ }
// }
//
// This way we fail your tests but don't break your library when adding
// a variant. You will be notified by a test failure when a variant is
// added, so that you can add code to handle it, but your library will
// continue to compile and work for downstream users in the interim.
}
}
ast_struct! {
/// A constant item: `const MAX: u16 = 65535`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemConst {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub const_token: Token![const],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Token![:],
pub ty: Box<Type>,
pub eq_token: Token![=],
pub expr: Box<Expr>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemEnum {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub enum_token: Token![enum],
pub ident: Ident,
pub generics: Generics,
pub brace_token: token::Brace,
pub variants: Punctuated<Variant, Token![,]>,
}
}
ast_struct! {
/// An `extern crate` item: `extern crate serde`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemExternCrate {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub extern_token: Token![extern],
pub crate_token: Token![crate],
pub ident: Ident,
pub rename: Option<(Token![as], Ident)>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A free-standing function: `fn process(n: usize) -> Result<()> { ... }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub sig: Signature,
pub block: Box<Block>,
}
}
ast_struct! {
/// A block of foreign items: `extern "C" { ... }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemForeignMod {
pub attrs: Vec<Attribute>,
pub unsafety: Option<Token![unsafe]>,
pub abi: Abi,
pub brace_token: token::Brace,
pub items: Vec<ForeignItem>,
}
}
ast_struct! {
/// An impl block providing trait or associated items: `impl<A> Trait
/// for Data<A> { ... }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemImpl {
pub attrs: Vec<Attribute>,
pub defaultness: Option<Token![default]>,
pub unsafety: Option<Token![unsafe]>,
pub impl_token: Token![impl],
pub generics: Generics,
/// Trait this impl implements.
pub trait_: Option<(Option<Token![!]>, Path, Token![for])>,
/// The Self type of the impl.
pub self_ty: Box<Type>,
pub brace_token: token::Brace,
pub items: Vec<ImplItem>,
}
}
ast_struct! {
/// A macro invocation, which includes `macro_rules!` definitions.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemMacro {
pub attrs: Vec<Attribute>,
/// The `example` in `macro_rules! example { ... }`.
pub ident: Option<Ident>,
pub mac: Macro,
pub semi_token: Option<Token![;]>,
}
}
ast_struct! {
/// A module or module declaration: `mod m` or `mod m { ... }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemMod {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub unsafety: Option<Token![unsafe]>,
pub mod_token: Token![mod],
pub ident: Ident,
pub content: Option<(token::Brace, Vec<Item>)>,
pub semi: Option<Token![;]>,
}
}
ast_struct! {
/// A static item: `static BIKE: Shed = Shed(42)`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemStatic {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub static_token: Token![static],
pub mutability: StaticMutability,
pub ident: Ident,
pub colon_token: Token![:],
pub ty: Box<Type>,
pub eq_token: Token![=],
pub expr: Box<Expr>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A struct definition: `struct Foo<A> { x: A }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemStruct {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub struct_token: Token![struct],
pub ident: Ident,
pub generics: Generics,
pub fields: Fields,
pub semi_token: Option<Token![;]>,
}
}
ast_struct! {
/// A trait definition: `pub trait Iterator { ... }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemTrait {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub unsafety: Option<Token![unsafe]>,
pub auto_token: Option<Token![auto]>,
pub restriction: Option<ImplRestriction>,
pub trait_token: Token![trait],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Option<Token![:]>,
pub supertraits: Punctuated<TypeParamBound, Token![+]>,
pub brace_token: token::Brace,
pub items: Vec<TraitItem>,
}
}
ast_struct! {
/// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemTraitAlias {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub trait_token: Token![trait],
pub ident: Ident,
pub generics: Generics,
pub eq_token: Token![=],
pub bounds: Punctuated<TypeParamBound, Token![+]>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemType {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub eq_token: Token![=],
pub ty: Box<Type>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A union definition: `union Foo<A, B> { x: A, y: B }`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemUnion {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub union_token: Token![union],
pub ident: Ident,
pub generics: Generics,
pub fields: FieldsNamed,
}
}
ast_struct! {
/// A use declaration: `use std::collections::HashMap`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ItemUse {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub use_token: Token![use],
pub leading_colon: Option<Token![::]>,
pub tree: UseTree,
pub semi_token: Token![;],
}
}
impl Item {
#[cfg(feature = "parsing")]
pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
match self {
Item::Const(ItemConst { attrs, .. })
| Item::Enum(ItemEnum { attrs, .. })
| Item::ExternCrate(ItemExternCrate { attrs, .. })
| Item::Fn(ItemFn { attrs, .. })
| Item::ForeignMod(ItemForeignMod { attrs, .. })
| Item::Impl(ItemImpl { attrs, .. })
| Item::Macro(ItemMacro { attrs, .. })
| Item::Mod(ItemMod { attrs, .. })
| Item::Static(ItemStatic { attrs, .. })
| Item::Struct(ItemStruct { attrs, .. })
| Item::Trait(ItemTrait { attrs, .. })
| Item::TraitAlias(ItemTraitAlias { attrs, .. })
| Item::Type(ItemType { attrs, .. })
| Item::Union(ItemUnion { attrs, .. })
| Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new),
Item::Verbatim(_) => Vec::new(),
}
}
}
impl From<DeriveInput> for Item {
fn from(input: DeriveInput) -> Item {
match input.data {
Data::Struct(data) => Item::Struct(ItemStruct {
attrs: input.attrs,
vis: input.vis,
struct_token: data.struct_token,
ident: input.ident,
generics: input.generics,
fields: data.fields,
semi_token: data.semi_token,
}),
Data::Enum(data) => Item::Enum(ItemEnum {
attrs: input.attrs,
vis: input.vis,
enum_token: data.enum_token,
ident: input.ident,
generics: input.generics,
brace_token: data.brace_token,
variants: data.variants,
}),
Data::Union(data) => Item::Union(ItemUnion {
attrs: input.attrs,
vis: input.vis,
union_token: data.union_token,
ident: input.ident,
generics: input.generics,
fields: data.fields,
}),
}
}
}
impl From<ItemStruct> for DeriveInput {
fn from(input: ItemStruct) -> DeriveInput {
DeriveInput {
attrs: input.attrs,
vis: input.vis,
ident: input.ident,
generics: input.generics,
data: Data::Struct(DataStruct {
struct_token: input.struct_token,
fields: input.fields,
semi_token: input.semi_token,
}),
}
}
}
impl From<ItemEnum> for DeriveInput {
fn from(input: ItemEnum) -> DeriveInput {
DeriveInput {
attrs: input.attrs,
vis: input.vis,
ident: input.ident,
generics: input.generics,
data: Data::Enum(DataEnum {
enum_token: input.enum_token,
brace_token: input.brace_token,
variants: input.variants,
}),
}
}
}
impl From<ItemUnion> for DeriveInput {
fn from(input: ItemUnion) -> DeriveInput {
DeriveInput {
attrs: input.attrs,
vis: input.vis,
ident: input.ident,
generics: input.generics,
data: Data::Union(DataUnion {
union_token: input.union_token,
fields: input.fields,
}),
}
}
}
ast_enum_of_structs! {
/// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub enum UseTree {
/// A path prefix of imports in a `use` item: `std::...`.
Path(UsePath),
/// An identifier imported by a `use` item: `HashMap`.
Name(UseName),
/// An renamed identifier imported by a `use` item: `HashMap as Map`.
Rename(UseRename),
/// A glob import in a `use` item: `*`.
Glob(UseGlob),
/// A braced group of imports in a `use` item: `{A, B, C}`.
Group(UseGroup),
}
}
ast_struct! {
/// A path prefix of imports in a `use` item: `std::...`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct UsePath {
pub ident: Ident,
pub colon2_token: Token![::],
pub tree: Box<UseTree>,
}
}
ast_struct! {
/// An identifier imported by a `use` item: `HashMap`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct UseName {
pub ident: Ident,
}
}
ast_struct! {
/// An renamed identifier imported by a `use` item: `HashMap as Map`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct UseRename {
pub ident: Ident,
pub as_token: Token![as],
pub rename: Ident,
}
}
ast_struct! {
/// A glob import in a `use` item: `*`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct UseGlob {
pub star_token: Token![*],
}
}
ast_struct! {
/// A braced group of imports in a `use` item: `{A, B, C}`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct UseGroup {
pub brace_token: token::Brace,
pub items: Punctuated<UseTree, Token![,]>,
}
}
ast_enum_of_structs! {
/// An item within an `extern` block.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum ForeignItem {
/// A foreign function in an `extern` block.
Fn(ForeignItemFn),
/// A foreign static item in an `extern` block: `static ext: u8`.
Static(ForeignItemStatic),
/// A foreign type in an `extern` block: `type void`.
Type(ForeignItemType),
/// A macro invocation within an extern block.
Macro(ForeignItemMacro),
/// Tokens in an `extern` block not interpreted by Syn.
Verbatim(TokenStream),
// For testing exhaustiveness in downstream code, use the following idiom:
//
// match item {
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
//
// ForeignItem::Fn(item) => {...}
// ForeignItem::Static(item) => {...}
// ...
// ForeignItem::Verbatim(item) => {...}
//
// _ => { /* some sane fallback */ }
// }
//
// This way we fail your tests but don't break your library when adding
// a variant. You will be notified by a test failure when a variant is
// added, so that you can add code to handle it, but your library will
// continue to compile and work for downstream users in the interim.
}
}
ast_struct! {
/// A foreign function in an `extern` block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ForeignItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub sig: Signature,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A foreign static item in an `extern` block: `static ext: u8`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ForeignItemStatic {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub static_token: Token![static],
pub mutability: StaticMutability,
pub ident: Ident,
pub colon_token: Token![:],
pub ty: Box<Type>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A foreign type in an `extern` block: `type void`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ForeignItemType {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A macro invocation within an extern block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ForeignItemMacro {
pub attrs: Vec<Attribute>,
pub mac: Macro,
pub semi_token: Option<Token![;]>,
}
}
ast_enum_of_structs! {
/// An item declaration within the definition of a trait.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum TraitItem {
/// An associated constant within the definition of a trait.
Const(TraitItemConst),
/// An associated function within the definition of a trait.
Fn(TraitItemFn),
/// An associated type within the definition of a trait.
Type(TraitItemType),
/// A macro invocation within the definition of a trait.
Macro(TraitItemMacro),
/// Tokens within the definition of a trait not interpreted by Syn.
Verbatim(TokenStream),
// For testing exhaustiveness in downstream code, use the following idiom:
//
// match item {
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
//
// TraitItem::Const(item) => {...}
// TraitItem::Fn(item) => {...}
// ...
// TraitItem::Verbatim(item) => {...}
//
// _ => { /* some sane fallback */ }
// }
//
// This way we fail your tests but don't break your library when adding
// a variant. You will be notified by a test failure when a variant is
// added, so that you can add code to handle it, but your library will
// continue to compile and work for downstream users in the interim.
}
}
ast_struct! {
/// An associated constant within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemConst {
pub attrs: Vec<Attribute>,
pub const_token: Token![const],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Token![:],
pub ty: Type,
pub default: Option<(Token![=], Expr)>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// An associated function within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemFn {
pub attrs: Vec<Attribute>,
pub sig: Signature,
pub default: Option<Block>,
pub semi_token: Option<Token![;]>,
}
}
ast_struct! {
/// An associated type within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemType {
pub attrs: Vec<Attribute>,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Option<Token![:]>,
pub bounds: Punctuated<TypeParamBound, Token![+]>,
pub default: Option<(Token![=], Type)>,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A macro invocation within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemMacro {
pub attrs: Vec<Attribute>,
pub mac: Macro,
pub semi_token: Option<Token![;]>,
}
}
ast_enum_of_structs! {
/// An item within an impl block.
///
/// # Syntax tree enum
///
/// This type is a [syntax tree enum].
///
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum ImplItem {
/// An associated constant within an impl block.
Const(ImplItemConst),
/// An associated function within an impl block.
Fn(ImplItemFn),
/// An associated type within an impl block.
Type(ImplItemType),
/// A macro invocation within an impl block.
Macro(ImplItemMacro),
/// Tokens within an impl block not interpreted by Syn.
Verbatim(TokenStream),
// For testing exhaustiveness in downstream code, use the following idiom:
//
// match item {
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
//
// ImplItem::Const(item) => {...}
// ImplItem::Fn(item) => {...}
// ...
// ImplItem::Verbatim(item) => {...}
//
// _ => { /* some sane fallback */ }
// }
//
// This way we fail your tests but don't break your library when adding
// a variant. You will be notified by a test failure when a variant is
// added, so that you can add code to handle it, but your library will
// continue to compile and work for downstream users in the interim.
}
}
ast_struct! {
/// An associated constant within an impl block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ImplItemConst {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: Option<Token![default]>,
pub const_token: Token![const],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Token![:],
pub ty: Type,
pub eq_token: Token![=],
pub expr: Expr,
pub semi_token: Token![;],
}
}
ast_struct! {
/// An associated function within an impl block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ImplItemFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: Option<Token![default]>,
pub sig: Signature,
pub block: Block,
}
}
ast_struct! {
/// An associated type within an impl block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ImplItemType {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: Option<Token![default]>,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub eq_token: Token![=],
pub ty: Type,
pub semi_token: Token![;],
}
}
ast_struct! {
/// A macro invocation within an impl block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ImplItemMacro {
pub attrs: Vec<Attribute>,
pub mac: Macro,
pub semi_token: Option<Token![;]>,
}
}
ast_struct! {
/// A function signature in a trait or implementation: `unsafe fn
/// initialize(&self)`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
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,
}
}
impl Signature {
/// A method's `self` receiver, such as `&self` or `self: Box<Self>`.
pub fn receiver(&self) -> Option<&Receiver> {
let arg = self.inputs.first()?;
match arg {
FnArg::Receiver(receiver) => Some(receiver),
FnArg::Typed(_) => None,
}
}
}
ast_enum_of_structs! {
/// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub enum FnArg {
/// The `self` argument of an associated method.
Receiver(Receiver),
/// A function argument accepted by pattern and type.
Typed(PatType),
}
}
ast_struct! {
/// The `self` argument of an associated method.
///
/// If `colon_token` is present, the receiver is written with an explicit
/// type such as `self: Box<Self>`. If `colon_token` is absent, the receiver
/// is written in shorthand such as `self` or `&self` or `&mut self`. In the
/// shorthand case, the type in `ty` is reconstructed as one of `Self`,
/// `&Self`, or `&mut Self`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct Receiver {
pub attrs: Vec<Attribute>,
pub reference: Option<(Token![&], Option<Lifetime>)>,
pub mutability: Option<Token![mut]>,
pub self_token: Token![self],
pub colon_token: Option<Token![:]>,
pub ty: Box<Type>,
}
}
impl Receiver {
pub fn lifetime(&self) -> Option<&Lifetime> {
self.reference.as_ref()?.1.as_ref()
}
}
ast_struct! {
/// The variadic argument of a foreign function.
///
/// ```rust
/// # struct c_char;
/// # struct c_int;
/// #
/// extern "C" {
/// fn printf(format: *const c_char, ...) -> c_int;
/// // ^^^
/// }
/// ```
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct Variadic {
pub attrs: Vec<Attribute>,
pub pat: Option<(Box<Pat>, Token![:])>,
pub dots: Token![...],
pub comma: Option<Token![,]>,
}
}
ast_enum! {
/// The mutability of an `Item::Static` or `ForeignItem::Static`.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum StaticMutability {
Mut(Token![mut]),
None,
}
}
ast_enum! {
/// Unused, but reserved for RFC 3323 restrictions.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum ImplRestriction {}
// TODO:
https://rust-lang.github.io/rfcs/3323-restrictions.html
//
// pub struct ImplRestriction {
// pub impl_token: Token![impl],
// pub paren_token: token::Paren,
// pub in_token: Option<Token![in]>,
// pub path: Box<Path>,
// }
}
#[cfg(feature = "parsing")]
pub(crate) mod parsing {
use crate::attr::{self, Attribute};
use crate::derive;
use crate::error::{Error, Result};
use crate::expr::Expr;
use crate::ext::IdentExt as _;
use crate::generics::{Generics, TypeParamBound};
use crate::ident::Ident;
use crate::item::{
FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemTy
pe,
ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item, ItemConst,
ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
};
use crate::lifetime::Lifetime;
use crate::lit::LitStr;
use crate::mac::{self, Macro};
use crate::parse::discouraged::Speculative as _;
use crate::parse::{Parse, ParseBuffer, ParseStream};
use crate::pat::{Pat, PatType, PatWild};
use crate::path::Path;
use crate::punctuated::Punctuated;
use crate::restriction::Visibility;
use crate::stmt::Block;
use crate::token;
use crate::ty::{Abi, ReturnType, Type, TypePath, TypeReference};
use crate::verbatim;
use proc_macro2::TokenStream;
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let begin = input.fork();
let attrs = input.call(Attribute::parse_outer)?;
parse_rest_of_item(begin, attrs, input)
}
}
pub(crate) fn parse_rest_of_item(
begin: ParseBuffer,
mut attrs: Vec<Attribute>,
input: ParseStream,
) -> Result<Item> {
let ahead = input.fork();
let vis: Visibility = ahead.parse()?;
let lookahead = ahead.lookahead1();
let allow_safe = false;
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
if input.peek(Token![;]) {
input.parse::<Token![;]>()?;
Ok(Item::Verbatim(verbatim::between(&begin, input)))
} else {
parse_rest_of_fn(input, Vec::new(), vis, sig).map(Item::Fn)
}
} else if lookahead.peek(Token![extern]) {
ahead.parse::<Token![extern]>()?;
let lookahead = ahead.lookahead1();
if lookahead.peek(Token![crate]) {
input.parse().map(Item::ExternCrate)
} else if lookahead.peek(token::Brace) {
input.parse().map(Item::ForeignMod)
} else if lookahead.peek(LitStr) {
ahead.parse::<LitStr>()?;
let lookahead = ahead.lookahead1();
if lookahead.peek(token::Brace) {
input.parse().map(Item::ForeignMod)
} else {
Err(lookahead.error())
}
} else {
Err(lookahead.error())
}
} else if lookahead.peek(Token![use]) {
let allow_crate_root_in_path = true;
match parse_item_use(input, allow_crate_root_in_path)? {
Some(item_use) => Ok(Item::Use(item_use)),
None => Ok(Item::Verbatim(verbatim::between(&begin, input))),
}
} else if lookahead.peek(Token![static]) {
let vis = input.parse()?;
let static_token = input.parse()?;
let mutability = input.parse()?;
let ident = input.parse()?;
if input.peek(Token![=]) {
input.parse::<Token![=]>()?;
input.parse::<Expr>()?;
input.parse::<Token![;]>()?;
Ok(Item::Verbatim(verbatim::between(&begin, input)))
} else {
let colon_token = input.parse()?;
let ty = input.parse()?;
if input.peek(Token![;]) {
input.parse::<Token![;]>()?;
Ok(Item::Verbatim(verbatim::between(&begin, input)))
} else {
Ok(Item::Static(ItemStatic {
attrs: Vec::new(),
vis,
static_token,
mutability,
ident,
colon_token,
ty,
eq_token: input.parse()?,
expr: input.parse()?,
semi_token: input.parse()?,
}))
}
}
} else if lookahead.peek(Token![const]) {
let vis = input.parse()?;
let const_token: Token![const] = input.parse()?;
let lookahead = input.lookahead1();
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
input.call(Ident::parse_any)?
} else {
return Err(lookahead.error());
};
let mut generics: Generics = input.parse()?;
let colon_token = input.parse()?;
let ty = input.parse()?;
let value = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
let expr: Expr = input.parse()?;
Some((eq_token, expr))
} else {
None
};
generics.where_clause = input.parse()?;
let semi_token: Token![;] = input.parse()?;
match value {
Some((eq_token, expr))
if generics.lt_token.is_none() && generics.where_clause.is_none() =>
{
Ok(Item::Const(ItemConst {
attrs: Vec::new(),
vis,
const_token,
ident,
generics,
colon_token,
ty,
eq_token,
expr: Box::new(expr),
semi_token,
}))
}
_ => Ok(Item::Verbatim(verbatim::between(&begin, input))),
}
} else if lookahead.peek(Token![unsafe]) {
ahead.parse::<Token![unsafe]>()?;
let lookahead = ahead.lookahead1();
if lookahead.peek(Token![trait])
|| lookahead.peek(Token![auto]) && ahead.peek2(Token![trait])
{
input.parse().map(Item::Trait)
} else if lookahead.peek(Token![impl]) {
let allow_verbatim_impl = true;
if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
Ok(Item::Impl(item))
} else {
Ok(Item::Verbatim(verbatim::between(&begin, input)))
}
} else if lookahead.peek(Token![extern]) {
input.parse().map(Item::ForeignMod)
} else if lookahead.peek(Token![mod]) {
input.parse().map(Item::Mod)
} else {
Err(lookahead.error())
}
} else if lookahead.peek(Token![mod]) {
input.parse().map(Item::Mod)
} else if lookahead.peek(Token![type]) {
parse_item_type(begin, input)
} else if lookahead.peek(Token![struct]) {
input.parse().map(Item::Struct)
} else if lookahead.peek(Token![enum]) {
input.parse().map(Item::Enum)
} else if lookahead.peek(Token![union]) && ahead.peek2(Ident) {
input.parse().map(Item::Union)
} else if lookahead.peek(Token![trait]) {
input.call(parse_trait_or_trait_alias)
} else if lookahead.peek(Token![auto]) && ahead.peek2(Token![trait]) {
input.parse().map(Item::Trait)
} else if lookahead.peek(Token![impl])
|| lookahead.peek(Token![default]) && !ahead.peek2(Token![!])
{
let allow_verbatim_impl = true;
if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
Ok(Item::Impl(item))
} else {
Ok(Item::Verbatim(verbatim::between(&begin, input)))
}
} else if lookahead.peek(Token![macro]) {
input.advance_to(&ahead);
parse_macro2(begin, vis, input)
} else if vis.is_inherited()
&& (lookahead.peek(Ident)
|| lookahead.peek(Token![self])
|| lookahead.peek(Token![super])
|| lookahead.peek(Token![crate])
|| lookahead.peek(Token![::]))
{
input.parse().map(Item::Macro)
} else {
Err(lookahead.error())
}?;
attrs.extend(item.replace_attrs(Vec::new()));
item.replace_attrs(attrs);
Ok(item)
}
struct FlexibleItemType {
vis: Visibility,
defaultness: Option<Token![default]>,
type_token: Token![type],
ident: Ident,
generics: Generics,
colon_token: Option<Token![:]>,
bounds: Punctuated<TypeParamBound, Token![+]>,
ty: Option<(Token![=], Type)>,
semi_token: Token![;],
}
enum TypeDefaultness {
Optional,
Disallowed,
}
enum WhereClauseLocation {
// type Ty<T> where T: 'static = T;
BeforeEq,
// type Ty<T> = T where T: 'static;
AfterEq,
// TODO: goes away once the migration period on rust-lang/rust#89122 is over
Both,
}
impl FlexibleItemType {
fn parse(
input: ParseStream,
allow_defaultness: TypeDefaultness,
where_clause_location: WhereClauseLocation,
) -> Result<Self> {
let vis: Visibility = input.parse()?;
let defaultness: Option<Token![default]> = match allow_defaultness {
TypeDefaultness::Optional => input.parse()?,
TypeDefaultness::Disallowed => None,
};
let type_token: Token![type] = input.parse()?;
let ident: Ident = input.parse()?;
let mut generics: Generics = input.parse()?;
let (colon_token, bounds) = Self::parse_optional_bounds(input)?;
match where_clause_location {
WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
generics.where_clause = input.parse()?;
}
WhereClauseLocation::AfterEq => {}
}
let ty = Self::parse_optional_definition(input)?;
match where_clause_location {
WhereClauseLocation::AfterEq | WhereClauseLocation::Both
if generics.where_clause.is_none() =>
{
generics.where_clause = input.parse()?;
}
_ => {}
}
let semi_token: Token![;] = input.parse()?;
Ok(FlexibleItemType {
vis,
defaultness,
type_token,
ident,
generics,
colon_token,
bounds,
ty,
semi_token,
})
}
fn parse_optional_bounds(
input: ParseStream,
) -> Result<(Option<Token![:]>, Punctuated<TypeParamBound, Token![+]>)> {
let colon_token: Option<Token![:]> = input.parse()?;
let mut bounds = Punctuated::new();
if colon_token.is_some() {
loop {
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
bounds.push_value({
let allow_precise_capture = false;
let allow_tilde_const = true;
TypeParamBound::parse_single(
input,
allow_precise_capture,
allow_tilde_const,
)?
});
if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
break;
}
bounds.push_punct(input.parse::<Token![+]>()?);
}
}
Ok((colon_token, bounds))
}
fn parse_optional_definition(input: ParseStream) -> Result<Option<(Token![=], Type)>> {
let eq_token: Option<Token![=]> = input.parse()?;
if let Some(eq_token) = eq_token {
let definition: Type = input.parse()?;
Ok(Some((eq_token, definition)))
} else {
Ok(None)
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemMacro {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let path = input.call(Path::parse_mod_style)?;
let bang_token: Token![!] = input.parse()?;
let ident: Option<Ident> = if input.peek(Token![try]) {
input.call(Ident::parse_any).map(Some)
} else {
input.parse()
}?;
let (delimiter, tokens) = input.call(mac::parse_delimiter)?;
let semi_token: Option<Token![;]> = if !delimiter.is_brace() {
Some(input.parse()?)
} else {
None
};
Ok(ItemMacro {
attrs,
ident,
mac: Macro {
path,
bang_token,
delimiter,
tokens,
},
semi_token,
})
}
}
fn parse_macro2(begin: ParseBuffer, _vis: Visibility, input: ParseStream) -> Result<Item> {
input.parse::<Token![macro]>()?;
input.parse::<Ident>()?;
let mut lookahead = input.lookahead1();
if lookahead.peek(token::Paren) {
let paren_content;
parenthesized!(paren_content in input);
paren_content.parse::<TokenStream>()?;
lookahead = input.lookahead1();
}
if lookahead.peek(token::Brace) {
let brace_content;
braced!(brace_content in input);
brace_content.parse::<TokenStream>()?;
} else {
return Err(lookahead.error());
}
Ok(Item::Verbatim(verbatim::between(&begin, input)))
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemExternCrate {
fn parse(input: ParseStream) -> Result<Self> {
Ok(ItemExternCrate {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
extern_token: input.parse()?,
crate_token: input.parse()?,
ident: {
if input.peek(Token![self]) {
input.call(Ident::parse_any)?
} else {
input.parse()?
}
},
rename: {
if input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
let rename: Ident = if input.peek(Token![_]) {
Ident::from(input.parse::<Token![_]>()?)
} else {
input.parse()?
};
Some((as_token, rename))
} else {
None
}
},
semi_token: input.parse()?,
})
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemUse {
fn parse(input: ParseStream) -> Result<Self> {
let allow_crate_root_in_path = false;
parse_item_use(input, allow_crate_root_in_path).map(Option::unwrap)
}
}
fn parse_item_use(
input: ParseStream,
allow_crate_root_in_path: bool,
) -> Result<Option<ItemUse>> {
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let use_token: Token![use] = input.parse()?;
let leading_colon: Option<Token![::]> = input.parse()?;
let tree = parse_use_tree(input, allow_crate_root_in_path && leading_colon.is_none())?;
let semi_token: Token![;] = input.parse()?;
let tree = match tree {
Some(tree) => tree,
None => return Ok(None),
};
Ok(Some(ItemUse {
attrs,
vis,
use_token,
leading_colon,
tree,
semi_token,
}))
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for UseTree {
fn parse(input: ParseStream) -> Result<UseTree> {
let allow_crate_root_in_path = false;
parse_use_tree(input, allow_crate_root_in_path).map(Option::unwrap)
}
}
fn parse_use_tree(
input: ParseStream,
allow_crate_root_in_path: bool,
) -> Result<Option<UseTree>> {
let lookahead = input.lookahead1();
if lookahead.peek(Ident)
|| lookahead.peek(Token![self])
|| lookahead.peek(Token![super])
|| lookahead.peek(Token![crate])
|| lookahead.peek(Token![try])
{
let ident = input.call(Ident::parse_any)?;
if input.peek(Token![::]) {
Ok(Some(UseTree::Path(UsePath {
ident,
colon2_token: input.parse()?,
tree: Box::new(input.parse()?),
})))
} else if input.peek(Token![as]) {
Ok(Some(UseTree::Rename(UseRename {
ident,
as_token: input.parse()?,
rename: {
if input.peek(Ident) {
input.parse()?
} else if input.peek(Token![_]) {
Ident::from(input.parse::<Token![_]>()?)
} else {
return Err(input.error("expected identifier or underscore"));
}
},
})))
} else {
Ok(Some(UseTree::Name(UseName { ident })))
}
} else if lookahead.peek(Token![*]) {
Ok(Some(UseTree::Glob(UseGlob {
star_token: input.parse()?,
})))
} else if lookahead.peek(token::Brace) {
let content;
let brace_token = braced!(content in input);
let mut items = Punctuated::new();
let mut has_any_crate_root_in_path = false;
loop {
if content.is_empty() {
break;
}
let this_tree_starts_with_crate_root =
allow_crate_root_in_path && content.parse::<Option<Token![::]>>()?.is_some();
has_any_crate_root_in_path |= this_tree_starts_with_crate_root;
match parse_use_tree(
&content,
allow_crate_root_in_path && !this_tree_starts_with_crate_root,
)? {
Some(tree) if !has_any_crate_root_in_path => items.push_value(tree),
_ => has_any_crate_root_in_path = true,
}
if content.is_empty() {
break;
}
let comma: Token![,] = content.parse()?;
if !has_any_crate_root_in_path {
items.push_punct(comma);
}
}
if has_any_crate_root_in_path {
Ok(None)
} else {
Ok(Some(UseTree::Group(UseGroup { brace_token, items })))
}
} else {
Err(lookahead.error())
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemStatic {
fn parse(input: ParseStream) -> Result<Self> {
Ok(ItemStatic {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
static_token: input.parse()?,
mutability: input.parse()?,
ident: input.parse()?,
colon_token: input.parse()?,
ty: input.parse()?,
eq_token: input.parse()?,
expr: input.parse()?,
semi_token: input.parse()?,
})
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemConst {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let const_token: Token![const] = input.parse()?;
let lookahead = input.lookahead1();
let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
input.call(Ident::parse_any)?
} else {
return Err(lookahead.error());
};
let colon_token: Token![:] = input.parse()?;
let ty: Type = input.parse()?;
let eq_token: Token![=] = input.parse()?;
let expr: Expr = input.parse()?;
let semi_token: Token![;] = input.parse()?;
Ok(ItemConst {
attrs,
vis,
const_token,
ident,
generics: Generics::default(),
colon_token,
ty: Box::new(ty),
eq_token,
expr: Box::new(expr),
semi_token,
})
}
}
fn peek_signature(input: ParseStream, allow_safe: bool) -> bool {
let fork = input.fork();
fork.parse::<Option<Token![const]>>().is_ok()
&& fork.parse::<Option<Token![async]>>().is_ok()
&& ((allow_safe
&& token::parsing::peek_keyword(fork.cursor(), "safe")
&& token::parsing::keyword(&fork, "safe").is_ok())
|| fork.parse::<Option<Token![unsafe]>>().is_ok())
&& fork.parse::<Option<Abi>>().is_ok()
&& fork.peek(Token![fn])
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for Signature {
fn parse(input: ParseStream) -> Result<Self> {
let allow_safe = false;
parse_signature(input, allow_safe).map(Option::unwrap)
}
}
fn parse_signature(input: ParseStream, allow_safe: bool) -> Result<Option<Signature>> {
let constness: Option<Token![const]> = input.parse()?;
let asyncness: Option<Token![async]> = input.parse()?;
let unsafety: Option<Token![unsafe]> = input.parse()?;
let safe = allow_safe
&& unsafety.is_none()
&& token::parsing::peek_keyword(input.cursor(), "safe");
if safe {
token::parsing::keyword(input, "safe")?;
}
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, variadic) = parse_fn_args(&content)?;
let output: ReturnType = input.parse()?;
generics.where_clause = input.parse()?;
Ok(if safe {
None
} else {
Some(Signature {
constness,
asyncness,
unsafety,
abi,
fn_token,
ident,
generics,
paren_token,
inputs,
variadic,
output,
})
})
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemFn {
fn parse(input: ParseStream) -> Result<Self> {
let outer_attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
parse_rest_of_fn(input, outer_attrs, vis, sig)
}
}
fn parse_rest_of_fn(
input: ParseStream,
mut attrs: Vec<Attribute>,
vis: Visibility,
sig: Signature,
) -> Result<ItemFn> {
let content;
let brace_token = braced!(content in input);
attr::parsing::parse_inner(&content, &mut attrs)?;
let stmts = content.call(Block::parse_within)?;
Ok(ItemFn {
attrs,
vis,
sig,
block: Box::new(Block { brace_token, stmts }),
})
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for FnArg {
fn parse(input: ParseStream) -> Result<Self> {
let allow_variadic = false;
let attrs = input.call(Attribute::parse_outer)?;
match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
FnArgOrVariadic::FnArg(arg) => Ok(arg),
FnArgOrVariadic::Variadic(_) => unreachable!(),
}
}
}
enum FnArgOrVariadic {
FnArg(FnArg),
Variadic(Variadic),
}
fn parse_fn_arg_or_variadic(
input: ParseStream,
attrs: Vec<Attribute>,
allow_variadic: bool,
) -> Result<FnArgOrVariadic> {
let ahead = input.fork();
if let Ok(mut receiver) = ahead.parse::<Receiver>() {
input.advance_to(&ahead);
receiver.attrs = attrs;
return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver)));
}
// Hack to parse pre-2018 syntax in
// test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
// because the rest of the test case is valuable.
if input.peek(Ident) && input.peek2(Token![<]) {
let span = input.fork().parse::<Ident>()?.span();
return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
attrs,
pat: Box::new(Pat::Wild(PatWild {
attrs: Vec::new(),
underscore_token: Token,
})),
colon_token: Token,
ty: input.parse()?,
})));
}
let pat = Box::new(Pat::parse_single(input)?);
let colon_token: Token![:] = input.parse()?;
if allow_variadic {
if let Some(dots) = input.parse::<Option<Token![...]>>()? {
return Ok(FnArgOrVariadic::Variadic(Variadic {
attrs,
pat: Some((pat, colon_token)),
dots,
comma: None,
}));
}
}
Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
attrs,
pat,
colon_token,
ty: input.parse()?,
})))
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for Receiver {
fn parse(input: ParseStream) -> Result<Self> {
let reference = if input.peek(Token![&]) {
let ampersand: Token![&] = input.parse()?;
let lifetime: Option<Lifetime> = input.parse()?;
Some((ampersand, lifetime))
} else {
None
};
let mutability: Option<Token![mut]> = input.parse()?;
let self_token: Token![self] = input.parse()?;
let colon_token: Option<Token![:]> = if reference.is_some() {
None
} else {
input.parse()?
};
let ty: Type = if colon_token.is_some() {
input.parse()?
} else {
let mut ty = Type::Path(TypePath {
qself: None,
path: Path::from(Ident::new("Self", self_token.span)),
});
if let Some((ampersand, lifetime)) = reference.as_ref() {
ty = Type::Reference(TypeReference {
and_token: Token,
lifetime: lifetime.clone(),
mutability: mutability.as_ref().map(|m| Token),
elem: Box::new(ty),
});
}
ty
};
Ok(Receiver {
attrs: Vec::new(),
reference,
mutability,
self_token,
colon_token,
ty: Box::new(ty),
})
}
}
fn parse_fn_args(
input: ParseStream,
) -> Result<(Punctuated<FnArg, Token![,]>, Option<Variadic>)> {
let mut args = Punctuated::new();
let mut variadic = None;
let mut has_receiver = false;
while !input.is_empty() {
let attrs = input.call(Attribute::parse_outer)?;
if let Some(dots) = input.parse::<Option<Token![...]>>()? {
variadic = Some(Variadic {
attrs,
pat: None,
dots,
comma: if input.is_empty() {
None
} else {
Some(input.parse()?)
},
});
break;
}
let allow_variadic = true;
let arg = match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
FnArgOrVariadic::FnArg(arg) => arg,
FnArgOrVariadic::Variadic(arg) => {
variadic = Some(Variadic {
comma: if input.is_empty() {
None
} else {
Some(input.parse()?)
},
..arg
});
break;
}
};
match &arg {
FnArg::Receiver(receiver) if has_receiver => {
return Err(Error::new(
receiver.self_token.span,
"unexpected second method receiver",
));
}
FnArg::Receiver(receiver) if !args.is_empty() => {
return Err(Error::new(
receiver.self_token.span,
"unexpected method receiver",
));
}
FnArg::Receiver(_) => has_receiver = true,
FnArg::Typed(_) => {}
}
args.push_value(arg);
if input.is_empty() {
break;
}
let comma: Token![,] = input.parse()?;
args.push_punct(comma);
}
Ok((args, variadic))
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemMod {
fn parse(input: ParseStream) -> Result<Self> {
let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let unsafety: Option<Token![unsafe]> = input.parse()?;
let mod_token: Token![mod] = input.parse()?;
let ident: Ident = if input.peek(Token![try]) {
input.call(Ident::parse_any)
} else {
input.parse()
}?;
let lookahead = input.lookahead1();
if lookahead.peek(Token![;]) {
Ok(ItemMod {
attrs,
vis,
unsafety,
mod_token,
ident,
content: None,
semi: Some(input.parse()?),
})
} else if lookahead.peek(token::Brace) {
let content;
let brace_token = braced!(content in input);
attr::parsing::parse_inner(&content, &mut attrs)?;
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(ItemMod {
attrs,
vis,
unsafety,
mod_token,
ident,
content: Some((brace_token, items)),
semi: None,
})
} else {
Err(lookahead.error())
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ItemForeignMod {
fn parse(input: ParseStream) -> Result<Self> {
let mut attrs = input.call(Attribute::parse_outer)?;
let unsafety: Option<Token![unsafe]> = input.parse()?;
let abi: Abi = input.parse()?;
let content;
let brace_token = braced!(content in input);
attr::parsing::parse_inner(&content, &mut attrs)?;
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(ItemForeignMod {
attrs,
unsafety,
abi,
brace_token,
items,
})
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for ForeignItem {
fn parse(input: ParseStream) -> Result<Self> {
let begin = input.fork();
let mut attrs = input.call(Attribute::parse_outer)?;
let ahead = input.fork();
let vis: Visibility = ahead.parse()?;
let lookahead = ahead.lookahead1();
let allow_safe = true;
let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
let vis: Visibility = input.parse()?;
let sig = parse_signature(input, allow_safe)?;
let has_safe = sig.is_none();
let has_body = input.peek(token::Brace);
let semi_token: Option<Token![;]> = if has_body {
let content;
braced!(content in input);
content.call(Attribute::parse_inner)?;
content.call(Block::parse_within)?;
None
} else {
Some(input.parse()?)
};
if has_safe || has_body {
Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
} else {
Ok(ForeignItem::Fn(ForeignItemFn {
attrs: Vec::new(),
vis,
sig: sig.unwrap(),
semi_token: semi_token.unwrap(),
}))
}
} else if lookahead.peek(Token![static])
|| ((ahead.peek(Token![unsafe])
|| token::parsing::peek_keyword(ahead.cursor(), "safe"))
&& ahead.peek2(Token![static]))
{
let vis = input.parse()?;
let unsafety: Option<Token![unsafe]> = input.parse()?;
let safe =
unsafety.is_none() && token::parsing::peek_keyword(input.cursor(), "safe");
if safe {
token::parsing::keyword(input, "safe")?;
}
let static_token = input.parse()?;
let mutability = input.parse()?;
let ident = input.parse()?;
let colon_token = input.parse()?;
let ty = input.parse()?;
let has_value = input.peek(Token![=]);
if has_value {
input.parse::<Token![=]>()?;
input.parse::<Expr>()?;
}
let semi_token: Token![;] = input.parse()?;
if unsafety.is_some() || safe || has_value {
Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
} else {
Ok(ForeignItem::Static(ForeignItemStatic {
attrs: Vec::new(),
vis,
static_token,
mutability,
ident,
colon_token,
ty,
semi_token,
}))
}
} else if lookahead.peek(Token![type]) {
parse_foreign_item_type(begin, input)
} else if vis.is_inherited()
&& (lookahead.peek(Ident)
|| lookahead.peek(Token![self])
|| lookahead.peek(Token![super])
|| lookahead.peek(Token![crate])
|| lookahead.peek(Token![::]))
{
input.parse().map(ForeignItem::Macro)
} else {
Err(lookahead.error())
}?;
let item_attrs = match &mut item {
ForeignItem::Fn(item) => &mut item.attrs,
ForeignItem::Static(item) => &mut item.attrs,
--> --------------------
--> maximum size reached
--> --------------------