1 use super::*; 2 use crate::punctuated::Punctuated; 3 4 ast_struct! { 5 /// A path at which a named item is exported (e.g. `std::collections::HashMap`). 6 /// 7 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 8 /// feature.* 9 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 10 pub struct Path { 11 pub leading_colon: Option<Token![::]>, 12 pub segments: Punctuated<PathSegment, Token![::]>, 13 } 14 } 15 16 impl<T> From<T> for Path 17 where 18 T: Into<PathSegment>, 19 { from(segment: T) -> Self20 fn from(segment: T) -> Self { 21 let mut path = Path { 22 leading_colon: None, 23 segments: Punctuated::new(), 24 }; 25 path.segments.push_value(segment.into()); 26 path 27 } 28 } 29 30 ast_struct! { 31 /// A segment of a path together with any path arguments on that segment. 32 /// 33 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 34 /// feature.* 35 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 36 pub struct PathSegment { 37 pub ident: Ident, 38 pub arguments: PathArguments, 39 } 40 } 41 42 impl<T> From<T> for PathSegment 43 where 44 T: Into<Ident>, 45 { from(ident: T) -> Self46 fn from(ident: T) -> Self { 47 PathSegment { 48 ident: ident.into(), 49 arguments: PathArguments::None, 50 } 51 } 52 } 53 54 ast_enum! { 55 /// Angle bracketed or parenthesized arguments of a path segment. 56 /// 57 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 58 /// feature.* 59 /// 60 /// ## Angle bracketed 61 /// 62 /// The `<'a, T>` in `std::slice::iter<'a, T>`. 63 /// 64 /// ## Parenthesized 65 /// 66 /// The `(A, B) -> C` in `Fn(A, B) -> C`. 67 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 68 pub enum PathArguments { 69 None, 70 /// The `<'a, T>` in `std::slice::iter<'a, T>`. 71 AngleBracketed(AngleBracketedGenericArguments), 72 /// The `(A, B) -> C` in `Fn(A, B) -> C`. 73 Parenthesized(ParenthesizedGenericArguments), 74 } 75 } 76 77 impl Default for PathArguments { default() -> Self78 fn default() -> Self { 79 PathArguments::None 80 } 81 } 82 83 impl PathArguments { is_empty(&self) -> bool84 pub fn is_empty(&self) -> bool { 85 match self { 86 PathArguments::None => true, 87 PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(), 88 PathArguments::Parenthesized(_) => false, 89 } 90 } 91 92 #[cfg(feature = "parsing")] is_none(&self) -> bool93 fn is_none(&self) -> bool { 94 match *self { 95 PathArguments::None => true, 96 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false, 97 } 98 } 99 } 100 101 ast_enum! { 102 /// An individual generic argument, like `'a`, `T`, or `Item = T`. 103 /// 104 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 105 /// feature.* 106 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 107 pub enum GenericArgument { 108 /// A lifetime argument. 109 Lifetime(Lifetime), 110 /// A type argument. 111 Type(Type), 112 /// A binding (equality constraint) on an associated type: the `Item = 113 /// u8` in `Iterator<Item = u8>`. 114 Binding(Binding), 115 /// An associated type bound: `Iterator<Item: Display>`. 116 Constraint(Constraint), 117 /// A const expression. Must be inside of a block. 118 /// 119 /// NOTE: Identity expressions are represented as Type arguments, as 120 /// they are indistinguishable syntactically. 121 Const(Expr), 122 } 123 } 124 125 ast_struct! { 126 /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K, 127 /// V>`. 128 /// 129 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 130 /// feature.* 131 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 132 pub struct AngleBracketedGenericArguments { 133 pub colon2_token: Option<Token![::]>, 134 pub lt_token: Token![<], 135 pub args: Punctuated<GenericArgument, Token![,]>, 136 pub gt_token: Token![>], 137 } 138 } 139 140 ast_struct! { 141 /// A binding (equality constraint) on an associated type: `Item = u8`. 142 /// 143 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 144 /// feature.* 145 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 146 pub struct Binding { 147 pub ident: Ident, 148 pub eq_token: Token![=], 149 pub ty: Type, 150 } 151 } 152 153 ast_struct! { 154 /// An associated type bound: `Iterator<Item: Display>`. 155 /// 156 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 157 /// feature.* 158 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 159 pub struct Constraint { 160 pub ident: Ident, 161 pub colon_token: Token![:], 162 pub bounds: Punctuated<TypeParamBound, Token![+]>, 163 } 164 } 165 166 ast_struct! { 167 /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) -> 168 /// C`. 169 /// 170 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 171 /// feature.* 172 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 173 pub struct ParenthesizedGenericArguments { 174 pub paren_token: token::Paren, 175 /// `(A, B)` 176 pub inputs: Punctuated<Type, Token![,]>, 177 /// `C` 178 pub output: ReturnType, 179 } 180 } 181 182 ast_struct! { 183 /// The explicit Self type in a qualified path: the `T` in `<T as 184 /// Display>::fmt`. 185 /// 186 /// The actual path, including the trait and the associated item, is stored 187 /// separately. The `position` field represents the index of the associated 188 /// item qualified with this Self type. 189 /// 190 /// ```text 191 /// <Vec<T> as a::b::Trait>::AssociatedItem 192 /// ^~~~~~ ~~~~~~~~~~~~~~^ 193 /// ty position = 3 194 /// 195 /// <Vec<T>>::AssociatedItem 196 /// ^~~~~~ ^ 197 /// ty position = 0 198 /// ``` 199 /// 200 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 201 /// feature.* 202 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 203 pub struct QSelf { 204 pub lt_token: Token![<], 205 pub ty: Box<Type>, 206 pub position: usize, 207 pub as_token: Option<Token![as]>, 208 pub gt_token: Token![>], 209 } 210 } 211 212 #[cfg(feature = "parsing")] 213 pub mod parsing { 214 use super::*; 215 216 use crate::ext::IdentExt; 217 use crate::parse::{Parse, ParseStream, Result}; 218 219 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 220 impl Parse for Path { parse(input: ParseStream) -> Result<Self>221 fn parse(input: ParseStream) -> Result<Self> { 222 Self::parse_helper(input, false) 223 } 224 } 225 226 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 227 impl Parse for GenericArgument { parse(input: ParseStream) -> Result<Self>228 fn parse(input: ParseStream) -> Result<Self> { 229 if input.peek(Lifetime) && !input.peek2(Token![+]) { 230 return Ok(GenericArgument::Lifetime(input.parse()?)); 231 } 232 233 if input.peek(Ident) && input.peek2(Token![=]) { 234 return Ok(GenericArgument::Binding(input.parse()?)); 235 } 236 237 #[cfg(feature = "full")] 238 { 239 if input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]) { 240 return Ok(GenericArgument::Constraint(input.parse()?)); 241 } 242 } 243 244 if input.peek(Lit) || input.peek(token::Brace) { 245 return const_argument(input).map(GenericArgument::Const); 246 } 247 248 #[cfg(feature = "full")] 249 let begin = input.fork(); 250 251 let argument: Type = input.parse()?; 252 253 #[cfg(feature = "full")] 254 { 255 if match &argument { 256 Type::Path(argument) 257 if argument.qself.is_none() 258 && argument.path.leading_colon.is_none() 259 && argument.path.segments.len() == 1 => 260 { 261 match argument.path.segments[0].arguments { 262 PathArguments::AngleBracketed(_) => true, 263 _ => false, 264 } 265 } 266 _ => false, 267 } && if input.peek(Token![=]) { 268 input.parse::<Token![=]>()?; 269 input.parse::<Type>()?; 270 true 271 } else if input.peek(Token![:]) { 272 input.parse::<Token![:]>()?; 273 input.call(constraint_bounds)?; 274 true 275 } else { 276 false 277 } { 278 let verbatim = verbatim::between(begin, input); 279 return Ok(GenericArgument::Type(Type::Verbatim(verbatim))); 280 } 281 } 282 283 Ok(GenericArgument::Type(argument)) 284 } 285 } 286 const_argument(input: ParseStream) -> Result<Expr>287 pub fn const_argument(input: ParseStream) -> Result<Expr> { 288 let lookahead = input.lookahead1(); 289 290 if input.peek(Lit) { 291 let lit = input.parse()?; 292 return Ok(Expr::Lit(lit)); 293 } 294 295 if input.peek(token::Brace) { 296 #[cfg(feature = "full")] 297 { 298 let block: ExprBlock = input.parse()?; 299 return Ok(Expr::Block(block)); 300 } 301 302 #[cfg(not(feature = "full"))] 303 { 304 let begin = input.fork(); 305 let content; 306 braced!(content in input); 307 content.parse::<Expr>()?; 308 let verbatim = verbatim::between(begin, input); 309 return Ok(Expr::Verbatim(verbatim)); 310 } 311 } 312 313 Err(lookahead.error()) 314 } 315 316 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 317 impl Parse for AngleBracketedGenericArguments { parse(input: ParseStream) -> Result<Self>318 fn parse(input: ParseStream) -> Result<Self> { 319 Ok(AngleBracketedGenericArguments { 320 colon2_token: input.parse()?, 321 lt_token: input.parse()?, 322 args: { 323 let mut args = Punctuated::new(); 324 loop { 325 if input.peek(Token![>]) { 326 break; 327 } 328 let value = input.parse()?; 329 args.push_value(value); 330 if input.peek(Token![>]) { 331 break; 332 } 333 let punct = input.parse()?; 334 args.push_punct(punct); 335 } 336 args 337 }, 338 gt_token: input.parse()?, 339 }) 340 } 341 } 342 343 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 344 impl Parse for ParenthesizedGenericArguments { parse(input: ParseStream) -> Result<Self>345 fn parse(input: ParseStream) -> Result<Self> { 346 let content; 347 Ok(ParenthesizedGenericArguments { 348 paren_token: parenthesized!(content in input), 349 inputs: content.parse_terminated(Type::parse)?, 350 output: input.call(ReturnType::without_plus)?, 351 }) 352 } 353 } 354 355 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 356 impl Parse for PathSegment { parse(input: ParseStream) -> Result<Self>357 fn parse(input: ParseStream) -> Result<Self> { 358 Self::parse_helper(input, false) 359 } 360 } 361 362 impl PathSegment { parse_helper(input: ParseStream, expr_style: bool) -> Result<Self>363 fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 364 if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) { 365 let ident = input.call(Ident::parse_any)?; 366 return Ok(PathSegment::from(ident)); 367 } 368 369 let ident = if input.peek(Token![Self]) { 370 input.call(Ident::parse_any)? 371 } else { 372 input.parse()? 373 }; 374 375 if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=]) 376 || input.peek(Token![::]) && input.peek3(Token![<]) 377 { 378 Ok(PathSegment { 379 ident, 380 arguments: PathArguments::AngleBracketed(input.parse()?), 381 }) 382 } else { 383 Ok(PathSegment::from(ident)) 384 } 385 } 386 } 387 388 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 389 impl Parse for Binding { parse(input: ParseStream) -> Result<Self>390 fn parse(input: ParseStream) -> Result<Self> { 391 Ok(Binding { 392 ident: input.parse()?, 393 eq_token: input.parse()?, 394 ty: input.parse()?, 395 }) 396 } 397 } 398 399 #[cfg(feature = "full")] 400 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 401 impl Parse for Constraint { parse(input: ParseStream) -> Result<Self>402 fn parse(input: ParseStream) -> Result<Self> { 403 Ok(Constraint { 404 ident: input.parse()?, 405 colon_token: input.parse()?, 406 bounds: constraint_bounds(input)?, 407 }) 408 } 409 } 410 411 #[cfg(feature = "full")] constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>>412 fn constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>> { 413 let mut bounds = Punctuated::new(); 414 loop { 415 if input.peek(Token![,]) || input.peek(Token![>]) { 416 break; 417 } 418 let value = input.parse()?; 419 bounds.push_value(value); 420 if !input.peek(Token![+]) { 421 break; 422 } 423 let punct = input.parse()?; 424 bounds.push_punct(punct); 425 } 426 Ok(bounds) 427 } 428 429 impl Path { 430 /// Parse a `Path` containing no path arguments on any of its segments. 431 /// 432 /// *This function is available only if Syn is built with the `"parsing"` 433 /// feature.* 434 /// 435 /// # Example 436 /// 437 /// ``` 438 /// use syn::{Path, Result, Token}; 439 /// use syn::parse::{Parse, ParseStream}; 440 /// 441 /// // A simplified single `use` statement like: 442 /// // 443 /// // use std::collections::HashMap; 444 /// // 445 /// // Note that generic parameters are not allowed in a `use` statement 446 /// // so the following must not be accepted. 447 /// // 448 /// // use a::<b>::c; 449 /// struct SingleUse { 450 /// use_token: Token![use], 451 /// path: Path, 452 /// } 453 /// 454 /// impl Parse for SingleUse { 455 /// fn parse(input: ParseStream) -> Result<Self> { 456 /// Ok(SingleUse { 457 /// use_token: input.parse()?, 458 /// path: input.call(Path::parse_mod_style)?, 459 /// }) 460 /// } 461 /// } 462 /// ``` 463 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] parse_mod_style(input: ParseStream) -> Result<Self>464 pub fn parse_mod_style(input: ParseStream) -> Result<Self> { 465 Ok(Path { 466 leading_colon: input.parse()?, 467 segments: { 468 let mut segments = Punctuated::new(); 469 loop { 470 if !input.peek(Ident) 471 && !input.peek(Token![super]) 472 && !input.peek(Token![self]) 473 && !input.peek(Token![Self]) 474 && !input.peek(Token![crate]) 475 { 476 break; 477 } 478 let ident = Ident::parse_any(input)?; 479 segments.push_value(PathSegment::from(ident)); 480 if !input.peek(Token![::]) { 481 break; 482 } 483 let punct = input.parse()?; 484 segments.push_punct(punct); 485 } 486 if segments.is_empty() { 487 return Err(input.error("expected path")); 488 } else if segments.trailing_punct() { 489 return Err(input.error("expected path segment")); 490 } 491 segments 492 }, 493 }) 494 } 495 496 /// Determines whether this is a path of length 1 equal to the given 497 /// ident. 498 /// 499 /// For them to compare equal, it must be the case that: 500 /// 501 /// - the path has no leading colon, 502 /// - the number of path segments is 1, 503 /// - the first path segment has no angle bracketed or parenthesized 504 /// path arguments, and 505 /// - the ident of the first path segment is equal to the given one. 506 /// 507 /// *This function is available only if Syn is built with the `"parsing"` 508 /// feature.* 509 /// 510 /// # Example 511 /// 512 /// ``` 513 /// use syn::{Attribute, Error, Meta, NestedMeta, Result}; 514 /// # use std::iter::FromIterator; 515 /// 516 /// fn get_serde_meta_items(attr: &Attribute) -> Result<Vec<NestedMeta>> { 517 /// if attr.path.is_ident("serde") { 518 /// match attr.parse_meta()? { 519 /// Meta::List(meta) => Ok(Vec::from_iter(meta.nested)), 520 /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")), 521 /// } 522 /// } else { 523 /// Ok(Vec::new()) 524 /// } 525 /// } 526 /// ``` 527 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] is_ident<I: ?Sized>(&self, ident: &I) -> bool where Ident: PartialEq<I>,528 pub fn is_ident<I: ?Sized>(&self, ident: &I) -> bool 529 where 530 Ident: PartialEq<I>, 531 { 532 match self.get_ident() { 533 Some(id) => id == ident, 534 None => false, 535 } 536 } 537 538 /// If this path consists of a single ident, returns the ident. 539 /// 540 /// A path is considered an ident if: 541 /// 542 /// - the path has no leading colon, 543 /// - the number of path segments is 1, and 544 /// - the first path segment has no angle bracketed or parenthesized 545 /// path arguments. 546 /// 547 /// *This function is available only if Syn is built with the `"parsing"` 548 /// feature.* 549 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] get_ident(&self) -> Option<&Ident>550 pub fn get_ident(&self) -> Option<&Ident> { 551 if self.leading_colon.is_none() 552 && self.segments.len() == 1 553 && self.segments[0].arguments.is_none() 554 { 555 Some(&self.segments[0].ident) 556 } else { 557 None 558 } 559 } 560 parse_helper(input: ParseStream, expr_style: bool) -> Result<Self>561 pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 562 let mut path = Path { 563 leading_colon: input.parse()?, 564 segments: { 565 let mut segments = Punctuated::new(); 566 let value = PathSegment::parse_helper(input, expr_style)?; 567 segments.push_value(value); 568 segments 569 }, 570 }; 571 Path::parse_rest(input, &mut path, expr_style)?; 572 Ok(path) 573 } 574 parse_rest( input: ParseStream, path: &mut Self, expr_style: bool, ) -> Result<()>575 pub(crate) fn parse_rest( 576 input: ParseStream, 577 path: &mut Self, 578 expr_style: bool, 579 ) -> Result<()> { 580 while input.peek(Token![::]) { 581 let punct: Token![::] = input.parse()?; 582 path.segments.push_punct(punct); 583 let value = PathSegment::parse_helper(input, expr_style)?; 584 path.segments.push_value(value); 585 } 586 Ok(()) 587 } 588 } 589 qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)>590 pub fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> { 591 if input.peek(Token![<]) { 592 let lt_token: Token![<] = input.parse()?; 593 let this: Type = input.parse()?; 594 let path = if input.peek(Token![as]) { 595 let as_token: Token![as] = input.parse()?; 596 let path: Path = input.parse()?; 597 Some((as_token, path)) 598 } else { 599 None 600 }; 601 let gt_token: Token![>] = input.parse()?; 602 let colon2_token: Token![::] = input.parse()?; 603 let mut rest = Punctuated::new(); 604 loop { 605 let path = PathSegment::parse_helper(input, expr_style)?; 606 rest.push_value(path); 607 if !input.peek(Token![::]) { 608 break; 609 } 610 let punct: Token![::] = input.parse()?; 611 rest.push_punct(punct); 612 } 613 let (position, as_token, path) = match path { 614 Some((as_token, mut path)) => { 615 let pos = path.segments.len(); 616 path.segments.push_punct(colon2_token); 617 path.segments.extend(rest.into_pairs()); 618 (pos, Some(as_token), path) 619 } 620 None => { 621 let path = Path { 622 leading_colon: Some(colon2_token), 623 segments: rest, 624 }; 625 (0, None, path) 626 } 627 }; 628 let qself = QSelf { 629 lt_token, 630 ty: Box::new(this), 631 position, 632 as_token, 633 gt_token, 634 }; 635 Ok((Some(qself), path)) 636 } else { 637 let path = Path::parse_helper(input, expr_style)?; 638 Ok((None, path)) 639 } 640 } 641 } 642 643 #[cfg(feature = "printing")] 644 mod printing { 645 use super::*; 646 use crate::print::TokensOrDefault; 647 use proc_macro2::TokenStream; 648 use quote::ToTokens; 649 use std::cmp; 650 651 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 652 impl ToTokens for Path { to_tokens(&self, tokens: &mut TokenStream)653 fn to_tokens(&self, tokens: &mut TokenStream) { 654 self.leading_colon.to_tokens(tokens); 655 self.segments.to_tokens(tokens); 656 } 657 } 658 659 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 660 impl ToTokens for PathSegment { to_tokens(&self, tokens: &mut TokenStream)661 fn to_tokens(&self, tokens: &mut TokenStream) { 662 self.ident.to_tokens(tokens); 663 self.arguments.to_tokens(tokens); 664 } 665 } 666 667 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 668 impl ToTokens for PathArguments { to_tokens(&self, tokens: &mut TokenStream)669 fn to_tokens(&self, tokens: &mut TokenStream) { 670 match self { 671 PathArguments::None => {} 672 PathArguments::AngleBracketed(arguments) => { 673 arguments.to_tokens(tokens); 674 } 675 PathArguments::Parenthesized(arguments) => { 676 arguments.to_tokens(tokens); 677 } 678 } 679 } 680 } 681 682 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 683 impl ToTokens for GenericArgument { 684 #[allow(clippy::match_same_arms)] to_tokens(&self, tokens: &mut TokenStream)685 fn to_tokens(&self, tokens: &mut TokenStream) { 686 match self { 687 GenericArgument::Lifetime(lt) => lt.to_tokens(tokens), 688 GenericArgument::Type(ty) => ty.to_tokens(tokens), 689 GenericArgument::Binding(tb) => tb.to_tokens(tokens), 690 GenericArgument::Constraint(tc) => tc.to_tokens(tokens), 691 GenericArgument::Const(e) => match *e { 692 Expr::Lit(_) => e.to_tokens(tokens), 693 694 // NOTE: We should probably support parsing blocks with only 695 // expressions in them without the full feature for const 696 // generics. 697 #[cfg(feature = "full")] 698 Expr::Block(_) => e.to_tokens(tokens), 699 700 // ERROR CORRECTION: Add braces to make sure that the 701 // generated code is valid. 702 _ => token::Brace::default().surround(tokens, |tokens| { 703 e.to_tokens(tokens); 704 }), 705 }, 706 } 707 } 708 } 709 710 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 711 impl ToTokens for AngleBracketedGenericArguments { to_tokens(&self, tokens: &mut TokenStream)712 fn to_tokens(&self, tokens: &mut TokenStream) { 713 self.colon2_token.to_tokens(tokens); 714 self.lt_token.to_tokens(tokens); 715 716 // Print lifetimes before types and consts, all before bindings, 717 // regardless of their order in self.args. 718 // 719 // TODO: ordering rules for const arguments vs type arguments have 720 // not been settled yet. https://github.com/rust-lang/rust/issues/44580 721 let mut trailing_or_empty = true; 722 for param in self.args.pairs() { 723 match **param.value() { 724 GenericArgument::Lifetime(_) => { 725 param.to_tokens(tokens); 726 trailing_or_empty = param.punct().is_some(); 727 } 728 GenericArgument::Type(_) 729 | GenericArgument::Binding(_) 730 | GenericArgument::Constraint(_) 731 | GenericArgument::Const(_) => {} 732 } 733 } 734 for param in self.args.pairs() { 735 match **param.value() { 736 GenericArgument::Type(_) | GenericArgument::Const(_) => { 737 if !trailing_or_empty { 738 <Token![,]>::default().to_tokens(tokens); 739 } 740 param.to_tokens(tokens); 741 trailing_or_empty = param.punct().is_some(); 742 } 743 GenericArgument::Lifetime(_) 744 | GenericArgument::Binding(_) 745 | GenericArgument::Constraint(_) => {} 746 } 747 } 748 for param in self.args.pairs() { 749 match **param.value() { 750 GenericArgument::Binding(_) | GenericArgument::Constraint(_) => { 751 if !trailing_or_empty { 752 <Token![,]>::default().to_tokens(tokens); 753 } 754 param.to_tokens(tokens); 755 trailing_or_empty = param.punct().is_some(); 756 } 757 GenericArgument::Lifetime(_) 758 | GenericArgument::Type(_) 759 | GenericArgument::Const(_) => {} 760 } 761 } 762 763 self.gt_token.to_tokens(tokens); 764 } 765 } 766 767 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 768 impl ToTokens for Binding { to_tokens(&self, tokens: &mut TokenStream)769 fn to_tokens(&self, tokens: &mut TokenStream) { 770 self.ident.to_tokens(tokens); 771 self.eq_token.to_tokens(tokens); 772 self.ty.to_tokens(tokens); 773 } 774 } 775 776 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 777 impl ToTokens for Constraint { to_tokens(&self, tokens: &mut TokenStream)778 fn to_tokens(&self, tokens: &mut TokenStream) { 779 self.ident.to_tokens(tokens); 780 self.colon_token.to_tokens(tokens); 781 self.bounds.to_tokens(tokens); 782 } 783 } 784 785 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 786 impl ToTokens for ParenthesizedGenericArguments { to_tokens(&self, tokens: &mut TokenStream)787 fn to_tokens(&self, tokens: &mut TokenStream) { 788 self.paren_token.surround(tokens, |tokens| { 789 self.inputs.to_tokens(tokens); 790 }); 791 self.output.to_tokens(tokens); 792 } 793 } 794 795 impl private { print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path)796 pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) { 797 let qself = match qself { 798 Some(qself) => qself, 799 None => { 800 path.to_tokens(tokens); 801 return; 802 } 803 }; 804 qself.lt_token.to_tokens(tokens); 805 qself.ty.to_tokens(tokens); 806 807 let pos = cmp::min(qself.position, path.segments.len()); 808 let mut segments = path.segments.pairs(); 809 if pos > 0 { 810 TokensOrDefault(&qself.as_token).to_tokens(tokens); 811 path.leading_colon.to_tokens(tokens); 812 for (i, segment) in segments.by_ref().take(pos).enumerate() { 813 if i + 1 == pos { 814 segment.value().to_tokens(tokens); 815 qself.gt_token.to_tokens(tokens); 816 segment.punct().to_tokens(tokens); 817 } else { 818 segment.to_tokens(tokens); 819 } 820 } 821 } else { 822 qself.gt_token.to_tokens(tokens); 823 path.leading_colon.to_tokens(tokens); 824 } 825 for segment in segments { 826 segment.to_tokens(tokens); 827 } 828 } 829 } 830 } 831