1273 lines · 43.7 KB · Rust
RawDownload
// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::attr::Attribute;use crate::expr::Expr;use crate::generics::{BoundLifetimes, TypeParamBound};use crate::ident::Ident;use crate::lifetime::Lifetime;use crate::lit::LitStr;use crate::mac::Macro;use crate::path::{Path, QSelf};use crate::punctuated::Punctuated;use crate::token;use proc_macro2::TokenStream; ast_enum_of_structs! {    /// The possible types that a Rust value could have.    ///    /// # Syntax tree enum    ///    /// This type is a [syntax tree enum].    ///    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    #[non_exhaustive]    pub enum Type {        /// A fixed size array type: `[T; n]`.        Array(TypeArray),         /// A bare function type: `fn(usize) -> bool`.        BareFn(TypeBareFn),         /// A type contained within invisible delimiters.        Group(TypeGroup),         /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or        /// a lifetime.        ImplTrait(TypeImplTrait),         /// Indication that a type should be inferred by the compiler: `_`.        Infer(TypeInfer),         /// A macro in the type position.        Macro(TypeMacro),         /// The never type: `!`.        Never(TypeNever),         /// A parenthesized type equivalent to the inner type.        Paren(TypeParen),         /// A path like `std::slice::Iter`, optionally qualified with a        /// self-type as in `<Vec<T> as SomeTrait>::Associated`.        Path(TypePath),         /// A raw pointer type: `*const T` or `*mut T`.        Ptr(TypePtr),         /// A reference type: `&'a T` or `&'a mut T`.        Reference(TypeReference),         /// A dynamically sized slice type: `[T]`.        Slice(TypeSlice),         /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a        /// trait or a lifetime.        TraitObject(TypeTraitObject),         /// A tuple type: `(A, B, C, String)`.        Tuple(TypeTuple),         /// Tokens in type position not interpreted by Syn.        Verbatim(TokenStream),         // For testing exhaustiveness in downstream code, use the following idiom:        //        //     match ty {        //         #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]        //        //         Type::Array(ty) => {...}        //         Type::BareFn(ty) => {...}        //         ...        //         Type::Verbatim(ty) => {...}        //        //         _ => { /* 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 fixed size array type: `[T; n]`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeArray {        pub bracket_token: token::Bracket,        pub elem: Box<Type>,        pub semi_token: Token![;],        pub len: Expr,    }} ast_struct! {    /// A bare function type: `fn(usize) -> bool`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeBareFn {        pub lifetimes: Option<BoundLifetimes>,        pub unsafety: Option<Token![unsafe]>,        pub abi: Option<Abi>,        pub fn_token: Token![fn],        pub paren_token: token::Paren,        pub inputs: Punctuated<BareFnArg, Token![,]>,        pub variadic: Option<BareVariadic>,        pub output: ReturnType,    }} ast_struct! {    /// A type contained within invisible delimiters.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeGroup {        pub group_token: token::Group,        pub elem: Box<Type>,    }} ast_struct! {    /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or    /// a lifetime.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeImplTrait {        pub impl_token: Token![impl],        pub bounds: Punctuated<TypeParamBound, Token![+]>,    }} ast_struct! {    /// Indication that a type should be inferred by the compiler: `_`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeInfer {        pub underscore_token: Token![_],    }} ast_struct! {    /// A macro in the type position.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeMacro {        pub mac: Macro,    }} ast_struct! {    /// The never type: `!`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeNever {        pub bang_token: Token![!],    }} ast_struct! {    /// A parenthesized type equivalent to the inner type.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeParen {        pub paren_token: token::Paren,        pub elem: Box<Type>,    }} ast_struct! {    /// A path like `std::slice::Iter`, optionally qualified with a    /// self-type as in `<Vec<T> as SomeTrait>::Associated`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypePath {        pub qself: Option<QSelf>,        pub path: Path,    }} ast_struct! {    /// A raw pointer type: `*const T` or `*mut T`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypePtr {        pub star_token: Token![*],        pub const_token: Option<Token![const]>,        pub mutability: Option<Token![mut]>,        pub elem: Box<Type>,    }} ast_struct! {    /// A reference type: `&'a T` or `&'a mut T`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeReference {        pub and_token: Token![&],        pub lifetime: Option<Lifetime>,        pub mutability: Option<Token![mut]>,        pub elem: Box<Type>,    }} ast_struct! {    /// A dynamically sized slice type: `[T]`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeSlice {        pub bracket_token: token::Bracket,        pub elem: Box<Type>,    }} ast_struct! {    /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a    /// trait or a lifetime.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeTraitObject {        pub dyn_token: Option<Token![dyn]>,        pub bounds: Punctuated<TypeParamBound, Token![+]>,    }} ast_struct! {    /// A tuple type: `(A, B, C, String)`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct TypeTuple {        pub paren_token: token::Paren,        pub elems: Punctuated<Type, Token![,]>,    }} ast_struct! {    /// The binary interface of a function: `extern "C"`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct Abi {        pub extern_token: Token![extern],        pub name: Option<LitStr>,    }} ast_struct! {    /// An argument in a function type: the `usize` in `fn(usize) -> bool`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct BareFnArg {        pub attrs: Vec<Attribute>,        pub name: Option<(Ident, Token![:])>,        pub ty: Type,    }} ast_struct! {    /// The variadic argument of a function pointer like `fn(usize, ...)`.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub struct BareVariadic {        pub attrs: Vec<Attribute>,        pub name: Option<(Ident, Token![:])>,        pub dots: Token![...],        pub comma: Option<Token![,]>,    }} ast_enum! {    /// Return type of a function signature.    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]    pub enum ReturnType {        /// Return type is not specified.        ///        /// Functions default to `()` and closures default to type inference.        Default,        /// A particular type is returned.        Type(Token![->], Box<Type>),    }} #[cfg(feature = "parsing")]pub(crate) mod parsing {    use crate::attr::Attribute;    use crate::error::{self, Result};    use crate::ext::IdentExt as _;    use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound};    use crate::ident::Ident;    use crate::lifetime::Lifetime;    use crate::mac::{self, Macro};    use crate::parse::{Parse, ParseStream};    use crate::path;    use crate::path::{Path, PathArguments, QSelf};    use crate::punctuated::Punctuated;    use crate::token;    use crate::ty::{        Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,        TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,        TypeReference, TypeSlice, TypeTraitObject, TypeTuple,    };    use crate::verbatim;    use proc_macro2::Span;     #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]    impl Parse for Type {        fn parse(input: ParseStream) -> Result<Self> {            let allow_plus = true;            let allow_group_generic = true;            ambig_ty(input, allow_plus, allow_group_generic)        }    }     impl Type {        /// In some positions, types may not contain the `+` character, to        /// disambiguate them. For example in the expression `1 as T`, T may not        /// contain a `+` character.        ///        /// This parser does not allow a `+`, while the default parser does.        #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]        pub fn without_plus(input: ParseStream) -> Result<Self> {            let allow_plus = false;            let allow_group_generic = true;            ambig_ty(input, allow_plus, allow_group_generic)        }    }     pub(crate) fn ambig_ty(        input: ParseStream,        allow_plus: bool,        allow_group_generic: bool,    ) -> Result<Type> {        let begin = input.fork();         if input.peek(token::Group) {            let mut group: TypeGroup = input.parse()?;            if input.peek(Token![::]) && input.peek3(Ident::peek_any) {                if let Type::Path(mut ty) = *group.elem {                    Path::parse_rest(input, &mut ty.path, false)?;                    return Ok(Type::Path(ty));                } else {                    return Ok(Type::Path(TypePath {                        qself: Some(QSelf {                            lt_token: Token![<](group.group_token.span),                            position: 0,                            as_token: None,                            gt_token: Token![>](group.group_token.span),                            ty: group.elem,                        }),                        path: Path::parse_helper(input, false)?,                    }));                }            } else if input.peek(Token![<]) && allow_group_generic                || input.peek(Token![::]) && input.peek3(Token![<])            {                if let Type::Path(mut ty) = *group.elem {                    let arguments = &mut ty.path.segments.last_mut().unwrap().arguments;                    if arguments.is_none() {                        *arguments = PathArguments::AngleBracketed(input.parse()?);                        Path::parse_rest(input, &mut ty.path, false)?;                        return Ok(Type::Path(ty));                    } else {                        group.elem = Box::new(Type::Path(ty));                    }                }            }            return Ok(Type::Group(group));        }         let mut lifetimes = None::<BoundLifetimes>;        let mut lookahead = input.lookahead1();        if lookahead.peek(Token![for]) {            lifetimes = input.parse()?;            lookahead = input.lookahead1();            if !lookahead.peek(Ident)                && !lookahead.peek(Token![fn])                && !lookahead.peek(Token![unsafe])                && !lookahead.peek(Token![extern])                && !lookahead.peek(Token![super])                && !lookahead.peek(Token![self])                && !lookahead.peek(Token![Self])                && !lookahead.peek(Token![crate])                || input.peek(Token![dyn])            {                return Err(lookahead.error());            }        }         if lookahead.peek(token::Paren) {            let content;            let paren_token = parenthesized!(content in input);            if content.is_empty() {                return Ok(Type::Tuple(TypeTuple {                    paren_token,                    elems: Punctuated::new(),                }));            }            if content.peek(Lifetime) {                return Ok(Type::Paren(TypeParen {                    paren_token,                    elem: Box::new(Type::TraitObject(content.parse()?)),                }));            }            if content.peek(Token![?]) {                return Ok(Type::TraitObject(TypeTraitObject {                    dyn_token: None,                    bounds: {                        let mut bounds = Punctuated::new();                        bounds.push_value(TypeParamBound::Trait(TraitBound {                            paren_token: Some(paren_token),                            ..content.parse()?                        }));                        while let Some(plus) = input.parse()? {                            bounds.push_punct(plus);                            bounds.push_value({                                let allow_precise_capture = false;                                let allow_const = false;                                TypeParamBound::parse_single(                                    input,                                    allow_precise_capture,                                    allow_const,                                )?                            });                        }                        bounds                    },                }));            }            let mut first: Type = content.parse()?;            if content.peek(Token![,]) {                return Ok(Type::Tuple(TypeTuple {                    paren_token,                    elems: {                        let mut elems = Punctuated::new();                        elems.push_value(first);                        elems.push_punct(content.parse()?);                        while !content.is_empty() {                            elems.push_value(content.parse()?);                            if content.is_empty() {                                break;                            }                            elems.push_punct(content.parse()?);                        }                        elems                    },                }));            }            if allow_plus && input.peek(Token![+]) {                loop {                    let first = match first {                        Type::Path(TypePath { qself: None, path }) => {                            TypeParamBound::Trait(TraitBound {                                paren_token: Some(paren_token),                                modifier: TraitBoundModifier::None,                                lifetimes: None,                                path,                            })                        }                        Type::TraitObject(TypeTraitObject {                            dyn_token: None,                            bounds,                        }) => {                            if bounds.len() > 1 || bounds.trailing_punct() {                                first = Type::TraitObject(TypeTraitObject {                                    dyn_token: None,                                    bounds,                                });                                break;                            }                            match bounds.into_iter().next().unwrap() {                                TypeParamBound::Trait(trait_bound) => {                                    TypeParamBound::Trait(TraitBound {                                        paren_token: Some(paren_token),                                        ..trait_bound                                    })                                }                                other @ (TypeParamBound::Lifetime(_)                                | TypeParamBound::PreciseCapture(_)                                | TypeParamBound::Verbatim(_)) => other,                            }                        }                        _ => break,                    };                    return Ok(Type::TraitObject(TypeTraitObject {                        dyn_token: None,                        bounds: {                            let mut bounds = Punctuated::new();                            bounds.push_value(first);                            while let Some(plus) = input.parse()? {                                bounds.push_punct(plus);                                bounds.push_value({                                    let allow_precise_capture = false;                                    let allow_const = false;                                    TypeParamBound::parse_single(                                        input,                                        allow_precise_capture,                                        allow_const,                                    )?                                });                            }                            bounds                        },                    }));                }            }            Ok(Type::Paren(TypeParen {                paren_token,                elem: Box::new(first),

Lines 1–500 of 1273.