Skip to main content

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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(doc_cfg, 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(input.parse()?);
406                        }
407                        bounds
408                    },
409                }));
410            }
411            let mut first: Type = content.parse()?;
412            if content.peek(Token![,]) {
413                return Ok(Type::Tuple(TypeTuple {
414                    paren_token,
415                    elems: {
416                        let mut elems = Punctuated::new();
417                        elems.push_value(first);
418                        elems.push_punct(content.parse()?);
419                        while !content.is_empty() {
420                            elems.push_value(content.parse()?);
421                            if content.is_empty() {
422                                break;
423                            }
424                            elems.push_punct(content.parse()?);
425                        }
426                        elems
427                    },
428                }));
429            }
430            if allow_plus && input.peek(Token![+]) {
431                loop {
432                    let first = match first {
433                        Type::Path(TypePath { qself: None, path }) => {
434                            TypeParamBound::Trait(TraitBound {
435                                paren_token: Some(paren_token),
436                                modifier: TraitBoundModifier::None,
437                                lifetimes: None,
438                                path,
439                            })
440                        }
441                        Type::TraitObject(TypeTraitObject {
442                            dyn_token: None,
443                            bounds,
444                        }) => {
445                            if bounds.len() > 1 || bounds.trailing_punct() {
446                                first = Type::TraitObject(TypeTraitObject {
447                                    dyn_token: None,
448                                    bounds,
449                                });
450                                break;
451                            }
452                            match bounds.into_iter().next().unwrap() {
453                                TypeParamBound::Trait(trait_bound) => {
454                                    TypeParamBound::Trait(TraitBound {
455                                        paren_token: Some(paren_token),
456                                        ..trait_bound
457                                    })
458                                }
459                                other @ (TypeParamBound::Lifetime(_)
460                                | TypeParamBound::Verbatim(_)) => other,
461                            }
462                        }
463                        _ => break,
464                    };
465                    return Ok(Type::TraitObject(TypeTraitObject {
466                        dyn_token: None,
467                        bounds: {
468                            let mut bounds = Punctuated::new();
469                            bounds.push_value(first);
470                            while let Some(plus) = input.parse()? {
471                                bounds.push_punct(plus);
472                                bounds.push_value(input.parse()?);
473                            }
474                            bounds
475                        },
476                    }));
477                }
478            }
479            Ok(Type::Paren(TypeParen {
480                paren_token,
481                elem: Box::new(first),
482            }))
483        } else if lookahead.peek(Token![fn])
484            || lookahead.peek(Token![unsafe])
485            || lookahead.peek(Token![extern])
486        {
487            let mut bare_fn: TypeBareFn = input.parse()?;
488            bare_fn.lifetimes = lifetimes;
489            Ok(Type::BareFn(bare_fn))
490        } else if lookahead.peek(Ident)
491            || input.peek(Token![super])
492            || input.peek(Token![self])
493            || input.peek(Token![Self])
494            || input.peek(Token![crate])
495            || lookahead.peek(Token![::])
496            || lookahead.peek(Token![<])
497        {
498            let ty: TypePath = input.parse()?;
499            if ty.qself.is_some() {
500                return Ok(Type::Path(ty));
501            }
502
503            if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() {
504                let bang_token: Token![!] = input.parse()?;
505                let (delimiter, tokens) = mac::parse_delimiter(input)?;
506                return Ok(Type::Macro(TypeMacro {
507                    mac: Macro {
508                        path: ty.path,
509                        bang_token,
510                        delimiter,
511                        tokens,
512                    },
513                }));
514            }
515
516            if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
517                let mut bounds = Punctuated::new();
518                bounds.push_value(TypeParamBound::Trait(TraitBound {
519                    paren_token: None,
520                    modifier: TraitBoundModifier::None,
521                    lifetimes,
522                    path: ty.path,
523                }));
524                if allow_plus {
525                    while input.peek(Token![+]) {
526                        bounds.push_punct(input.parse()?);
527                        if !(input.peek(Ident::peek_any)
528                            || input.peek(Token![::])
529                            || input.peek(Token![?])
530                            || input.peek(Lifetime)
531                            || input.peek(token::Paren))
532                        {
533                            break;
534                        }
535                        bounds.push_value(input.parse()?);
536                    }
537                }
538                return Ok(Type::TraitObject(TypeTraitObject {
539                    dyn_token: None,
540                    bounds,
541                }));
542            }
543
544            Ok(Type::Path(ty))
545        } else if lookahead.peek(Token![dyn]) {
546            let dyn_token: Token![dyn] = input.parse()?;
547            let dyn_span = dyn_token.span;
548            let star_token: Option<Token![*]> = input.parse()?;
549            let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?;
550            return Ok(if star_token.is_some() {
551                Type::Verbatim(verbatim::between(&begin, input))
552            } else {
553                Type::TraitObject(TypeTraitObject {
554                    dyn_token: Some(dyn_token),
555                    bounds,
556                })
557            });
558        } else if lookahead.peek(token::Bracket) {
559            let content;
560            let bracket_token = bracketed!(content in input);
561            let elem: Type = content.parse()?;
562            if content.peek(Token![;]) {
563                Ok(Type::Array(TypeArray {
564                    bracket_token,
565                    elem: Box::new(elem),
566                    semi_token: content.parse()?,
567                    len: content.parse()?,
568                }))
569            } else {
570                Ok(Type::Slice(TypeSlice {
571                    bracket_token,
572                    elem: Box::new(elem),
573                }))
574            }
575        } else if lookahead.peek(Token![*]) {
576            input.parse().map(Type::Ptr)
577        } else if lookahead.peek(Token![&]) {
578            input.parse().map(Type::Reference)
579        } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
580            input.parse().map(Type::Never)
581        } else if lookahead.peek(Token![impl]) {
582            TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait)
583        } else if lookahead.peek(Token![_]) {
584            input.parse().map(Type::Infer)
585        } else if lookahead.peek(Lifetime) {
586            input.parse().map(Type::TraitObject)
587        } else {
588            Err(lookahead.error())
589        }
590    }
591
592    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
593    impl Parse for TypeSlice {
594        fn parse(input: ParseStream) -> Result<Self> {
595            let content;
596            Ok(TypeSlice {
597                bracket_token: bracketed!(content in input),
598                elem: content.parse()?,
599            })
600        }
601    }
602
603    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
604    impl Parse for TypeArray {
605        fn parse(input: ParseStream) -> Result<Self> {
606            let content;
607            Ok(TypeArray {
608                bracket_token: bracketed!(content in input),
609                elem: content.parse()?,
610                semi_token: content.parse()?,
611                len: content.parse()?,
612            })
613        }
614    }
615
616    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
617    impl Parse for TypePtr {
618        fn parse(input: ParseStream) -> Result<Self> {
619            let star_token: Token![*] = input.parse()?;
620
621            let lookahead = input.lookahead1();
622            let (const_token, mutability) = if lookahead.peek(Token![const]) {
623                (Some(input.parse()?), None)
624            } else if lookahead.peek(Token![mut]) {
625                (None, Some(input.parse()?))
626            } else {
627                return Err(lookahead.error());
628            };
629
630            Ok(TypePtr {
631                star_token,
632                const_token,
633                mutability,
634                elem: Box::new(input.call(Type::without_plus)?),
635            })
636        }
637    }
638
639    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
640    impl Parse for TypeReference {
641        fn parse(input: ParseStream) -> Result<Self> {
642            Ok(TypeReference {
643                and_token: input.parse()?,
644                lifetime: input.parse()?,
645                mutability: input.parse()?,
646                // & binds tighter than +, so we don't allow + here.
647                elem: Box::new(input.call(Type::without_plus)?),
648            })
649        }
650    }
651
652    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
653    impl Parse for TypeBareFn {
654        fn parse(input: ParseStream) -> Result<Self> {
655            let args;
656            let mut variadic = None;
657
658            Ok(TypeBareFn {
659                lifetimes: input.parse()?,
660                unsafety: input.parse()?,
661                abi: input.parse()?,
662                fn_token: input.parse()?,
663                paren_token: parenthesized!(args in input),
664                inputs: {
665                    let mut inputs = Punctuated::new();
666
667                    while !args.is_empty() {
668                        let attrs = args.call(Attribute::parse_outer)?;
669
670                        if inputs.empty_or_trailing()
671                            && (args.peek(Token![...])
672                                || args.peek(Ident)
673                                    && args.peek2(Token![:])
674                                    && args.peek3(Token![...]))
675                        {
676                            variadic = Some(parse_bare_variadic(&args, attrs)?);
677                            break;
678                        }
679
680                        let allow_self = inputs.is_empty();
681                        let arg = parse_bare_fn_arg(&args, allow_self)?;
682                        inputs.push_value(BareFnArg { attrs, ..arg });
683                        if args.is_empty() {
684                            break;
685                        }
686
687                        let comma = args.parse()?;
688                        inputs.push_punct(comma);
689                    }
690
691                    inputs
692                },
693                variadic,
694                output: input.call(ReturnType::without_plus)?,
695            })
696        }
697    }
698
699    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
700    impl Parse for TypeNever {
701        fn parse(input: ParseStream) -> Result<Self> {
702            Ok(TypeNever {
703                bang_token: input.parse()?,
704            })
705        }
706    }
707
708    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
709    impl Parse for TypeInfer {
710        fn parse(input: ParseStream) -> Result<Self> {
711            Ok(TypeInfer {
712                underscore_token: input.parse()?,
713            })
714        }
715    }
716
717    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
718    impl Parse for TypeTuple {
719        fn parse(input: ParseStream) -> Result<Self> {
720            let content;
721            let paren_token = parenthesized!(content in input);
722
723            if content.is_empty() {
724                return Ok(TypeTuple {
725                    paren_token,
726                    elems: Punctuated::new(),
727                });
728            }
729
730            let first: Type = content.parse()?;
731            Ok(TypeTuple {
732                paren_token,
733                elems: {
734                    let mut elems = Punctuated::new();
735                    elems.push_value(first);
736                    elems.push_punct(content.parse()?);
737                    while !content.is_empty() {
738                        elems.push_value(content.parse()?);
739                        if content.is_empty() {
740                            break;
741                        }
742                        elems.push_punct(content.parse()?);
743                    }
744                    elems
745                },
746            })
747        }
748    }
749
750    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
751    impl Parse for TypeMacro {
752        fn parse(input: ParseStream) -> Result<Self> {
753            Ok(TypeMacro {
754                mac: input.parse()?,
755            })
756        }
757    }
758
759    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
760    impl Parse for TypePath {
761        fn parse(input: ParseStream) -> Result<Self> {
762            let expr_style = false;
763            let (qself, path) = path::parsing::qpath(input, expr_style)?;
764            Ok(TypePath { qself, path })
765        }
766    }
767
768    impl ReturnType {
769        #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
770        pub fn without_plus(input: ParseStream) -> Result<Self> {
771            let allow_plus = false;
772            Self::parse(input, allow_plus)
773        }
774
775        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
776            if input.peek(Token![->]) {
777                let arrow = input.parse()?;
778                let allow_group_generic = true;
779                let ty = ambig_ty(input, allow_plus, allow_group_generic)?;
780                Ok(ReturnType::Type(arrow, Box::new(ty)))
781            } else {
782                Ok(ReturnType::Default)
783            }
784        }
785    }
786
787    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
788    impl Parse for ReturnType {
789        fn parse(input: ParseStream) -> Result<Self> {
790            let allow_plus = true;
791            Self::parse(input, allow_plus)
792        }
793    }
794
795    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
796    impl Parse for TypeTraitObject {
797        fn parse(input: ParseStream) -> Result<Self> {
798            let allow_plus = true;
799            Self::parse(input, allow_plus)
800        }
801    }
802
803    impl TypeTraitObject {
804        #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
805        pub fn without_plus(input: ParseStream) -> Result<Self> {
806            let allow_plus = false;
807            Self::parse(input, allow_plus)
808        }
809
810        // Only allow multiple trait references if allow_plus is true.
811        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
812            let dyn_token: Option<Token![dyn]> = input.parse()?;
813            let dyn_span = match &dyn_token {
814                Some(token) => token.span,
815                None => input.span(),
816            };
817            let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?;
818            Ok(TypeTraitObject { dyn_token, bounds })
819        }
820
821        fn parse_bounds(
822            dyn_span: Span,
823            input: ParseStream,
824            allow_plus: bool,
825        ) -> Result<Punctuated<TypeParamBound, Token![+]>> {
826            let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
827            let mut last_lifetime_span = None;
828            let mut at_least_one_trait = false;
829            for bound in &bounds {
830                match bound {
831                    TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => {
832                        at_least_one_trait = true;
833                        break;
834                    }
835                    TypeParamBound::Lifetime(lifetime) => {
836                        last_lifetime_span = Some(lifetime.ident.span());
837                    }
838                }
839            }
840            // Just lifetimes like `'a + 'b` is not a TraitObject.
841            if !at_least_one_trait {
842                let msg = "at least one trait is required for an object type";
843                return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg));
844            }
845            Ok(bounds)
846        }
847    }
848
849    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
850    impl Parse for TypeImplTrait {
851        fn parse(input: ParseStream) -> Result<Self> {
852            let allow_plus = true;
853            Self::parse(input, allow_plus)
854        }
855    }
856
857    impl TypeImplTrait {
858        #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
859        pub fn without_plus(input: ParseStream) -> Result<Self> {
860            let allow_plus = false;
861            Self::parse(input, allow_plus)
862        }
863
864        pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
865            let impl_token: Token![impl] = input.parse()?;
866            let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
867            let mut last_lifetime_span = None;
868            let mut at_least_one_trait = false;
869            for bound in &bounds {
870                match bound {
871                    TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => {
872                        at_least_one_trait = true;
873                        break;
874                    }
875                    TypeParamBound::Lifetime(lifetime) => {
876                        last_lifetime_span = Some(lifetime.ident.span());
877                    }
878                }
879            }
880            if !at_least_one_trait {
881                let msg = "at least one trait must be specified";
882                return Err(error::new2(
883                    impl_token.span,
884                    last_lifetime_span.unwrap(),
885                    msg,
886                ));
887            }
888            Ok(TypeImplTrait { impl_token, bounds })
889        }
890    }
891
892    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
893    impl Parse for TypeGroup {
894        fn parse(input: ParseStream) -> Result<Self> {
895            let group = crate::group::parse_group(input)?;
896            Ok(TypeGroup {
897                group_token: group.token,
898                elem: group.content.parse()?,
899            })
900        }
901    }
902
903    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
904    impl Parse for TypeParen {
905        fn parse(input: ParseStream) -> Result<Self> {
906            let allow_plus = false;
907            Self::parse(input, allow_plus)
908        }
909    }
910
911    impl TypeParen {
912        fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
913            let content;
914            Ok(TypeParen {
915                paren_token: parenthesized!(content in input),
916                elem: Box::new({
917                    let allow_group_generic = true;
918                    ambig_ty(&content, allow_plus, allow_group_generic)?
919                }),
920            })
921        }
922    }
923
924    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
925    impl Parse for BareFnArg {
926        fn parse(input: ParseStream) -> Result<Self> {
927            let allow_self = false;
928            parse_bare_fn_arg(input, allow_self)
929        }
930    }
931
932    fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> {
933        let attrs = input.call(Attribute::parse_outer)?;
934
935        let begin = input.fork();
936
937        let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]);
938        if has_mut_self {
939            input.parse::<Token![mut]>()?;
940        }
941
942        let mut has_self = false;
943        let mut name = if (input.peek(Ident) || input.peek(Token![_]) || {
944            has_self = allow_self && input.peek(Token![self]);
945            has_self
946        }) && input.peek2(Token![:])
947            && !input.peek2(Token![::])
948        {
949            let name = input.call(Ident::parse_any)?;
950            let colon: Token![:] = input.parse()?;
951            Some((name, colon))
952        } else {
953            has_self = false;
954            None
955        };
956
957        let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self])
958        {
959            input.parse::<Token![mut]>()?;
960            input.parse::<Token![self]>()?;
961            None
962        } else if has_mut_self && name.is_none() {
963            input.parse::<Token![self]>()?;
964            None
965        } else {
966            Some(input.parse()?)
967        };
968
969        let ty = match ty {
970            Some(ty) if !has_mut_self => ty,
971            _ => {
972                name = None;
973                Type::Verbatim(verbatim::between(&begin, input))
974            }
975        };
976
977        Ok(BareFnArg { attrs, name, ty })
978    }
979
980    fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> {
981        Ok(BareVariadic {
982            attrs,
983            name: if input.peek(Ident) || input.peek(Token![_]) {
984                let name = input.call(Ident::parse_any)?;
985                let colon: Token![:] = input.parse()?;
986                Some((name, colon))
987            } else {
988                None
989            },
990            dots: input.parse()?,
991            comma: input.parse()?,
992        })
993    }
994
995    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
996    impl Parse for Abi {
997        fn parse(input: ParseStream) -> Result<Self> {
998            Ok(Abi {
999                extern_token: input.parse()?,
1000                name: input.parse()?,
1001            })
1002        }
1003    }
1004
1005    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1006    impl Parse for Option<Abi> {
1007        fn parse(input: ParseStream) -> Result<Self> {
1008            if input.peek(Token![extern]) {
1009                input.parse().map(Some)
1010            } else {
1011                Ok(None)
1012            }
1013        }
1014    }
1015}
1016
1017#[cfg(feature = "printing")]
1018mod printing {
1019    use crate::attr::FilterAttrs;
1020    use crate::path;
1021    use crate::print::TokensOrDefault;
1022    use crate::ty::{
1023        Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait,
1024        TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
1025        TypeTraitObject, TypeTuple,
1026    };
1027    use proc_macro2::TokenStream;
1028    use quote::{ToTokens, TokenStreamExt};
1029
1030    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1031    impl ToTokens for TypeSlice {
1032        fn to_tokens(&self, tokens: &mut TokenStream) {
1033            self.bracket_token.surround(tokens, |tokens| {
1034                self.elem.to_tokens(tokens);
1035            });
1036        }
1037    }
1038
1039    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1040    impl ToTokens for TypeArray {
1041        fn to_tokens(&self, tokens: &mut TokenStream) {
1042            self.bracket_token.surround(tokens, |tokens| {
1043                self.elem.to_tokens(tokens);
1044                self.semi_token.to_tokens(tokens);
1045                self.len.to_tokens(tokens);
1046            });
1047        }
1048    }
1049
1050    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1051    impl ToTokens for TypePtr {
1052        fn to_tokens(&self, tokens: &mut TokenStream) {
1053            self.star_token.to_tokens(tokens);
1054            match &self.mutability {
1055                Some(tok) => tok.to_tokens(tokens),
1056                None => {
1057                    TokensOrDefault(&self.const_token).to_tokens(tokens);
1058                }
1059            }
1060            self.elem.to_tokens(tokens);
1061        }
1062    }
1063
1064    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1065    impl ToTokens for TypeReference {
1066        fn to_tokens(&self, tokens: &mut TokenStream) {
1067            self.and_token.to_tokens(tokens);
1068            self.lifetime.to_tokens(tokens);
1069            self.mutability.to_tokens(tokens);
1070            self.elem.to_tokens(tokens);
1071        }
1072    }
1073
1074    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1075    impl ToTokens for TypeBareFn {
1076        fn to_tokens(&self, tokens: &mut TokenStream) {
1077            self.lifetimes.to_tokens(tokens);
1078            self.unsafety.to_tokens(tokens);
1079            self.abi.to_tokens(tokens);
1080            self.fn_token.to_tokens(tokens);
1081            self.paren_token.surround(tokens, |tokens| {
1082                self.inputs.to_tokens(tokens);
1083                if let Some(variadic) = &self.variadic {
1084                    if !self.inputs.empty_or_trailing() {
1085                        let span = variadic.dots.spans[0];
1086                        Token![,](span).to_tokens(tokens);
1087                    }
1088                    variadic.to_tokens(tokens);
1089                }
1090            });
1091            self.output.to_tokens(tokens);
1092        }
1093    }
1094
1095    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1096    impl ToTokens for TypeNever {
1097        fn to_tokens(&self, tokens: &mut TokenStream) {
1098            self.bang_token.to_tokens(tokens);
1099        }
1100    }
1101
1102    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1103    impl ToTokens for TypeTuple {
1104        fn to_tokens(&self, tokens: &mut TokenStream) {
1105            self.paren_token.surround(tokens, |tokens| {
1106                self.elems.to_tokens(tokens);
1107                // If we only have one argument, we need a trailing comma to
1108                // distinguish TypeTuple from TypeParen.
1109                if self.elems.len() == 1 && !self.elems.trailing_punct() {
1110                    <Token![,]>::default().to_tokens(tokens);
1111                }
1112            });
1113        }
1114    }
1115
1116    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1117    impl ToTokens for TypePath {
1118        fn to_tokens(&self, tokens: &mut TokenStream) {
1119            path::printing::print_path(tokens, &self.qself, &self.path);
1120        }
1121    }
1122
1123    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1124    impl ToTokens for TypeTraitObject {
1125        fn to_tokens(&self, tokens: &mut TokenStream) {
1126            self.dyn_token.to_tokens(tokens);
1127            self.bounds.to_tokens(tokens);
1128        }
1129    }
1130
1131    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1132    impl ToTokens for TypeImplTrait {
1133        fn to_tokens(&self, tokens: &mut TokenStream) {
1134            self.impl_token.to_tokens(tokens);
1135            self.bounds.to_tokens(tokens);
1136        }
1137    }
1138
1139    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1140    impl ToTokens for TypeGroup {
1141        fn to_tokens(&self, tokens: &mut TokenStream) {
1142            self.group_token.surround(tokens, |tokens| {
1143                self.elem.to_tokens(tokens);
1144            });
1145        }
1146    }
1147
1148    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1149    impl ToTokens for TypeParen {
1150        fn to_tokens(&self, tokens: &mut TokenStream) {
1151            self.paren_token.surround(tokens, |tokens| {
1152                self.elem.to_tokens(tokens);
1153            });
1154        }
1155    }
1156
1157    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1158    impl ToTokens for TypeInfer {
1159        fn to_tokens(&self, tokens: &mut TokenStream) {
1160            self.underscore_token.to_tokens(tokens);
1161        }
1162    }
1163
1164    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1165    impl ToTokens for TypeMacro {
1166        fn to_tokens(&self, tokens: &mut TokenStream) {
1167            self.mac.to_tokens(tokens);
1168        }
1169    }
1170
1171    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1172    impl ToTokens for ReturnType {
1173        fn to_tokens(&self, tokens: &mut TokenStream) {
1174            match self {
1175                ReturnType::Default => {}
1176                ReturnType::Type(arrow, ty) => {
1177                    arrow.to_tokens(tokens);
1178                    ty.to_tokens(tokens);
1179                }
1180            }
1181        }
1182    }
1183
1184    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1185    impl ToTokens for BareFnArg {
1186        fn to_tokens(&self, tokens: &mut TokenStream) {
1187            tokens.append_all(self.attrs.outer());
1188            if let Some((name, colon)) = &self.name {
1189                name.to_tokens(tokens);
1190                colon.to_tokens(tokens);
1191            }
1192            self.ty.to_tokens(tokens);
1193        }
1194    }
1195
1196    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1197    impl ToTokens for BareVariadic {
1198        fn to_tokens(&self, tokens: &mut TokenStream) {
1199            tokens.append_all(self.attrs.outer());
1200            if let Some((name, colon)) = &self.name {
1201                name.to_tokens(tokens);
1202                colon.to_tokens(tokens);
1203            }
1204            self.dots.to_tokens(tokens);
1205            self.comma.to_tokens(tokens);
1206        }
1207    }
1208
1209    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1210    impl ToTokens for Abi {
1211        fn to_tokens(&self, tokens: &mut TokenStream) {
1212            self.extern_token.to_tokens(tokens);
1213            self.name.to_tokens(tokens);
1214        }
1215    }
1216}