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