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