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