syn/
ty.rs

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