File Index
Files and directories
Sign in
FILE

ty.rs

File preview with syntax highlighting.

linux-6.19.14/rust/syn/ty.rs RUST
   1// SPDX-License-Identifier: Apache-2.0 OR MIT
   2
   3use crate::attr::Attribute;
   4use crate::expr::Expr;
   5use crate::generics::{BoundLifetimes, TypeParamBound};
   6use crate::ident::Ident;
   7use crate::lifetime::Lifetime;
   8use crate::lit::LitStr;
   9use crate::mac::Macro;
  10use crate::path::{Path, QSelf};
  11use crate::punctuated::Punctuated;
  12use crate::token;
  13use proc_macro2::TokenStream;
  14
  15ast_enum_of_structs! {
  16    /// The possible types that a Rust value could have.
  17    ///
  18    /// # Syntax tree enum
  19    ///
  20    /// This type is a [syntax tree enum].
  21    ///
  22    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
  23    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  24    #[non_exhaustive]
  25    pub enum Type {
  26        /// A fixed size array type: `[T; n]`.
  27        Array(TypeArray),
  28
  29        /// A bare function type: `fn(usize) -> bool`.
  30        BareFn(TypeBareFn),
  31
  32        /// A type contained within invisible delimiters.
  33        Group(TypeGroup),
  34
  35        /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
  36        /// a lifetime.
  37        ImplTrait(TypeImplTrait),
  38
  39        /// Indication that a type should be inferred by the compiler: `_`.
  40        Infer(TypeInfer),
  41
  42        /// A macro in the type position.
  43        Macro(TypeMacro),
  44
  45        /// The never type: `!`.
  46        Never(TypeNever),
  47
  48        /// A parenthesized type equivalent to the inner type.
  49        Paren(TypeParen),
  50
  51        /// A path like `std::slice::Iter`, optionally qualified with a
  52        /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
  53        Path(TypePath),
  54
  55        /// A raw pointer type: `*const T` or `*mut T`.
  56        Ptr(TypePtr),
  57
  58        /// A reference type: `&'a T` or `&'a mut T`.
  59        Reference(TypeReference),
  60
  61        /// A dynamically sized slice type: `[T]`.
  62        Slice(TypeSlice),
  63
  64        /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
  65        /// trait or a lifetime.
  66        TraitObject(TypeTraitObject),
  67
  68        /// A tuple type: `(A, B, C, String)`.
  69        Tuple(TypeTuple),
  70
  71        /// Tokens in type position not interpreted by Syn.
  72        Verbatim(TokenStream),
  73
  74        // For testing exhaustiveness in downstream code, use the following idiom:
  75        //
  76        //     match ty {
  77        //         #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
  78        //
  79        //         Type::Array(ty) => {...}
  80        //         Type::BareFn(ty) => {...}
  81        //         ...
  82        //         Type::Verbatim(ty) => {...}
  83        //
  84        //         _ => { /* some sane fallback */ }
  85        //     }
  86        //
  87        // This way we fail your tests but don't break your library when adding
  88        // a variant. You will be notified by a test failure when a variant is
  89        // added, so that you can add code to handle it, but your library will
  90        // continue to compile and work for downstream users in the interim.
  91    }
  92}
  93
  94ast_struct! {
  95    /// A fixed size array type: `[T; n]`.
  96    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  97    pub struct TypeArray {
  98        pub bracket_token: token::Bracket,
  99        pub elem: Box<Type>,
 100        pub semi_token: Token![;],
 101        pub len: Expr,
 102    }
 103}
 104
 105ast_struct! {
 106    /// A bare function type: `fn(usize) -> bool`.
 107    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 108    pub struct TypeBareFn {
 109        pub lifetimes: Option<BoundLifetimes>,
 110        pub unsafety: Option<Token![unsafe]>,
 111        pub abi: Option<Abi>,
 112        pub fn_token: Token![fn],
 113        pub paren_token: token::Paren,
 114        pub inputs: Punctuated<BareFnArg, Token![,]>,
 115        pub variadic: Option<BareVariadic>,
 116        pub output: ReturnType,
 117    }
 118}
 119
 120ast_struct! {
 121    /// A type contained within invisible delimiters.
 122    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 123    pub struct TypeGroup {
 124        pub group_token: token::Group,
 125        pub elem: Box<Type>,
 126    }
 127}
 128
 129ast_struct! {
 130    /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
 131    /// a lifetime.
 132    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 133    pub struct TypeImplTrait {
 134        pub impl_token: Token![impl],
 135        pub bounds: Punctuated<TypeParamBound, Token![+]>,
 136    }
 137}
 138
 139ast_struct! {
 140    /// Indication that a type should be inferred by the compiler: `_`.
 141    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 142    pub struct TypeInfer {
 143        pub underscore_token: Token![_],
 144    }
 145}
 146
 147ast_struct! {
 148    /// A macro in the type position.
 149    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 150    pub struct TypeMacro {
 151        pub mac: Macro,
 152    }
 153}
 154
 155ast_struct! {
 156    /// The never type: `!`.
 157    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 158    pub struct TypeNever {
 159        pub bang_token: Token![!],
 160    }
 161}
 162
 163ast_struct! {
 164    /// A parenthesized type equivalent to the inner type.
 165    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 166    pub struct TypeParen {
 167        pub paren_token: token::Paren,
 168        pub elem: Box<Type>,
 169    }
 170}
 171
 172ast_struct! {
 173    /// A path like `std::slice::Iter`, optionally qualified with a
 174    /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
 175    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 176    pub struct TypePath {
 177        pub qself: Option<QSelf>,
 178        pub path: Path,
 179    }
 180}
 181
 182ast_struct! {
 183    /// A raw pointer type: `*const T` or `*mut T`.
 184    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 185    pub struct TypePtr {
 186        pub star_token: Token![*],
 187        pub const_token: Option<Token![const]>,
 188        pub mutability: Option<Token![mut]>,
 189        pub elem: Box<Type>,
 190    }
 191}
 192
 193ast_struct! {
 194    /// A reference type: `&'a T` or `&'a mut T`.
 195    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 196    pub struct TypeReference {
 197        pub and_token: Token![&],
 198        pub lifetime: Option<Lifetime>,
 199        pub mutability: Option<Token![mut]>,
 200        pub elem: Box<Type>,
 201    }
 202}
 203
 204ast_struct! {
 205    /// A dynamically sized slice type: `[T]`.
 206    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 207    pub struct TypeSlice {
 208        pub bracket_token: token::Bracket,
 209        pub elem: Box<Type>,
 210    }
 211}
 212
 213ast_struct! {
 214    /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
 215    /// trait or a lifetime.
 216    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 217    pub struct TypeTraitObject {
 218        pub dyn_token: Option<Token![dyn]>,
 219        pub bounds: Punctuated<TypeParamBound, Token![+]>,
 220    }
 221}
 222
 223ast_struct! {
 224    /// A tuple type: `(A, B, C, String)`.
 225    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 226    pub struct TypeTuple {
 227        pub paren_token: token::Paren,
 228        pub elems: Punctuated<Type, Token![,]>,
 229    }
 230}
 231
 232ast_struct! {
 233    /// The binary interface of a function: `extern "C"`.
 234    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 235    pub struct Abi {
 236        pub extern_token: Token![extern],
 237        pub name: Option<LitStr>,
 238    }
 239}
 240
 241ast_struct! {
 242    /// An argument in a function type: the `usize` in `fn(usize) -> bool`.
 243    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 244    pub struct BareFnArg {
 245        pub attrs: Vec<Attribute>,
 246        pub name: Option<(Ident, Token![:])>,
 247        pub ty: Type,
 248    }
 249}
 250
 251ast_struct! {
 252    /// The variadic argument of a function pointer like `fn(usize, ...)`.
 253    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 254    pub struct BareVariadic {
 255        pub attrs: Vec<Attribute>,
 256        pub name: Option<(Ident, Token![:])>,
 257        pub dots: Token![...],
 258        pub comma: Option<Token![,]>,
 259    }
 260}
 261
 262ast_enum! {
 263    /// Return type of a function signature.
 264    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
 265    pub enum ReturnType {
 266        /// Return type is not specified.
 267        ///
 268        /// Functions default to `()` and closures default to type inference.
 269        Default,
 270        /// A particular type is returned.
 271        Type(Token![->], Box<Type>),
 272    }
 273}
 274
 275#[cfg(feature = "parsing")]
 276pub(crate) mod parsing {
 277    use crate::attr::Attribute;
 278    use crate::error::{self, Result};
 279    use crate::ext::IdentExt as _;
 280    use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound};
 281    use crate::ident::Ident;
 282    use crate::lifetime::Lifetime;
 283    use crate::mac::{self, Macro};
 284    use crate::parse::{Parse, ParseStream};
 285    use crate::path;
 286    use crate::path::{Path, PathArguments, QSelf};
 287    use crate::punctuated::Punctuated;
 288    use crate::token;
 289    use crate::ty::{
 290        Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
 291        TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,
 292        TypeReference, TypeSlice, TypeTraitObject, TypeTuple,
 293    };
 294    use crate::verbatim;
 295    use proc_macro2::Span;
 296
 297    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 298    impl Parse for Type {
 299        fn parse(input: ParseStream) -> Result<Self> {
 300            let allow_plus = true;
 301            let allow_group_generic = true;
 302            ambig_ty(input, allow_plus, allow_group_generic)
 303        }
 304    }
 305
 306    impl Type {
 307        /// In some positions, types may not contain the `+` character, to
 308        /// disambiguate them. For example in the expression `1 as T`, T may not
 309        /// contain a `+` character.
 310        ///
 311        /// This parser does not allow a `+`, while the default parser does.
 312        #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 313        pub fn without_plus(input: ParseStream) -> Result<Self> {
 314            let allow_plus = false;
 315            let allow_group_generic = true;
 316            ambig_ty(input, allow_plus, allow_group_generic)
 317        }
 318    }
 319
 320    pub(crate) fn ambig_ty(
 321        input: ParseStream,
 322        allow_plus: bool,
 323        allow_group_generic: bool,
 324    ) -> Result<Type> {
 325        let begin = input.fork();
 326
 327        if input.peek(token::Group) {
 328            let mut group: TypeGroup = input.parse()?;
 329            if input.peek(Token![::]) && input.peek3(Ident::peek_any) {
 330                if let Type::Path(mut ty) = *group.elem {
 331                    Path::parse_rest(input, &mut ty.path, false)?;
 332                    return Ok(Type::Path(ty));
 333                } else {
 334                    return Ok(Type::Path(TypePath {
 335                        qself: Some(QSelf {
 336                            lt_token: Token![<](group.group_token.span),
 337                            position: 0,
 338                            as_token: None,
 339                            gt_token: Token![>](group.group_token.span),
 340                            ty: group.elem,
 341                        }),
 342                        path: Path::parse_helper(input, false)?,
 343                    }));
 344                }
 345            } else if input.peek(Token![<]) && allow_group_generic
 346                || input.peek(Token![::]) && input.peek3(Token![<])
 347            {
 348                if let Type::Path(mut ty) = *group.elem {
 349                    let arguments = &mut ty.path.segments.last_mut().unwrap().arguments;
 350                    if arguments.is_none() {
 351                        *arguments = PathArguments::AngleBracketed(input.parse()?);
 352                        Path::parse_rest(input, &mut ty.path, false)?;
 353                        return Ok(Type::Path(ty));
 354                    } else {
 355                        group.elem = Box::new(Type::Path(ty));
 356                    }
 357                }
 358            }
 359            return Ok(Type::Group(group));
 360        }
 361
 362        let mut lifetimes = None::<BoundLifetimes>;
 363        let mut lookahead = input.lookahead1();
 364        if lookahead.peek(Token![for]) {
 365            lifetimes = input.parse()?;
 366            lookahead = input.lookahead1();
 367            if !lookahead.peek(Ident)
 368                && !lookahead.peek(Token![fn])
 369                && !lookahead.peek(Token![unsafe])
 370                && !lookahead.peek(Token![extern])
 371                && !lookahead.peek(Token![super])
 372                && !lookahead.peek(Token![self])
 373                && !lookahead.peek(Token![Self])
 374                && !lookahead.peek(Token![crate])
 375                || input.peek(Token![dyn])
 376            {
 377                return Err(lookahead.error());
 378            }
 379        }
 380
 381        if lookahead.peek(token::Paren) {
 382            let content;
 383            let paren_token = parenthesized!(content in input);
 384            if content.is_empty() {
 385                return Ok(Type::Tuple(TypeTuple {
 386                    paren_token,
 387                    elems: Punctuated::new(),
 388                }));
 389            }
 390            if content.peek(Lifetime) {
 391                return Ok(Type::Paren(TypeParen {
 392                    paren_token,
 393                    elem: Box::new(Type::TraitObject(content.parse()?)),
 394                }));
 395            }
 396            if content.peek(Token![?]) {
 397                return Ok(Type::TraitObject(TypeTraitObject {
 398                    dyn_token: None,
 399                    bounds: {
 400                        let mut bounds = Punctuated::new();
 401                        bounds.push_value(TypeParamBound::Trait(TraitBound {
 402                            paren_token: Some(paren_token),
 403                            ..content.parse()?
 404                        }));
 405                        while let Some(plus) = input.parse()? {
 406                            bounds.push_punct(plus);
 407                            bounds.push_value({
 408                                let allow_precise_capture = false;
 409                                let allow_const = false;
 410                                TypeParamBound::parse_single(
 411                                    input,
 412                                    allow_precise_capture,
 413                                    allow_const,
 414                                )?
 415                            });
 416                        }
 417                        bounds
 418                    },
 419                }));
 420            }
 421            let mut first: Type = content.parse()?;
 422            if content.peek(Token![,]) {
 423                return Ok(Type::Tuple(TypeTuple {
 424                    paren_token,
 425                    elems: {
 426                        let mut elems = Punctuated::new();
 427                        elems.push_value(first);
 428                        elems.push_punct(content.parse()?);
 429                        while !content.is_empty() {
 430                            elems.push_value(content.parse()?);
 431                            if content.is_empty() {
 432                                break;
 433                            }
 434                            elems.push_punct(content.parse()?);
 435                        }
 436                        elems
 437                    },
 438                }));
 439            }
 440            if allow_plus && input.peek(Token![+]) {
 441                loop {
 442                    let first = match first {
 443                        Type::Path(TypePath { qself: None, path }) => {
 444                            TypeParamBound::Trait(TraitBound {
 445                                paren_token: Some(paren_token),
 446                                modifier: TraitBoundModifier::None,
 447                                lifetimes: None,
 448                                path,
 449                            })
 450                        }
 451                        Type::TraitObject(TypeTraitObject {
 452                            dyn_token: None,
 453                            bounds,
 454                        }) => {
 455                            if bounds.len() > 1 || bounds.trailing_punct() {
 456                                first = Type::TraitObject(TypeTraitObject {
 457                                    dyn_token: None,
 458                                    bounds,
 459                                });
 460                                break;
 461                            }
 462                            match bounds.into_iter().next().unwrap() {
 463                                TypeParamBound::Trait(trait_bound) => {
 464                                    TypeParamBound::Trait(TraitBound {
 465                                        paren_token: Some(paren_token),
 466                                        ..trait_bound
 467                                    })
 468                                }
 469                                other @ (TypeParamBound::Lifetime(_)
 470                                | TypeParamBound::PreciseCapture(_)
 471                                | TypeParamBound::Verbatim(_)) => other,
 472                            }
 473                        }
 474                        _ => break,
 475                    };
 476                    return Ok(Type::TraitObject(TypeTraitObject {
 477                        dyn_token: None,
 478                        bounds: {
 479                            let mut bounds = Punctuated::new();
 480                            bounds.push_value(first);
 481                            while let Some(plus) = input.parse()? {
 482                                bounds.push_punct(plus);
 483                                bounds.push_value({
 484                                    let allow_precise_capture = false;
 485                                    let allow_const = false;
 486                                    TypeParamBound::parse_single(
 487                                        input,
 488                                        allow_precise_capture,
 489                                        allow_const,
 490                                    )?
 491                                });
 492                            }
 493                            bounds
 494                        },
 495                    }));
 496                }
 497            }
 498            Ok(Type::Paren(TypeParen {
 499                paren_token,
 500                elem: Box::new(first),
 501            }))
 502        } else if lookahead.peek(Token![fn])
 503            || lookahead.peek(Token![unsafe])
 504            || lookahead.peek(Token![extern])
 505        {
 506            let mut bare_fn: TypeBareFn = input.parse()?;
 507            bare_fn.lifetimes = lifetimes;
 508            Ok(Type::BareFn(bare_fn))
 509        } else if lookahead.peek(Ident)
 510            || input.peek(Token![super])
 511            || input.peek(Token![self])
 512            || input.peek(Token![Self])
 513            || input.peek(Token![crate])
 514            || lookahead.peek(Token![::])
 515            || lookahead.peek(Token![<])
 516        {
 517            let ty: TypePath = input.parse()?;
 518            if ty.qself.is_some() {
 519                return Ok(Type::Path(ty));
 520            }
 521
 522            if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() {
 523                let bang_token: Token![!] = input.parse()?;
 524                let (delimiter, tokens) = mac::parse_delimiter(input)?;
 525                return Ok(Type::Macro(TypeMacro {
 526                    mac: Macro {
 527                        path: ty.path,
 528                        bang_token,
 529                        delimiter,
 530                        tokens,
 531                    },
 532                }));
 533            }
 534
 535            if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
 536                let mut bounds = Punctuated::new();
 537                bounds.push_value(TypeParamBound::Trait(TraitBound {
 538                    paren_token: None,
 539                    modifier: TraitBoundModifier::None,
 540                    lifetimes,
 541                    path: ty.path,
 542                }));
 543                if allow_plus {
 544                    while input.peek(Token![+]) {
 545                        bounds.push_punct(input.parse()?);
 546                        if !(input.peek(Ident::peek_any)
 547                            || input.peek(Token![::])
 548                            || input.peek(Token![?])
 549                            || input.peek(Lifetime)
 550                            || input.peek(token::Paren))
 551                        {
 552                            break;
 553                        }
 554                        bounds.push_value({
 555                            let allow_precise_capture = false;
 556                            let allow_const = false;
 557                            TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
 558                        });
 559                    }
 560                }
 561                return Ok(Type::TraitObject(TypeTraitObject {
 562                    dyn_token: None,
 563                    bounds,
 564                }));
 565            }
 566
 567            Ok(Type::Path(ty))
 568        } else if lookahead.peek(Token![dyn]) {
 569            let dyn_token: Token![dyn] = input.parse()?;
 570            let dyn_span = dyn_token.span;
 571            let star_token: Option<Token![*]> = input.parse()?;
 572            let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?;
 573            Ok(if star_token.is_some() {
 574                Type::Verbatim(verbatim::between(&begin, input))
 575            } else {
 576                Type::TraitObject(TypeTraitObject {
 577                    dyn_token: Some(dyn_token),
 578                    bounds,
 579                })
 580            })
 581        } else if lookahead.peek(token::Bracket) {
 582            let content;
 583            let bracket_token = bracketed!(content in input);
 584            let elem: Type = content.parse()?;
 585            if content.peek(Token![;]) {
 586                Ok(Type::Array(TypeArray {
 587                    bracket_token,
 588                    elem: Box::new(elem),
 589                    semi_token: content.parse()?,
 590                    len: content.parse()?,
 591                }))
 592            } else {
 593                Ok(Type::Slice(TypeSlice {
 594                    bracket_token,
 595                    elem: Box::new(elem),
 596                }))
 597            }
 598        } else if lookahead.peek(Token![*]) {
 599            input.parse().map(Type::Ptr)
 600        } else if lookahead.peek(Token![&]) {
 601            input.parse().map(Type::Reference)
 602        } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
 603            input.parse().map(Type::Never)
 604        } else if lookahead.peek(Token![impl]) {
 605            TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait)
 606        } else if lookahead.peek(Token![_]) {
 607            input.parse().map(Type::Infer)
 608        } else if lookahead.peek(Lifetime) {
 609            input.parse().map(Type::TraitObject)
 610        } else {
 611            Err(lookahead.error())
 612        }
 613    }
 614
 615    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 616    impl Parse for TypeSlice {
 617        fn parse(input: ParseStream) -> Result<Self> {
 618            let content;
 619            Ok(TypeSlice {
 620                bracket_token: bracketed!(content in input),
 621                elem: content.parse()?,
 622            })
 623        }
 624    }
 625
 626    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 627    impl Parse for TypeArray {
 628        fn parse(input: ParseStream) -> Result<Self> {
 629            let content;
 630            Ok(TypeArray {
 631                bracket_token: bracketed!(content in input),
 632                elem: content.parse()?,
 633                semi_token: content.parse()?,
 634                len: content.parse()?,
 635            })
 636        }
 637    }
 638
 639    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 640    impl Parse for TypePtr {
 641        fn parse(input: ParseStream) -> Result<Self> {
 642            let star_token: Token![*] = input.parse()?;
 643
 644            let lookahead = input.lookahead1();
 645            let (const_token, mutability) = if lookahead.peek(Token![const]) {
 646                (Some(input.parse()?), None)
 647            } else if lookahead.peek(Token![mut]) {
 648                (None, Some(input.parse()?))
 649            } else {
 650                return Err(lookahead.error());
 651            };
 652
 653            Ok(TypePtr {
 654                star_token,
 655                const_token,
 656                mutability,
 657                elem: Box::new(input.call(Type::without_plus)?),
 658            })
 659        }
 660    }
 661
 662    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 663    impl Parse for TypeReference {
 664        fn parse(input: ParseStream) -> Result<Self> {
 665            Ok(TypeReference {
 666                and_token: input.parse()?,
 667                lifetime: input.parse()?,
 668                mutability: input.parse()?,
 669                // & binds tighter than +, so we don't allow + here.
 670                elem: Box::new(input.call(Type::without_plus)?),
 671            })
 672        }
 673    }
 674
 675    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 676    impl Parse for TypeBareFn {
 677        fn parse(input: ParseStream) -> Result<Self> {
 678            let args;
 679            let mut variadic = None;
 680
 681            Ok(TypeBareFn {
 682                lifetimes: input.parse()?,
 683                unsafety: input.parse()?,
 684                abi: input.parse()?,
 685                fn_token: input.parse()?,
 686                paren_token: parenthesized!(args in input),
 687                inputs: {
 688                    let mut inputs = Punctuated::new();
 689
 690                    while !args.is_empty() {
 691                        let attrs = args.call(Attribute::parse_outer)?;
 692
 693                        if inputs.empty_or_trailing()
 694                            && (args.peek(Token![...])
 695                                || (args.peek(Ident) || args.peek(Token![_]))
 696                                    && args.peek2(Token![:])
 697                                    && args.peek3(Token![...]))
 698                        {
 699                            variadic = Some(parse_bare_variadic(&args, attrs)?);
 700                            break;
 701                        }
 702
 703                        let allow_self = inputs.is_empty();
 704                        let arg = parse_bare_fn_arg(&args, allow_self)?;
 705                        inputs.push_value(BareFnArg { attrs, ..arg });
 706                        if args.is_empty() {
 707                            break;
 708                        }
 709
 710                        let comma = args.parse()?;
 711                        inputs.push_punct(comma);
 712                    }
 713
 714                    inputs
 715                },
 716                variadic,
 717                output: input.call(ReturnType::without_plus)?,
 718            })
 719        }
 720    }
 721
 722    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 723    impl Parse for TypeNever {
 724        fn parse(input: ParseStream) -> Result<Self> {
 725            Ok(TypeNever {
 726                bang_token: input.parse()?,
 727            })
 728        }
 729    }
 730
 731    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 732    impl Parse for TypeInfer {
 733        fn parse(input: ParseStream) -> Result<Self> {
 734            Ok(TypeInfer {
 735                underscore_token: input.parse()?,
 736            })
 737        }
 738    }
 739
 740    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 741    impl Parse for TypeTuple {
 742        fn parse(input: ParseStream) -> Result<Self> {
 743            let content;
 744            let paren_token = parenthesized!(content in input);
 745
 746            if content.is_empty() {
 747                return Ok(TypeTuple {
 748                    paren_token,
 749                    elems: Punctuated::new(),
 750                });
 751            }
 752
 753            let first: Type = content.parse()?;
 754            Ok(TypeTuple {
 755                paren_token,
 756                elems: {
 757                    let mut elems = Punctuated::new();
 758                    elems.push_value(first);
 759                    elems.push_punct(content.parse()?);
 760                    while !content.is_empty() {
 761                        elems.push_value(content.parse()?);
 762                        if content.is_empty() {
 763                            break;
 764                        }
 765                        elems.push_punct(content.parse()?);
 766                    }
 767                    elems
 768                },
 769            })
 770        }
 771    }
 772
 773    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 774    impl Parse for TypeMacro {
 775        fn parse(input: ParseStream) -> Result<Self> {
 776            Ok(TypeMacro {
 777                mac: input.parse()?,
 778            })
 779        }
 780    }
 781
 782    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 783    impl Parse for TypePath {
 784        fn parse(input: ParseStream) -> Result<Self> {
 785            let expr_style = false;
 786            let (qself, path) = path::parsing::qpath(input, expr_style)?;
 787            Ok(TypePath { qself, path })
 788        }
 789    }
 790
 791    impl ReturnType {
 792        #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 793        pub fn without_plus(input: ParseStream) -> Result<Self> {
 794            let allow_plus = false;
 795            Self::parse(input, allow_plus)
 796        }
 797
 798        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
 799            if input.peek(Token![->]) {
 800                let arrow = input.parse()?;
 801                let allow_group_generic = true;
 802                let ty = ambig_ty(input, allow_plus, allow_group_generic)?;
 803                Ok(ReturnType::Type(arrow, Box::new(ty)))
 804            } else {
 805                Ok(ReturnType::Default)
 806            }
 807        }
 808    }
 809
 810    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 811    impl Parse for ReturnType {
 812        fn parse(input: ParseStream) -> Result<Self> {
 813            let allow_plus = true;
 814            Self::parse(input, allow_plus)
 815        }
 816    }
 817
 818    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 819    impl Parse for TypeTraitObject {
 820        fn parse(input: ParseStream) -> Result<Self> {
 821            let allow_plus = true;
 822            Self::parse(input, allow_plus)
 823        }
 824    }
 825
 826    impl TypeTraitObject {
 827        #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 828        pub fn without_plus(input: ParseStream) -> Result<Self> {
 829            let allow_plus = false;
 830            Self::parse(input, allow_plus)
 831        }
 832
 833        // Only allow multiple trait references if allow_plus is true.
 834        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
 835            let dyn_token: Option<Token![dyn]> = input.parse()?;
 836            let dyn_span = match &dyn_token {
 837                Some(token) => token.span,
 838                None => input.span(),
 839            };
 840            let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?;
 841            Ok(TypeTraitObject { dyn_token, bounds })
 842        }
 843
 844        fn parse_bounds(
 845            dyn_span: Span,
 846            input: ParseStream,
 847            allow_plus: bool,
 848        ) -> Result<Punctuated<TypeParamBound, Token![+]>> {
 849            let allow_precise_capture = false;
 850            let allow_const = false;
 851            let bounds = TypeParamBound::parse_multiple(
 852                input,
 853                allow_plus,
 854                allow_precise_capture,
 855                allow_const,
 856            )?;
 857            let mut last_lifetime_span = None;
 858            let mut at_least_one_trait = false;
 859            for bound in &bounds {
 860                match bound {
 861                    TypeParamBound::Trait(_) => {
 862                        at_least_one_trait = true;
 863                        break;
 864                    }
 865                    TypeParamBound::Lifetime(lifetime) => {
 866                        last_lifetime_span = Some(lifetime.ident.span());
 867                    }
 868                    TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => {
 869                        unreachable!()
 870                    }
 871                }
 872            }
 873            // Just lifetimes like `'a + 'b` is not a TraitObject.
 874            if !at_least_one_trait {
 875                let msg = "at least one trait is required for an object type";
 876                return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg));
 877            }
 878            Ok(bounds)
 879        }
 880    }
 881
 882    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 883    impl Parse for TypeImplTrait {
 884        fn parse(input: ParseStream) -> Result<Self> {
 885            let allow_plus = true;
 886            Self::parse(input, allow_plus)
 887        }
 888    }
 889
 890    impl TypeImplTrait {
 891        #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 892        pub fn without_plus(input: ParseStream) -> Result<Self> {
 893            let allow_plus = false;
 894            Self::parse(input, allow_plus)
 895        }
 896
 897        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
 898            let impl_token: Token![impl] = input.parse()?;
 899            let allow_precise_capture = true;
 900            let allow_const = true;
 901            let bounds = TypeParamBound::parse_multiple(
 902                input,
 903                allow_plus,
 904                allow_precise_capture,
 905                allow_const,
 906            )?;
 907            let mut last_nontrait_span = None;
 908            let mut at_least_one_trait = false;
 909            for bound in &bounds {
 910                match bound {
 911                    TypeParamBound::Trait(_) => {
 912                        at_least_one_trait = true;
 913                        break;
 914                    }
 915                    TypeParamBound::Lifetime(lifetime) => {
 916                        last_nontrait_span = Some(lifetime.ident.span());
 917                    }
 918                    TypeParamBound::PreciseCapture(precise_capture) => {
 919                        #[cfg(feature = "full")]
 920                        {
 921                            last_nontrait_span = Some(precise_capture.gt_token.span);
 922                        }
 923                        #[cfg(not(feature = "full"))]
 924                        {
 925                            _ = precise_capture;
 926                            unreachable!();
 927                        }
 928                    }
 929                    TypeParamBound::Verbatim(_) => {
 930                        // `[const] Trait`
 931                        at_least_one_trait = true;
 932                        break;
 933                    }
 934                }
 935            }
 936            if !at_least_one_trait {
 937                let msg = "at least one trait must be specified";
 938                return Err(error::new2(
 939                    impl_token.span,
 940                    last_nontrait_span.unwrap(),
 941                    msg,
 942                ));
 943            }
 944            Ok(TypeImplTrait { impl_token, bounds })
 945        }
 946    }
 947
 948    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 949    impl Parse for TypeGroup {
 950        fn parse(input: ParseStream) -> Result<Self> {
 951            let group = crate::group::parse_group(input)?;
 952            Ok(TypeGroup {
 953                group_token: group.token,
 954                elem: group.content.parse()?,
 955            })
 956        }
 957    }
 958
 959    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 960    impl Parse for TypeParen {
 961        fn parse(input: ParseStream) -> Result<Self> {
 962            let allow_plus = false;
 963            Self::parse(input, allow_plus)
 964        }
 965    }
 966
 967    impl TypeParen {
 968        fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
 969            let content;
 970            Ok(TypeParen {
 971                paren_token: parenthesized!(content in input),
 972                elem: Box::new({
 973                    let allow_group_generic = true;
 974                    ambig_ty(&content, allow_plus, allow_group_generic)?
 975                }),
 976            })
 977        }
 978    }
 979
 980    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
 981    impl Parse for BareFnArg {
 982        fn parse(input: ParseStream) -> Result<Self> {
 983            let allow_self = false;
 984            parse_bare_fn_arg(input, allow_self)
 985        }
 986    }
 987
 988    fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> {
 989        let attrs = input.call(Attribute::parse_outer)?;
 990
 991        let begin = input.fork();
 992
 993        let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]);
 994        if has_mut_self {
 995            input.parse::<Token![mut]>()?;
 996        }
 997
 998        let mut has_self = false;
 999        let mut name = if (input.peek(Ident) || input.peek(Token![_]) || {
1000            has_self = allow_self && input.peek(Token![self]);
1001            has_self
1002        }) && input.peek2(Token![:])
1003            && !input.peek2(Token![::])
1004        {
1005            let name = input.call(Ident::parse_any)?;
1006            let colon: Token![:] = input.parse()?;
1007            Some((name, colon))
1008        } else {
1009            has_self = false;
1010            None
1011        };
1012
1013        let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self])
1014        {
1015            input.parse::<Token![mut]>()?;
1016            input.parse::<Token![self]>()?;
1017            None
1018        } else if has_mut_self && name.is_none() {
1019            input.parse::<Token![self]>()?;
1020            None
1021        } else {
1022            Some(input.parse()?)
1023        };
1024
1025        let ty = match ty {
1026            Some(ty) if !has_mut_self => ty,
1027            _ => {
1028                name = None;
1029                Type::Verbatim(verbatim::between(&begin, input))
1030            }
1031        };
1032
1033        Ok(BareFnArg { attrs, name, ty })
1034    }
1035
1036    fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> {
1037        Ok(BareVariadic {
1038            attrs,
1039            name: if input.peek(Ident) || input.peek(Token![_]) {
1040                let name = input.call(Ident::parse_any)?;
1041                let colon: Token![:] = input.parse()?;
1042                Some((name, colon))
1043            } else {
1044                None
1045            },
1046            dots: input.parse()?,
1047            comma: input.parse()?,
1048        })
1049    }
1050
1051    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1052    impl Parse for Abi {
1053        fn parse(input: ParseStream) -> Result<Self> {
1054            Ok(Abi {
1055                extern_token: input.parse()?,
1056                name: input.parse()?,
1057            })
1058        }
1059    }
1060
1061    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1062    impl Parse for Option<Abi> {
1063        fn parse(input: ParseStream) -> Result<Self> {
1064            if input.peek(Token![extern]) {
1065                input.parse().map(Some)
1066            } else {
1067                Ok(None)
1068            }
1069        }
1070    }
1071}
1072
1073#[cfg(feature = "printing")]
1074mod printing {
1075    use crate::attr::FilterAttrs;
1076    use crate::path;
1077    use crate::path::printing::PathStyle;
1078    use crate::print::TokensOrDefault;
1079    use crate::ty::{
1080        Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait,
1081        TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
1082        TypeTraitObject, TypeTuple,
1083    };
1084    use proc_macro2::TokenStream;
1085    use quote::{ToTokens, TokenStreamExt};
1086
1087    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1088    impl ToTokens for TypeSlice {
1089        fn to_tokens(&self, tokens: &mut TokenStream) {
1090            self.bracket_token.surround(tokens, |tokens| {
1091                self.elem.to_tokens(tokens);
1092            });
1093        }
1094    }
1095
1096    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1097    impl ToTokens for TypeArray {
1098        fn to_tokens(&self, tokens: &mut TokenStream) {
1099            self.bracket_token.surround(tokens, |tokens| {
1100                self.elem.to_tokens(tokens);
1101                self.semi_token.to_tokens(tokens);
1102                self.len.to_tokens(tokens);
1103            });
1104        }
1105    }
1106
1107    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1108    impl ToTokens for TypePtr {
1109        fn to_tokens(&self, tokens: &mut TokenStream) {
1110            self.star_token.to_tokens(tokens);
1111            match &self.mutability {
1112                Some(tok) => tok.to_tokens(tokens),
1113                None => {
1114                    TokensOrDefault(&self.const_token).to_tokens(tokens);
1115                }
1116            }
1117            self.elem.to_tokens(tokens);
1118        }
1119    }
1120
1121    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1122    impl ToTokens for TypeReference {
1123        fn to_tokens(&self, tokens: &mut TokenStream) {
1124            self.and_token.to_tokens(tokens);
1125            self.lifetime.to_tokens(tokens);
1126            self.mutability.to_tokens(tokens);
1127            self.elem.to_tokens(tokens);
1128        }
1129    }
1130
1131    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1132    impl ToTokens for TypeBareFn {
1133        fn to_tokens(&self, tokens: &mut TokenStream) {
1134            self.lifetimes.to_tokens(tokens);
1135            self.unsafety.to_tokens(tokens);
1136            self.abi.to_tokens(tokens);
1137            self.fn_token.to_tokens(tokens);
1138            self.paren_token.surround(tokens, |tokens| {
1139                self.inputs.to_tokens(tokens);
1140                if let Some(variadic) = &self.variadic {
1141                    if !self.inputs.empty_or_trailing() {
1142                        let span = variadic.dots.spans[0];
1143                        Token![,](span).to_tokens(tokens);
1144                    }
1145                    variadic.to_tokens(tokens);
1146                }
1147            });
1148            self.output.to_tokens(tokens);
1149        }
1150    }
1151
1152    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1153    impl ToTokens for TypeNever {
1154        fn to_tokens(&self, tokens: &mut TokenStream) {
1155            self.bang_token.to_tokens(tokens);
1156        }
1157    }
1158
1159    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1160    impl ToTokens for TypeTuple {
1161        fn to_tokens(&self, tokens: &mut TokenStream) {
1162            self.paren_token.surround(tokens, |tokens| {
1163                self.elems.to_tokens(tokens);
1164                // If we only have one argument, we need a trailing comma to
1165                // distinguish TypeTuple from TypeParen.
1166                if self.elems.len() == 1 && !self.elems.trailing_punct() {
1167                    <Token![,]>::default().to_tokens(tokens);
1168                }
1169            });
1170        }
1171    }
1172
1173    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1174    impl ToTokens for TypePath {
1175        fn to_tokens(&self, tokens: &mut TokenStream) {
1176            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::AsWritten);
1177        }
1178    }
1179
1180    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1181    impl ToTokens for TypeTraitObject {
1182        fn to_tokens(&self, tokens: &mut TokenStream) {
1183            self.dyn_token.to_tokens(tokens);
1184            self.bounds.to_tokens(tokens);
1185        }
1186    }
1187
1188    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1189    impl ToTokens for TypeImplTrait {
1190        fn to_tokens(&self, tokens: &mut TokenStream) {
1191            self.impl_token.to_tokens(tokens);
1192            self.bounds.to_tokens(tokens);
1193        }
1194    }
1195
1196    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1197    impl ToTokens for TypeGroup {
1198        fn to_tokens(&self, tokens: &mut TokenStream) {
1199            self.group_token.surround(tokens, |tokens| {
1200                self.elem.to_tokens(tokens);
1201            });
1202        }
1203    }
1204
1205    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1206    impl ToTokens for TypeParen {
1207        fn to_tokens(&self, tokens: &mut TokenStream) {
1208            self.paren_token.surround(tokens, |tokens| {
1209                self.elem.to_tokens(tokens);
1210            });
1211        }
1212    }
1213
1214    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1215    impl ToTokens for TypeInfer {
1216        fn to_tokens(&self, tokens: &mut TokenStream) {
1217            self.underscore_token.to_tokens(tokens);
1218        }
1219    }
1220
1221    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1222    impl ToTokens for TypeMacro {
1223        fn to_tokens(&self, tokens: &mut TokenStream) {
1224            self.mac.to_tokens(tokens);
1225        }
1226    }
1227
1228    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1229    impl ToTokens for ReturnType {
1230        fn to_tokens(&self, tokens: &mut TokenStream) {
1231            match self {
1232                ReturnType::Default => {}
1233                ReturnType::Type(arrow, ty) => {
1234                    arrow.to_tokens(tokens);
1235                    ty.to_tokens(tokens);
1236                }
1237            }
1238        }
1239    }
1240
1241    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1242    impl ToTokens for BareFnArg {
1243        fn to_tokens(&self, tokens: &mut TokenStream) {
1244            tokens.append_all(self.attrs.outer());
1245            if let Some((name, colon)) = &self.name {
1246                name.to_tokens(tokens);
1247                colon.to_tokens(tokens);
1248            }
1249            self.ty.to_tokens(tokens);
1250        }
1251    }
1252
1253    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1254    impl ToTokens for BareVariadic {
1255        fn to_tokens(&self, tokens: &mut TokenStream) {
1256            tokens.append_all(self.attrs.outer());
1257            if let Some((name, colon)) = &self.name {
1258                name.to_tokens(tokens);
1259                colon.to_tokens(tokens);
1260            }
1261            self.dots.to_tokens(tokens);
1262            self.comma.to_tokens(tokens);
1263        }
1264    }
1265
1266    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1267    impl ToTokens for Abi {
1268        fn to_tokens(&self, tokens: &mut TokenStream) {
1269            self.extern_token.to_tokens(tokens);
1270            self.name.to_tokens(tokens);
1271        }
1272    }
1273}
~/ Read-only file preview.