1 use super::*; 2 use crate::punctuated::{Iter, IterMut, Punctuated}; 3 #[cfg(all(feature = "printing", feature = "extra-traits"))] 4 use std::fmt::{self, Debug}; 5 #[cfg(all(feature = "printing", feature = "extra-traits"))] 6 use std::hash::{Hash, Hasher}; 7 8 ast_struct! { 9 /// Lifetimes and type parameters attached to a declaration of a function, 10 /// enum, trait, etc. 11 /// 12 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 13 /// feature.* 14 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 15 pub struct Generics { 16 pub lt_token: Option<Token![<]>, 17 pub params: Punctuated<GenericParam, Token![,]>, 18 pub gt_token: Option<Token![>]>, 19 pub where_clause: Option<WhereClause>, 20 } 21 } 22 23 ast_enum_of_structs! { 24 /// A generic type parameter, lifetime, or const generic: `T: Into<String>`, 25 /// `'a: 'b`, `const LEN: usize`. 26 /// 27 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 28 /// feature.* 29 /// 30 /// # Syntax tree enum 31 /// 32 /// This type is a [syntax tree enum]. 33 /// 34 /// [syntax tree enum]: Expr#syntax-tree-enums 35 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 36 pub enum GenericParam { 37 /// A generic type parameter: `T: Into<String>`. 38 Type(TypeParam), 39 40 /// A lifetime definition: `'a: 'b + 'c + 'd`. 41 Lifetime(LifetimeDef), 42 43 /// A const generic parameter: `const LENGTH: usize`. 44 Const(ConstParam), 45 } 46 } 47 48 ast_struct! { 49 /// A generic type parameter: `T: Into<String>`. 50 /// 51 /// *This type is available only if Syn is built with the `"derive"` or 52 /// `"full"` feature.* 53 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 54 pub struct TypeParam { 55 pub attrs: Vec<Attribute>, 56 pub ident: Ident, 57 pub colon_token: Option<Token![:]>, 58 pub bounds: Punctuated<TypeParamBound, Token![+]>, 59 pub eq_token: Option<Token![=]>, 60 pub default: Option<Type>, 61 } 62 } 63 64 ast_struct! { 65 /// A lifetime definition: `'a: 'b + 'c + 'd`. 66 /// 67 /// *This type is available only if Syn is built with the `"derive"` or 68 /// `"full"` feature.* 69 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 70 pub struct LifetimeDef { 71 pub attrs: Vec<Attribute>, 72 pub lifetime: Lifetime, 73 pub colon_token: Option<Token![:]>, 74 pub bounds: Punctuated<Lifetime, Token![+]>, 75 } 76 } 77 78 ast_struct! { 79 /// A const generic parameter: `const LENGTH: usize`. 80 /// 81 /// *This type is available only if Syn is built with the `"derive"` or 82 /// `"full"` feature.* 83 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 84 pub struct ConstParam { 85 pub attrs: Vec<Attribute>, 86 pub const_token: Token![const], 87 pub ident: Ident, 88 pub colon_token: Token![:], 89 pub ty: Type, 90 pub eq_token: Option<Token![=]>, 91 pub default: Option<Expr>, 92 } 93 } 94 95 impl Default for Generics { default() -> Self96 fn default() -> Self { 97 Generics { 98 lt_token: None, 99 params: Punctuated::new(), 100 gt_token: None, 101 where_clause: None, 102 } 103 } 104 } 105 106 impl Generics { 107 /// Returns an 108 /// <code 109 /// style="padding-right:0;">Iterator<Item = &</code><a 110 /// href="struct.TypeParam.html"><code 111 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code 112 /// style="padding-left:0;">></code> 113 /// over the type parameters in `self.params`. type_params(&self) -> TypeParams114 pub fn type_params(&self) -> TypeParams { 115 TypeParams(self.params.iter()) 116 } 117 118 /// Returns an 119 /// <code 120 /// style="padding-right:0;">Iterator<Item = &mut </code><a 121 /// href="struct.TypeParam.html"><code 122 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code 123 /// style="padding-left:0;">></code> 124 /// over the type parameters in `self.params`. type_params_mut(&mut self) -> TypeParamsMut125 pub fn type_params_mut(&mut self) -> TypeParamsMut { 126 TypeParamsMut(self.params.iter_mut()) 127 } 128 129 /// Returns an 130 /// <code 131 /// style="padding-right:0;">Iterator<Item = &</code><a 132 /// href="struct.LifetimeDef.html"><code 133 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code 134 /// style="padding-left:0;">></code> 135 /// over the lifetime parameters in `self.params`. lifetimes(&self) -> Lifetimes136 pub fn lifetimes(&self) -> Lifetimes { 137 Lifetimes(self.params.iter()) 138 } 139 140 /// Returns an 141 /// <code 142 /// style="padding-right:0;">Iterator<Item = &mut </code><a 143 /// href="struct.LifetimeDef.html"><code 144 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code 145 /// style="padding-left:0;">></code> 146 /// over the lifetime parameters in `self.params`. lifetimes_mut(&mut self) -> LifetimesMut147 pub fn lifetimes_mut(&mut self) -> LifetimesMut { 148 LifetimesMut(self.params.iter_mut()) 149 } 150 151 /// Returns an 152 /// <code 153 /// style="padding-right:0;">Iterator<Item = &</code><a 154 /// href="struct.ConstParam.html"><code 155 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code 156 /// style="padding-left:0;">></code> 157 /// over the constant parameters in `self.params`. const_params(&self) -> ConstParams158 pub fn const_params(&self) -> ConstParams { 159 ConstParams(self.params.iter()) 160 } 161 162 /// Returns an 163 /// <code 164 /// style="padding-right:0;">Iterator<Item = &mut </code><a 165 /// href="struct.ConstParam.html"><code 166 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code 167 /// style="padding-left:0;">></code> 168 /// over the constant parameters in `self.params`. const_params_mut(&mut self) -> ConstParamsMut169 pub fn const_params_mut(&mut self) -> ConstParamsMut { 170 ConstParamsMut(self.params.iter_mut()) 171 } 172 173 /// Initializes an empty `where`-clause if there is not one present already. make_where_clause(&mut self) -> &mut WhereClause174 pub fn make_where_clause(&mut self) -> &mut WhereClause { 175 // This is Option::get_or_insert_with in Rust 1.20. 176 if self.where_clause.is_none() { 177 self.where_clause = Some(WhereClause { 178 where_token: <Token![where]>::default(), 179 predicates: Punctuated::new(), 180 }); 181 } 182 match &mut self.where_clause { 183 Some(where_clause) => where_clause, 184 None => unreachable!(), 185 } 186 } 187 } 188 189 pub struct TypeParams<'a>(Iter<'a, GenericParam>); 190 191 impl<'a> Iterator for TypeParams<'a> { 192 type Item = &'a TypeParam; 193 next(&mut self) -> Option<Self::Item>194 fn next(&mut self) -> Option<Self::Item> { 195 let next = match self.0.next() { 196 Some(item) => item, 197 None => return None, 198 }; 199 if let GenericParam::Type(type_param) = next { 200 Some(type_param) 201 } else { 202 self.next() 203 } 204 } 205 } 206 207 pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>); 208 209 impl<'a> Iterator for TypeParamsMut<'a> { 210 type Item = &'a mut TypeParam; 211 next(&mut self) -> Option<Self::Item>212 fn next(&mut self) -> Option<Self::Item> { 213 let next = match self.0.next() { 214 Some(item) => item, 215 None => return None, 216 }; 217 if let GenericParam::Type(type_param) = next { 218 Some(type_param) 219 } else { 220 self.next() 221 } 222 } 223 } 224 225 pub struct Lifetimes<'a>(Iter<'a, GenericParam>); 226 227 impl<'a> Iterator for Lifetimes<'a> { 228 type Item = &'a LifetimeDef; 229 next(&mut self) -> Option<Self::Item>230 fn next(&mut self) -> Option<Self::Item> { 231 let next = match self.0.next() { 232 Some(item) => item, 233 None => return None, 234 }; 235 if let GenericParam::Lifetime(lifetime) = next { 236 Some(lifetime) 237 } else { 238 self.next() 239 } 240 } 241 } 242 243 pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>); 244 245 impl<'a> Iterator for LifetimesMut<'a> { 246 type Item = &'a mut LifetimeDef; 247 next(&mut self) -> Option<Self::Item>248 fn next(&mut self) -> Option<Self::Item> { 249 let next = match self.0.next() { 250 Some(item) => item, 251 None => return None, 252 }; 253 if let GenericParam::Lifetime(lifetime) = next { 254 Some(lifetime) 255 } else { 256 self.next() 257 } 258 } 259 } 260 261 pub struct ConstParams<'a>(Iter<'a, GenericParam>); 262 263 impl<'a> Iterator for ConstParams<'a> { 264 type Item = &'a ConstParam; 265 next(&mut self) -> Option<Self::Item>266 fn next(&mut self) -> Option<Self::Item> { 267 let next = match self.0.next() { 268 Some(item) => item, 269 None => return None, 270 }; 271 if let GenericParam::Const(const_param) = next { 272 Some(const_param) 273 } else { 274 self.next() 275 } 276 } 277 } 278 279 pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>); 280 281 impl<'a> Iterator for ConstParamsMut<'a> { 282 type Item = &'a mut ConstParam; 283 next(&mut self) -> Option<Self::Item>284 fn next(&mut self) -> Option<Self::Item> { 285 let next = match self.0.next() { 286 Some(item) => item, 287 None => return None, 288 }; 289 if let GenericParam::Const(const_param) = next { 290 Some(const_param) 291 } else { 292 self.next() 293 } 294 } 295 } 296 297 /// Returned by `Generics::split_for_impl`. 298 /// 299 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 300 /// feature and the `"printing"` feature.* 301 #[cfg(feature = "printing")] 302 #[cfg_attr( 303 doc_cfg, 304 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 305 )] 306 pub struct ImplGenerics<'a>(&'a Generics); 307 308 /// Returned by `Generics::split_for_impl`. 309 /// 310 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 311 /// feature and the `"printing"` feature.* 312 #[cfg(feature = "printing")] 313 #[cfg_attr( 314 doc_cfg, 315 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 316 )] 317 pub struct TypeGenerics<'a>(&'a Generics); 318 319 /// Returned by `TypeGenerics::as_turbofish`. 320 /// 321 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 322 /// feature and the `"printing"` feature.* 323 #[cfg(feature = "printing")] 324 #[cfg_attr( 325 doc_cfg, 326 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 327 )] 328 pub struct Turbofish<'a>(&'a Generics); 329 330 #[cfg(feature = "printing")] 331 impl Generics { 332 /// Split a type's generics into the pieces required for impl'ing a trait 333 /// for that type. 334 /// 335 /// ``` 336 /// # use proc_macro2::{Span, Ident}; 337 /// # use quote::quote; 338 /// # 339 /// # let generics: syn::Generics = Default::default(); 340 /// # let name = Ident::new("MyType", Span::call_site()); 341 /// # 342 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 343 /// quote! { 344 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { 345 /// // ... 346 /// } 347 /// } 348 /// # ; 349 /// ``` 350 /// 351 /// *This method is available only if Syn is built with the `"derive"` or 352 /// `"full"` feature and the `"printing"` feature.* 353 #[cfg_attr( 354 doc_cfg, 355 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 356 )] split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>)357 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { 358 ( 359 ImplGenerics(self), 360 TypeGenerics(self), 361 self.where_clause.as_ref(), 362 ) 363 } 364 } 365 366 #[cfg(feature = "printing")] 367 macro_rules! generics_wrapper_impls { 368 ($ty:ident) => { 369 #[cfg(feature = "clone-impls")] 370 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))] 371 impl<'a> Clone for $ty<'a> { 372 fn clone(&self) -> Self { 373 $ty(self.0) 374 } 375 } 376 377 #[cfg(feature = "extra-traits")] 378 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 379 impl<'a> Debug for $ty<'a> { 380 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 381 formatter 382 .debug_tuple(stringify!($ty)) 383 .field(self.0) 384 .finish() 385 } 386 } 387 388 #[cfg(feature = "extra-traits")] 389 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 390 impl<'a> Eq for $ty<'a> {} 391 392 #[cfg(feature = "extra-traits")] 393 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 394 impl<'a> PartialEq for $ty<'a> { 395 fn eq(&self, other: &Self) -> bool { 396 self.0 == other.0 397 } 398 } 399 400 #[cfg(feature = "extra-traits")] 401 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))] 402 impl<'a> Hash for $ty<'a> { 403 fn hash<H: Hasher>(&self, state: &mut H) { 404 self.0.hash(state); 405 } 406 } 407 }; 408 } 409 410 #[cfg(feature = "printing")] 411 generics_wrapper_impls!(ImplGenerics); 412 #[cfg(feature = "printing")] 413 generics_wrapper_impls!(TypeGenerics); 414 #[cfg(feature = "printing")] 415 generics_wrapper_impls!(Turbofish); 416 417 #[cfg(feature = "printing")] 418 impl<'a> TypeGenerics<'a> { 419 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`. 420 /// 421 /// *This method is available only if Syn is built with the `"derive"` or 422 /// `"full"` feature and the `"printing"` feature.* as_turbofish(&self) -> Turbofish423 pub fn as_turbofish(&self) -> Turbofish { 424 Turbofish(self.0) 425 } 426 } 427 428 ast_struct! { 429 /// A set of bound lifetimes: `for<'a, 'b, 'c>`. 430 /// 431 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 432 /// feature.* 433 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 434 pub struct BoundLifetimes { 435 pub for_token: Token![for], 436 pub lt_token: Token![<], 437 pub lifetimes: Punctuated<LifetimeDef, Token![,]>, 438 pub gt_token: Token![>], 439 } 440 } 441 442 impl Default for BoundLifetimes { default() -> Self443 fn default() -> Self { 444 BoundLifetimes { 445 for_token: Default::default(), 446 lt_token: Default::default(), 447 lifetimes: Punctuated::new(), 448 gt_token: Default::default(), 449 } 450 } 451 } 452 453 impl LifetimeDef { new(lifetime: Lifetime) -> Self454 pub fn new(lifetime: Lifetime) -> Self { 455 LifetimeDef { 456 attrs: Vec::new(), 457 lifetime, 458 colon_token: None, 459 bounds: Punctuated::new(), 460 } 461 } 462 } 463 464 impl From<Ident> for TypeParam { from(ident: Ident) -> Self465 fn from(ident: Ident) -> Self { 466 TypeParam { 467 attrs: vec![], 468 ident, 469 colon_token: None, 470 bounds: Punctuated::new(), 471 eq_token: None, 472 default: None, 473 } 474 } 475 } 476 477 ast_enum_of_structs! { 478 /// A trait or lifetime used as a bound on a type parameter. 479 /// 480 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 481 /// feature.* 482 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 483 pub enum TypeParamBound { 484 Trait(TraitBound), 485 Lifetime(Lifetime), 486 } 487 } 488 489 ast_struct! { 490 /// A trait used as a bound on a type parameter. 491 /// 492 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 493 /// feature.* 494 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 495 pub struct TraitBound { 496 pub paren_token: Option<token::Paren>, 497 pub modifier: TraitBoundModifier, 498 /// The `for<'a>` in `for<'a> Foo<&'a T>` 499 pub lifetimes: Option<BoundLifetimes>, 500 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>` 501 pub path: Path, 502 } 503 } 504 505 ast_enum! { 506 /// A modifier on a trait bound, currently only used for the `?` in 507 /// `?Sized`. 508 /// 509 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 510 /// feature.* 511 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 512 pub enum TraitBoundModifier { 513 None, 514 Maybe(Token![?]), 515 } 516 } 517 518 ast_struct! { 519 /// A `where` clause in a definition: `where T: Deserialize<'de>, D: 520 /// 'static`. 521 /// 522 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 523 /// feature.* 524 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 525 pub struct WhereClause { 526 pub where_token: Token![where], 527 pub predicates: Punctuated<WherePredicate, Token![,]>, 528 } 529 } 530 531 ast_enum_of_structs! { 532 /// A single predicate in a `where` clause: `T: Deserialize<'de>`. 533 /// 534 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 535 /// feature.* 536 /// 537 /// # Syntax tree enum 538 /// 539 /// This type is a [syntax tree enum]. 540 /// 541 /// [syntax tree enum]: Expr#syntax-tree-enums 542 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 543 pub enum WherePredicate { 544 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. 545 Type(PredicateType), 546 547 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. 548 Lifetime(PredicateLifetime), 549 550 /// An equality predicate in a `where` clause (unsupported). 551 Eq(PredicateEq), 552 } 553 } 554 555 ast_struct! { 556 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. 557 /// 558 /// *This type is available only if Syn is built with the `"derive"` or 559 /// `"full"` feature.* 560 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 561 pub struct PredicateType { 562 /// Any lifetimes from a `for` binding 563 pub lifetimes: Option<BoundLifetimes>, 564 /// The type being bounded 565 pub bounded_ty: Type, 566 pub colon_token: Token![:], 567 /// Trait and lifetime bounds (`Clone+Send+'static`) 568 pub bounds: Punctuated<TypeParamBound, Token![+]>, 569 } 570 } 571 572 ast_struct! { 573 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. 574 /// 575 /// *This type is available only if Syn is built with the `"derive"` or 576 /// `"full"` feature.* 577 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 578 pub struct PredicateLifetime { 579 pub lifetime: Lifetime, 580 pub colon_token: Token![:], 581 pub bounds: Punctuated<Lifetime, Token![+]>, 582 } 583 } 584 585 ast_struct! { 586 /// An equality predicate in a `where` clause (unsupported). 587 /// 588 /// *This type is available only if Syn is built with the `"derive"` or 589 /// `"full"` feature.* 590 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 591 pub struct PredicateEq { 592 pub lhs_ty: Type, 593 pub eq_token: Token![=], 594 pub rhs_ty: Type, 595 } 596 } 597 598 #[cfg(feature = "parsing")] 599 pub mod parsing { 600 use super::*; 601 use crate::ext::IdentExt; 602 use crate::parse::{Parse, ParseStream, Result}; 603 604 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 605 impl Parse for Generics { parse(input: ParseStream) -> Result<Self>606 fn parse(input: ParseStream) -> Result<Self> { 607 if !input.peek(Token![<]) { 608 return Ok(Generics::default()); 609 } 610 611 let lt_token: Token![<] = input.parse()?; 612 613 let mut params = Punctuated::new(); 614 loop { 615 if input.peek(Token![>]) { 616 break; 617 } 618 619 let attrs = input.call(Attribute::parse_outer)?; 620 let lookahead = input.lookahead1(); 621 if lookahead.peek(Lifetime) { 622 params.push_value(GenericParam::Lifetime(LifetimeDef { 623 attrs, 624 ..input.parse()? 625 })); 626 } else if lookahead.peek(Ident) { 627 params.push_value(GenericParam::Type(TypeParam { 628 attrs, 629 ..input.parse()? 630 })); 631 } else if lookahead.peek(Token![const]) { 632 params.push_value(GenericParam::Const(ConstParam { 633 attrs, 634 ..input.parse()? 635 })); 636 } else if input.peek(Token![_]) { 637 params.push_value(GenericParam::Type(TypeParam { 638 attrs, 639 ident: input.call(Ident::parse_any)?, 640 colon_token: None, 641 bounds: Punctuated::new(), 642 eq_token: None, 643 default: None, 644 })); 645 } else { 646 return Err(lookahead.error()); 647 } 648 649 if input.peek(Token![>]) { 650 break; 651 } 652 let punct = input.parse()?; 653 params.push_punct(punct); 654 } 655 656 let gt_token: Token![>] = input.parse()?; 657 658 Ok(Generics { 659 lt_token: Some(lt_token), 660 params, 661 gt_token: Some(gt_token), 662 where_clause: None, 663 }) 664 } 665 } 666 667 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 668 impl Parse for GenericParam { parse(input: ParseStream) -> Result<Self>669 fn parse(input: ParseStream) -> Result<Self> { 670 let attrs = input.call(Attribute::parse_outer)?; 671 672 let lookahead = input.lookahead1(); 673 if lookahead.peek(Ident) { 674 Ok(GenericParam::Type(TypeParam { 675 attrs, 676 ..input.parse()? 677 })) 678 } else if lookahead.peek(Lifetime) { 679 Ok(GenericParam::Lifetime(LifetimeDef { 680 attrs, 681 ..input.parse()? 682 })) 683 } else if lookahead.peek(Token![const]) { 684 Ok(GenericParam::Const(ConstParam { 685 attrs, 686 ..input.parse()? 687 })) 688 } else { 689 Err(lookahead.error()) 690 } 691 } 692 } 693 694 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 695 impl Parse for LifetimeDef { parse(input: ParseStream) -> Result<Self>696 fn parse(input: ParseStream) -> Result<Self> { 697 let has_colon; 698 Ok(LifetimeDef { 699 attrs: input.call(Attribute::parse_outer)?, 700 lifetime: input.parse()?, 701 colon_token: { 702 if input.peek(Token![:]) { 703 has_colon = true; 704 Some(input.parse()?) 705 } else { 706 has_colon = false; 707 None 708 } 709 }, 710 bounds: { 711 let mut bounds = Punctuated::new(); 712 if has_colon { 713 loop { 714 if input.peek(Token![,]) || input.peek(Token![>]) { 715 break; 716 } 717 let value = input.parse()?; 718 bounds.push_value(value); 719 if !input.peek(Token![+]) { 720 break; 721 } 722 let punct = input.parse()?; 723 bounds.push_punct(punct); 724 } 725 } 726 bounds 727 }, 728 }) 729 } 730 } 731 732 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 733 impl Parse for BoundLifetimes { parse(input: ParseStream) -> Result<Self>734 fn parse(input: ParseStream) -> Result<Self> { 735 Ok(BoundLifetimes { 736 for_token: input.parse()?, 737 lt_token: input.parse()?, 738 lifetimes: { 739 let mut lifetimes = Punctuated::new(); 740 while !input.peek(Token![>]) { 741 lifetimes.push_value(input.parse()?); 742 if input.peek(Token![>]) { 743 break; 744 } 745 lifetimes.push_punct(input.parse()?); 746 } 747 lifetimes 748 }, 749 gt_token: input.parse()?, 750 }) 751 } 752 } 753 754 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 755 impl Parse for Option<BoundLifetimes> { parse(input: ParseStream) -> Result<Self>756 fn parse(input: ParseStream) -> Result<Self> { 757 if input.peek(Token![for]) { 758 input.parse().map(Some) 759 } else { 760 Ok(None) 761 } 762 } 763 } 764 765 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 766 impl Parse for TypeParam { parse(input: ParseStream) -> Result<Self>767 fn parse(input: ParseStream) -> Result<Self> { 768 let attrs = input.call(Attribute::parse_outer)?; 769 let ident: Ident = input.parse()?; 770 let colon_token: Option<Token![:]> = input.parse()?; 771 772 let begin_bound = input.fork(); 773 let mut is_maybe_const = false; 774 let mut bounds = Punctuated::new(); 775 if colon_token.is_some() { 776 loop { 777 if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) { 778 break; 779 } 780 if input.peek(Token![?]) && input.peek2(Token![const]) { 781 input.parse::<Token![?]>()?; 782 input.parse::<Token![const]>()?; 783 is_maybe_const = true; 784 } 785 let value: TypeParamBound = input.parse()?; 786 bounds.push_value(value); 787 if !input.peek(Token![+]) { 788 break; 789 } 790 let punct: Token![+] = input.parse()?; 791 bounds.push_punct(punct); 792 } 793 } 794 795 let mut eq_token: Option<Token![=]> = input.parse()?; 796 let mut default = if eq_token.is_some() { 797 Some(input.parse::<Type>()?) 798 } else { 799 None 800 }; 801 802 if is_maybe_const { 803 bounds.clear(); 804 eq_token = None; 805 default = Some(Type::Verbatim(verbatim::between(begin_bound, input))); 806 } 807 808 Ok(TypeParam { 809 attrs, 810 ident, 811 colon_token, 812 bounds, 813 eq_token, 814 default, 815 }) 816 } 817 } 818 819 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 820 impl Parse for TypeParamBound { parse(input: ParseStream) -> Result<Self>821 fn parse(input: ParseStream) -> Result<Self> { 822 if input.peek(Lifetime) { 823 return input.parse().map(TypeParamBound::Lifetime); 824 } 825 826 if input.peek(token::Paren) { 827 let content; 828 let paren_token = parenthesized!(content in input); 829 let mut bound: TraitBound = content.parse()?; 830 bound.paren_token = Some(paren_token); 831 return Ok(TypeParamBound::Trait(bound)); 832 } 833 834 input.parse().map(TypeParamBound::Trait) 835 } 836 } 837 838 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 839 impl Parse for TraitBound { parse(input: ParseStream) -> Result<Self>840 fn parse(input: ParseStream) -> Result<Self> { 841 let modifier: TraitBoundModifier = input.parse()?; 842 let lifetimes: Option<BoundLifetimes> = input.parse()?; 843 844 let mut path: Path = input.parse()?; 845 if path.segments.last().unwrap().arguments.is_empty() && input.peek(token::Paren) { 846 let parenthesized = PathArguments::Parenthesized(input.parse()?); 847 path.segments.last_mut().unwrap().arguments = parenthesized; 848 } 849 850 Ok(TraitBound { 851 paren_token: None, 852 modifier, 853 lifetimes, 854 path, 855 }) 856 } 857 } 858 859 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 860 impl Parse for TraitBoundModifier { parse(input: ParseStream) -> Result<Self>861 fn parse(input: ParseStream) -> Result<Self> { 862 if input.peek(Token![?]) { 863 input.parse().map(TraitBoundModifier::Maybe) 864 } else { 865 Ok(TraitBoundModifier::None) 866 } 867 } 868 } 869 870 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 871 impl Parse for ConstParam { parse(input: ParseStream) -> Result<Self>872 fn parse(input: ParseStream) -> Result<Self> { 873 let mut default = None; 874 Ok(ConstParam { 875 attrs: input.call(Attribute::parse_outer)?, 876 const_token: input.parse()?, 877 ident: input.parse()?, 878 colon_token: input.parse()?, 879 ty: input.parse()?, 880 eq_token: { 881 if input.peek(Token![=]) { 882 let eq_token = input.parse()?; 883 default = Some(path::parsing::const_argument(input)?); 884 Some(eq_token) 885 } else { 886 None 887 } 888 }, 889 default, 890 }) 891 } 892 } 893 894 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 895 impl Parse for WhereClause { parse(input: ParseStream) -> Result<Self>896 fn parse(input: ParseStream) -> Result<Self> { 897 Ok(WhereClause { 898 where_token: input.parse()?, 899 predicates: { 900 let mut predicates = Punctuated::new(); 901 loop { 902 if input.is_empty() 903 || input.peek(token::Brace) 904 || input.peek(Token![,]) 905 || input.peek(Token![;]) 906 || input.peek(Token![:]) && !input.peek(Token![::]) 907 || input.peek(Token![=]) 908 { 909 break; 910 } 911 let value = input.parse()?; 912 predicates.push_value(value); 913 if !input.peek(Token![,]) { 914 break; 915 } 916 let punct = input.parse()?; 917 predicates.push_punct(punct); 918 } 919 predicates 920 }, 921 }) 922 } 923 } 924 925 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 926 impl Parse for Option<WhereClause> { parse(input: ParseStream) -> Result<Self>927 fn parse(input: ParseStream) -> Result<Self> { 928 if input.peek(Token![where]) { 929 input.parse().map(Some) 930 } else { 931 Ok(None) 932 } 933 } 934 } 935 936 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 937 impl Parse for WherePredicate { parse(input: ParseStream) -> Result<Self>938 fn parse(input: ParseStream) -> Result<Self> { 939 if input.peek(Lifetime) && input.peek2(Token![:]) { 940 Ok(WherePredicate::Lifetime(PredicateLifetime { 941 lifetime: input.parse()?, 942 colon_token: input.parse()?, 943 bounds: { 944 let mut bounds = Punctuated::new(); 945 loop { 946 if input.is_empty() 947 || input.peek(token::Brace) 948 || input.peek(Token![,]) 949 || input.peek(Token![;]) 950 || input.peek(Token![:]) 951 || input.peek(Token![=]) 952 { 953 break; 954 } 955 let value = input.parse()?; 956 bounds.push_value(value); 957 if !input.peek(Token![+]) { 958 break; 959 } 960 let punct = input.parse()?; 961 bounds.push_punct(punct); 962 } 963 bounds 964 }, 965 })) 966 } else { 967 Ok(WherePredicate::Type(PredicateType { 968 lifetimes: input.parse()?, 969 bounded_ty: input.parse()?, 970 colon_token: input.parse()?, 971 bounds: { 972 let mut bounds = Punctuated::new(); 973 loop { 974 if input.is_empty() 975 || input.peek(token::Brace) 976 || input.peek(Token![,]) 977 || input.peek(Token![;]) 978 || input.peek(Token![:]) && !input.peek(Token![::]) 979 || input.peek(Token![=]) 980 { 981 break; 982 } 983 let value = input.parse()?; 984 bounds.push_value(value); 985 if !input.peek(Token![+]) { 986 break; 987 } 988 let punct = input.parse()?; 989 bounds.push_punct(punct); 990 } 991 bounds 992 }, 993 })) 994 } 995 } 996 } 997 } 998 999 #[cfg(feature = "printing")] 1000 mod printing { 1001 use super::*; 1002 use crate::attr::FilterAttrs; 1003 use crate::print::TokensOrDefault; 1004 use proc_macro2::TokenStream; 1005 #[cfg(feature = "full")] 1006 use proc_macro2::TokenTree; 1007 use quote::{ToTokens, TokenStreamExt}; 1008 1009 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1010 impl ToTokens for Generics { to_tokens(&self, tokens: &mut TokenStream)1011 fn to_tokens(&self, tokens: &mut TokenStream) { 1012 if self.params.is_empty() { 1013 return; 1014 } 1015 1016 TokensOrDefault(&self.lt_token).to_tokens(tokens); 1017 1018 // Print lifetimes before types and consts, regardless of their 1019 // order in self.params. 1020 // 1021 // TODO: ordering rules for const parameters vs type parameters have 1022 // not been settled yet. https://github.com/rust-lang/rust/issues/44580 1023 let mut trailing_or_empty = true; 1024 for param in self.params.pairs() { 1025 if let GenericParam::Lifetime(_) = **param.value() { 1026 param.to_tokens(tokens); 1027 trailing_or_empty = param.punct().is_some(); 1028 } 1029 } 1030 for param in self.params.pairs() { 1031 match **param.value() { 1032 GenericParam::Type(_) | GenericParam::Const(_) => { 1033 if !trailing_or_empty { 1034 <Token![,]>::default().to_tokens(tokens); 1035 trailing_or_empty = true; 1036 } 1037 param.to_tokens(tokens); 1038 } 1039 GenericParam::Lifetime(_) => {} 1040 } 1041 } 1042 1043 TokensOrDefault(&self.gt_token).to_tokens(tokens); 1044 } 1045 } 1046 1047 impl<'a> ToTokens for ImplGenerics<'a> { to_tokens(&self, tokens: &mut TokenStream)1048 fn to_tokens(&self, tokens: &mut TokenStream) { 1049 if self.0.params.is_empty() { 1050 return; 1051 } 1052 1053 TokensOrDefault(&self.0.lt_token).to_tokens(tokens); 1054 1055 // Print lifetimes before types and consts, regardless of their 1056 // order in self.params. 1057 // 1058 // TODO: ordering rules for const parameters vs type parameters have 1059 // not been settled yet. https://github.com/rust-lang/rust/issues/44580 1060 let mut trailing_or_empty = true; 1061 for param in self.0.params.pairs() { 1062 if let GenericParam::Lifetime(_) = **param.value() { 1063 param.to_tokens(tokens); 1064 trailing_or_empty = param.punct().is_some(); 1065 } 1066 } 1067 for param in self.0.params.pairs() { 1068 if let GenericParam::Lifetime(_) = **param.value() { 1069 continue; 1070 } 1071 if !trailing_or_empty { 1072 <Token![,]>::default().to_tokens(tokens); 1073 trailing_or_empty = true; 1074 } 1075 match *param.value() { 1076 GenericParam::Lifetime(_) => unreachable!(), 1077 GenericParam::Type(param) => { 1078 // Leave off the type parameter defaults 1079 tokens.append_all(param.attrs.outer()); 1080 param.ident.to_tokens(tokens); 1081 if !param.bounds.is_empty() { 1082 TokensOrDefault(¶m.colon_token).to_tokens(tokens); 1083 param.bounds.to_tokens(tokens); 1084 } 1085 } 1086 GenericParam::Const(param) => { 1087 // Leave off the const parameter defaults 1088 tokens.append_all(param.attrs.outer()); 1089 param.const_token.to_tokens(tokens); 1090 param.ident.to_tokens(tokens); 1091 param.colon_token.to_tokens(tokens); 1092 param.ty.to_tokens(tokens); 1093 } 1094 } 1095 param.punct().to_tokens(tokens); 1096 } 1097 1098 TokensOrDefault(&self.0.gt_token).to_tokens(tokens); 1099 } 1100 } 1101 1102 impl<'a> ToTokens for TypeGenerics<'a> { to_tokens(&self, tokens: &mut TokenStream)1103 fn to_tokens(&self, tokens: &mut TokenStream) { 1104 if self.0.params.is_empty() { 1105 return; 1106 } 1107 1108 TokensOrDefault(&self.0.lt_token).to_tokens(tokens); 1109 1110 // Print lifetimes before types and consts, regardless of their 1111 // order in self.params. 1112 // 1113 // TODO: ordering rules for const parameters vs type parameters have 1114 // not been settled yet. https://github.com/rust-lang/rust/issues/44580 1115 let mut trailing_or_empty = true; 1116 for param in self.0.params.pairs() { 1117 if let GenericParam::Lifetime(def) = *param.value() { 1118 // Leave off the lifetime bounds and attributes 1119 def.lifetime.to_tokens(tokens); 1120 param.punct().to_tokens(tokens); 1121 trailing_or_empty = param.punct().is_some(); 1122 } 1123 } 1124 for param in self.0.params.pairs() { 1125 if let GenericParam::Lifetime(_) = **param.value() { 1126 continue; 1127 } 1128 if !trailing_or_empty { 1129 <Token![,]>::default().to_tokens(tokens); 1130 trailing_or_empty = true; 1131 } 1132 match *param.value() { 1133 GenericParam::Lifetime(_) => unreachable!(), 1134 GenericParam::Type(param) => { 1135 // Leave off the type parameter defaults 1136 param.ident.to_tokens(tokens); 1137 } 1138 GenericParam::Const(param) => { 1139 // Leave off the const parameter defaults 1140 param.ident.to_tokens(tokens); 1141 } 1142 } 1143 param.punct().to_tokens(tokens); 1144 } 1145 1146 TokensOrDefault(&self.0.gt_token).to_tokens(tokens); 1147 } 1148 } 1149 1150 impl<'a> ToTokens for Turbofish<'a> { to_tokens(&self, tokens: &mut TokenStream)1151 fn to_tokens(&self, tokens: &mut TokenStream) { 1152 if !self.0.params.is_empty() { 1153 <Token![::]>::default().to_tokens(tokens); 1154 TypeGenerics(self.0).to_tokens(tokens); 1155 } 1156 } 1157 } 1158 1159 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1160 impl ToTokens for BoundLifetimes { to_tokens(&self, tokens: &mut TokenStream)1161 fn to_tokens(&self, tokens: &mut TokenStream) { 1162 self.for_token.to_tokens(tokens); 1163 self.lt_token.to_tokens(tokens); 1164 self.lifetimes.to_tokens(tokens); 1165 self.gt_token.to_tokens(tokens); 1166 } 1167 } 1168 1169 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1170 impl ToTokens for LifetimeDef { to_tokens(&self, tokens: &mut TokenStream)1171 fn to_tokens(&self, tokens: &mut TokenStream) { 1172 tokens.append_all(self.attrs.outer()); 1173 self.lifetime.to_tokens(tokens); 1174 if !self.bounds.is_empty() { 1175 TokensOrDefault(&self.colon_token).to_tokens(tokens); 1176 self.bounds.to_tokens(tokens); 1177 } 1178 } 1179 } 1180 1181 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1182 impl ToTokens for TypeParam { to_tokens(&self, tokens: &mut TokenStream)1183 fn to_tokens(&self, tokens: &mut TokenStream) { 1184 tokens.append_all(self.attrs.outer()); 1185 self.ident.to_tokens(tokens); 1186 if !self.bounds.is_empty() { 1187 TokensOrDefault(&self.colon_token).to_tokens(tokens); 1188 self.bounds.to_tokens(tokens); 1189 } 1190 if let Some(default) = &self.default { 1191 #[cfg(feature = "full")] 1192 { 1193 if self.eq_token.is_none() { 1194 if let Type::Verbatim(default) = default { 1195 let mut iter = default.clone().into_iter().peekable(); 1196 while let Some(token) = iter.next() { 1197 if let TokenTree::Punct(q) = token { 1198 if q.as_char() == '?' { 1199 if let Some(TokenTree::Ident(c)) = iter.peek() { 1200 if c == "const" { 1201 if self.bounds.is_empty() { 1202 TokensOrDefault(&self.colon_token) 1203 .to_tokens(tokens); 1204 } 1205 return default.to_tokens(tokens); 1206 } 1207 } 1208 } 1209 } 1210 } 1211 } 1212 } 1213 } 1214 TokensOrDefault(&self.eq_token).to_tokens(tokens); 1215 default.to_tokens(tokens); 1216 } 1217 } 1218 } 1219 1220 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1221 impl ToTokens for TraitBound { to_tokens(&self, tokens: &mut TokenStream)1222 fn to_tokens(&self, tokens: &mut TokenStream) { 1223 let to_tokens = |tokens: &mut TokenStream| { 1224 self.modifier.to_tokens(tokens); 1225 self.lifetimes.to_tokens(tokens); 1226 self.path.to_tokens(tokens); 1227 }; 1228 match &self.paren_token { 1229 Some(paren) => paren.surround(tokens, to_tokens), 1230 None => to_tokens(tokens), 1231 } 1232 } 1233 } 1234 1235 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1236 impl ToTokens for TraitBoundModifier { to_tokens(&self, tokens: &mut TokenStream)1237 fn to_tokens(&self, tokens: &mut TokenStream) { 1238 match self { 1239 TraitBoundModifier::None => {} 1240 TraitBoundModifier::Maybe(t) => t.to_tokens(tokens), 1241 } 1242 } 1243 } 1244 1245 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1246 impl ToTokens for ConstParam { to_tokens(&self, tokens: &mut TokenStream)1247 fn to_tokens(&self, tokens: &mut TokenStream) { 1248 tokens.append_all(self.attrs.outer()); 1249 self.const_token.to_tokens(tokens); 1250 self.ident.to_tokens(tokens); 1251 self.colon_token.to_tokens(tokens); 1252 self.ty.to_tokens(tokens); 1253 if let Some(default) = &self.default { 1254 TokensOrDefault(&self.eq_token).to_tokens(tokens); 1255 default.to_tokens(tokens); 1256 } 1257 } 1258 } 1259 1260 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1261 impl ToTokens for WhereClause { to_tokens(&self, tokens: &mut TokenStream)1262 fn to_tokens(&self, tokens: &mut TokenStream) { 1263 if !self.predicates.is_empty() { 1264 self.where_token.to_tokens(tokens); 1265 self.predicates.to_tokens(tokens); 1266 } 1267 } 1268 } 1269 1270 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1271 impl ToTokens for PredicateType { to_tokens(&self, tokens: &mut TokenStream)1272 fn to_tokens(&self, tokens: &mut TokenStream) { 1273 self.lifetimes.to_tokens(tokens); 1274 self.bounded_ty.to_tokens(tokens); 1275 self.colon_token.to_tokens(tokens); 1276 self.bounds.to_tokens(tokens); 1277 } 1278 } 1279 1280 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1281 impl ToTokens for PredicateLifetime { to_tokens(&self, tokens: &mut TokenStream)1282 fn to_tokens(&self, tokens: &mut TokenStream) { 1283 self.lifetime.to_tokens(tokens); 1284 self.colon_token.to_tokens(tokens); 1285 self.bounds.to_tokens(tokens); 1286 } 1287 } 1288 1289 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 1290 impl ToTokens for PredicateEq { to_tokens(&self, tokens: &mut TokenStream)1291 fn to_tokens(&self, tokens: &mut TokenStream) { 1292 self.lhs_ty.to_tokens(tokens); 1293 self.eq_token.to_tokens(tokens); 1294 self.rhs_ty.to_tokens(tokens); 1295 } 1296 } 1297 } 1298