,
}
}
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.
///
///
///
/// Important: see [Compatibility notes][crate#verbatim-variants].
///
///
Verbatim(TokenStream),
}
}
ast_struct! {
/// A foreign function in an `extern` block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ForeignItemFn {
pub attrs: Vec,
pub vis: Visibility,
/// (Non-exhaustive) Additional optional information about a function.
pub modifiers: FnModifiers,
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,
pub vis: Visibility,
pub safety: Safety,
pub static_token: Token![static],
pub mutability: StaticMutability,
pub ident: Ident,
pub colon_token: Token![:],
pub ty: Box,
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,
pub vis: Visibility,
/// (Non-exhaustive) Additional optional information about a type alias.
pub modifiers: TypeModifiers,
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,
pub mac: Macro,
pub semi_token: Option,
}
}
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.
///
///
///
/// Important: see [Compatibility notes][crate#verbatim-variants].
///
///
Verbatim(TokenStream),
}
}
ast_struct! {
/// An associated constant within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemConst {
pub attrs: Vec,
/// (Non-exhaustive) Additional optional information about a const item.
pub modifiers: ConstModifiers,
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,
/// (Non-exhaustive) Additional optional information about a function.
pub modifiers: FnModifiers,
pub sig: Signature,
pub default: Option,
pub semi_token: Option,
}
}
ast_struct! {
/// An associated type within the definition of a trait.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct TraitItemType {
pub attrs: Vec,
/// (Non-exhaustive) Additional optional information about a type alias.
pub modifiers: TypeModifiers,
pub type_token: Token![type],
pub ident: Ident,
pub generics: Generics,
pub colon_token: Option,
pub bounds: Punctuated,
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,
pub mac: Macro,
pub semi_token: Option,
}
}
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.
///
///
///
/// Important: see [Compatibility notes][crate#verbatim-variants].
///
///
Verbatim(TokenStream),
}
}
ast_struct! {
/// An associated constant within an impl block.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct ImplItemConst {
pub attrs: Vec,
pub vis: Visibility,
/// (Non-exhaustive) Additional optional information about a const item.
pub modifiers: ConstModifiers,
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,
pub vis: Visibility,
/// (Non-exhaustive) Additional optional information about a function.
pub modifiers: FnModifiers,
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,
pub vis: Visibility,
/// (Non-exhaustive) Additional optional information about a type alias.
pub modifiers: TypeModifiers,
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,
pub mac: Macro,
pub semi_token: Option,
}
}
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,
pub asyncness: Option,
pub safety: Safety,
pub abi: Option,
pub fn_token: Token![fn],
pub ident: Ident,
pub generics: Generics,
pub paren_token: token::Paren,
pub inputs: Punctuated,
pub variadic: Option,
pub output: ReturnType,
}
}
impl Signature {
/// A method's `self` receiver, such as `&self` or `self: Box`.
pub fn receiver(&self) -> Option<&Receiver> {
let arg = self.inputs.first()?;
match arg {
FnArg::Receiver(receiver) => Some(receiver),
FnArg::Typed(_) => None,
}
}
}
ast_enum! {
/// Safe, unsafe or default.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub enum Safety {
/// The item is qualified as `safe`.
Safe(Token![safe]),
/// The item is qualified as `unsafe`.
Unsafe(Token![unsafe]),
/// The item is not qualified either way.
Default,
}
}
impl Default for Safety {
fn default() -> Self {
Safety::Default
}
}
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.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub struct Receiver {
pub attrs: Vec,
pub mutability: Option,
pub self_token: Token![self],
pub kind: ReceiverKind,
}
}
ast_enum! {
/// Different shorthand and explicit notations for a method receiver.
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
#[non_exhaustive]
pub enum ReceiverKind {
/// `self` or `mut self`
Value,
/// `&self` or `&mut self`
Reference(Token![&], Option, Option),
/// `self: Box`
Typed(Token![:], Box),
// TODO: https://github.com/rust-lang/rust/issues/123076
// Pin(Token![&], Option, Token![pin], PointerMutability),
}
}
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,
pub pat: Option<(Box, Token![:])>,
pub dots: Token![...],
pub comma: Option,
}
}
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! {
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
pub enum WhereClausePlacement {
/// `type Ty where T: 'static = T;`
///
/// In associated types, this syntax is **deprecated** in favor of the
/// late placement.
///
/// ```log
/// warning: where clause not allowed here
/// --> src/main.rs
/// |
/// | impl Trait for Thing { type Ty where T: 'static = T; }
/// | ^^^^^^^^^^^^^^^^
/// = note: see issue #89122 for more information
/// = note: `#[warn(deprecated_where_clause_location)]` on by default
/// ```
Early,
/// `type Ty = T where T: 'static;`
///
/// In item-level type aliases, this syntax is **unstable**.
///
/// ```log
/// error: where clauses are not allowed after the type for type aliases
/// --> src/main.rs
/// |
/// | type Ty = T where T: 'static;
/// | ^^^^^^^^^^^^^^^^
/// = note: see issue #112792 for more information
/// = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
/// ```
Late,
}
}
impl Copy for WhereClausePlacement {}
impl Clone for WhereClausePlacement {
fn clone(&self) -> Self {
*self
}
}
#[cfg(feature = "parsing")]
pub(crate) mod parsing {
use crate::attr::{self, Attribute};
use crate::buffer::Cursor;
use crate::derive;
use crate::error::{Error, Result};
use crate::expr::Expr;
use crate::ext::IdentExt as _;
use crate::generics::{self, Generics, TypeParamBound};
use crate::ident::Ident;
use crate::item::{
ConstModifiers, FnArg, FnModifiers, ForeignItem, ForeignItemFn, ForeignItemMacro,
ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro,
ImplItemType, ImplModifiers, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait,
ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, ReceiverKind, Safety, Signature,
StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType,
TraitModifiers, TypeModifiers, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree,
Variadic, WhereClausePlacement,
};
use crate::lifetime::Lifetime;
use crate::lit::LitStr;
use crate::mac::{self, Macro};
use crate::parse::discouraged::Speculative as _;
use crate::parse::{Parse, 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};
use crate::verbatim;
use alloc::boxed::Box;
use alloc::vec::Vec;
use proc_macro2::TokenStream;
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
impl Parse for Item {
fn parse(input: ParseStream) -> Result {
let begin = input.cursor();
let attrs = input.call(Attribute::parse_outer)?;
parse_rest_of_item(begin, attrs, input)
}
}
pub(crate) fn parse_rest_of_item(
begin: Cursor,
mut attrs: Vec,
input: ParseStream,
) -> Result- {
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::()?;
Ok(Item::Verbatim(verbatim::between(begin, input.cursor())))
} else {
parse_rest_of_fn(input, Vec::new(), vis, sig).map(Item::Fn)
}
} else if lookahead.peek(Token![extern]) {
ahead.parse::()?;
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::()?;
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.cursor()))),
}
} 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::()?;
input.parse::()?;
input.parse::()?;
Ok(Item::Verbatim(verbatim::between(begin, input.cursor())))
} else {
let colon_token = input.parse()?;
let ty = input.parse()?;
if input.peek(Token![;]) {
input.parse::()?;
Ok(Item::Verbatim(verbatim::between(begin, input.cursor())))
} 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: Visibility = input.parse()?;
let const_token: Token![const] = input.parse()?;
let lookahead = input.lookahead1();
if (lookahead.peek(Ident) && !(input.peek(Token![auto]) && input.peek2(Token![trait])))
|| lookahead.peek(Token![_])
{
let ident = input.call(Ident::parse_any)?;
let mut generics: Generics = input.parse()?;
let colon_token = input.parse()?;
let ty = input.parse()?;
let value = if let Some(eq_token) = input.parse::