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}
1217