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