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