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