]> git.proxmox.com Git - rustc.git/blob - vendor/syn/src/path.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / vendor / syn / src / path.rs
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 {
20 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 {
46 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 {
78 fn default() -> Self {
79 PathArguments::None
80 }
81 }
82
83 impl PathArguments {
84 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")]
93 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 {
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 {
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
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 #[cfg(feature = "full")]
296 {
297 if input.peek(Ident) {
298 let ident: Ident = input.parse()?;
299 return Ok(Expr::Path(ExprPath {
300 attrs: Vec::new(),
301 qself: None,
302 path: Path::from(ident),
303 }));
304 }
305 }
306
307 if input.peek(token::Brace) {
308 #[cfg(feature = "full")]
309 {
310 let block: ExprBlock = input.parse()?;
311 return Ok(Expr::Block(block));
312 }
313
314 #[cfg(not(feature = "full"))]
315 {
316 let begin = input.fork();
317 let content;
318 braced!(content in input);
319 content.parse::<Expr>()?;
320 let verbatim = verbatim::between(begin, input);
321 return Ok(Expr::Verbatim(verbatim));
322 }
323 }
324
325 Err(lookahead.error())
326 }
327
328 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
329 impl Parse for AngleBracketedGenericArguments {
330 fn parse(input: ParseStream) -> Result<Self> {
331 Ok(AngleBracketedGenericArguments {
332 colon2_token: input.parse()?,
333 lt_token: input.parse()?,
334 args: {
335 let mut args = Punctuated::new();
336 loop {
337 if input.peek(Token![>]) {
338 break;
339 }
340 let value = input.parse()?;
341 args.push_value(value);
342 if input.peek(Token![>]) {
343 break;
344 }
345 let punct = input.parse()?;
346 args.push_punct(punct);
347 }
348 args
349 },
350 gt_token: input.parse()?,
351 })
352 }
353 }
354
355 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
356 impl Parse for ParenthesizedGenericArguments {
357 fn parse(input: ParseStream) -> Result<Self> {
358 let content;
359 Ok(ParenthesizedGenericArguments {
360 paren_token: parenthesized!(content in input),
361 inputs: content.parse_terminated(Type::parse)?,
362 output: input.call(ReturnType::without_plus)?,
363 })
364 }
365 }
366
367 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
368 impl Parse for PathSegment {
369 fn parse(input: ParseStream) -> Result<Self> {
370 Self::parse_helper(input, false)
371 }
372 }
373
374 impl PathSegment {
375 fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
376 if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) {
377 let ident = input.call(Ident::parse_any)?;
378 return Ok(PathSegment::from(ident));
379 }
380
381 let ident = if input.peek(Token![Self]) {
382 input.call(Ident::parse_any)?
383 } else {
384 input.parse()?
385 };
386
387 if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=])
388 || input.peek(Token![::]) && input.peek3(Token![<])
389 {
390 Ok(PathSegment {
391 ident,
392 arguments: PathArguments::AngleBracketed(input.parse()?),
393 })
394 } else {
395 Ok(PathSegment::from(ident))
396 }
397 }
398 }
399
400 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
401 impl Parse for Binding {
402 fn parse(input: ParseStream) -> Result<Self> {
403 Ok(Binding {
404 ident: input.parse()?,
405 eq_token: input.parse()?,
406 ty: input.parse()?,
407 })
408 }
409 }
410
411 #[cfg(feature = "full")]
412 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
413 impl Parse for Constraint {
414 fn parse(input: ParseStream) -> Result<Self> {
415 Ok(Constraint {
416 ident: input.parse()?,
417 colon_token: input.parse()?,
418 bounds: constraint_bounds(input)?,
419 })
420 }
421 }
422
423 #[cfg(feature = "full")]
424 fn constraint_bounds(input: ParseStream) -> Result<Punctuated<TypeParamBound, Token![+]>> {
425 let mut bounds = Punctuated::new();
426 loop {
427 if input.peek(Token![,]) || input.peek(Token![>]) {
428 break;
429 }
430 let value = input.parse()?;
431 bounds.push_value(value);
432 if !input.peek(Token![+]) {
433 break;
434 }
435 let punct = input.parse()?;
436 bounds.push_punct(punct);
437 }
438 Ok(bounds)
439 }
440
441 impl Path {
442 /// Parse a `Path` containing no path arguments on any of its segments.
443 ///
444 /// *This function is available only if Syn is built with the `"parsing"`
445 /// feature.*
446 ///
447 /// # Example
448 ///
449 /// ```
450 /// use syn::{Path, Result, Token};
451 /// use syn::parse::{Parse, ParseStream};
452 ///
453 /// // A simplified single `use` statement like:
454 /// //
455 /// // use std::collections::HashMap;
456 /// //
457 /// // Note that generic parameters are not allowed in a `use` statement
458 /// // so the following must not be accepted.
459 /// //
460 /// // use a::<b>::c;
461 /// struct SingleUse {
462 /// use_token: Token![use],
463 /// path: Path,
464 /// }
465 ///
466 /// impl Parse for SingleUse {
467 /// fn parse(input: ParseStream) -> Result<Self> {
468 /// Ok(SingleUse {
469 /// use_token: input.parse()?,
470 /// path: input.call(Path::parse_mod_style)?,
471 /// })
472 /// }
473 /// }
474 /// ```
475 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
476 pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
477 Ok(Path {
478 leading_colon: input.parse()?,
479 segments: {
480 let mut segments = Punctuated::new();
481 loop {
482 if !input.peek(Ident)
483 && !input.peek(Token![super])
484 && !input.peek(Token![self])
485 && !input.peek(Token![Self])
486 && !input.peek(Token![crate])
487 {
488 break;
489 }
490 let ident = Ident::parse_any(input)?;
491 segments.push_value(PathSegment::from(ident));
492 if !input.peek(Token![::]) {
493 break;
494 }
495 let punct = input.parse()?;
496 segments.push_punct(punct);
497 }
498 if segments.is_empty() {
499 return Err(input.error("expected path"));
500 } else if segments.trailing_punct() {
501 return Err(input.error("expected path segment"));
502 }
503 segments
504 },
505 })
506 }
507
508 /// Determines whether this is a path of length 1 equal to the given
509 /// ident.
510 ///
511 /// For them to compare equal, it must be the case that:
512 ///
513 /// - the path has no leading colon,
514 /// - the number of path segments is 1,
515 /// - the first path segment has no angle bracketed or parenthesized
516 /// path arguments, and
517 /// - the ident of the first path segment is equal to the given one.
518 ///
519 /// *This function is available only if Syn is built with the `"parsing"`
520 /// feature.*
521 ///
522 /// # Example
523 ///
524 /// ```
525 /// use syn::{Attribute, Error, Meta, NestedMeta, Result};
526 /// # use std::iter::FromIterator;
527 ///
528 /// fn get_serde_meta_items(attr: &Attribute) -> Result<Vec<NestedMeta>> {
529 /// if attr.path.is_ident("serde") {
530 /// match attr.parse_meta()? {
531 /// Meta::List(meta) => Ok(Vec::from_iter(meta.nested)),
532 /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")),
533 /// }
534 /// } else {
535 /// Ok(Vec::new())
536 /// }
537 /// }
538 /// ```
539 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
540 pub fn is_ident<I: ?Sized>(&self, ident: &I) -> bool
541 where
542 Ident: PartialEq<I>,
543 {
544 match self.get_ident() {
545 Some(id) => id == ident,
546 None => false,
547 }
548 }
549
550 /// If this path consists of a single ident, returns the ident.
551 ///
552 /// A path is considered an ident if:
553 ///
554 /// - the path has no leading colon,
555 /// - the number of path segments is 1, and
556 /// - the first path segment has no angle bracketed or parenthesized
557 /// path arguments.
558 ///
559 /// *This function is available only if Syn is built with the `"parsing"`
560 /// feature.*
561 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
562 pub fn get_ident(&self) -> Option<&Ident> {
563 if self.leading_colon.is_none()
564 && self.segments.len() == 1
565 && self.segments[0].arguments.is_none()
566 {
567 Some(&self.segments[0].ident)
568 } else {
569 None
570 }
571 }
572
573 pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
574 let mut path = Path {
575 leading_colon: input.parse()?,
576 segments: {
577 let mut segments = Punctuated::new();
578 let value = PathSegment::parse_helper(input, expr_style)?;
579 segments.push_value(value);
580 segments
581 },
582 };
583 Path::parse_rest(input, &mut path, expr_style)?;
584 Ok(path)
585 }
586
587 pub(crate) fn parse_rest(
588 input: ParseStream,
589 path: &mut Self,
590 expr_style: bool,
591 ) -> Result<()> {
592 while input.peek(Token![::]) {
593 let punct: Token![::] = input.parse()?;
594 path.segments.push_punct(punct);
595 let value = PathSegment::parse_helper(input, expr_style)?;
596 path.segments.push_value(value);
597 }
598 Ok(())
599 }
600 }
601
602 pub fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
603 if input.peek(Token![<]) {
604 let lt_token: Token![<] = input.parse()?;
605 let this: Type = input.parse()?;
606 let path = if input.peek(Token![as]) {
607 let as_token: Token![as] = input.parse()?;
608 let path: Path = input.parse()?;
609 Some((as_token, path))
610 } else {
611 None
612 };
613 let gt_token: Token![>] = input.parse()?;
614 let colon2_token: Token![::] = input.parse()?;
615 let mut rest = Punctuated::new();
616 loop {
617 let path = PathSegment::parse_helper(input, expr_style)?;
618 rest.push_value(path);
619 if !input.peek(Token![::]) {
620 break;
621 }
622 let punct: Token![::] = input.parse()?;
623 rest.push_punct(punct);
624 }
625 let (position, as_token, path) = match path {
626 Some((as_token, mut path)) => {
627 let pos = path.segments.len();
628 path.segments.push_punct(colon2_token);
629 path.segments.extend(rest.into_pairs());
630 (pos, Some(as_token), path)
631 }
632 None => {
633 let path = Path {
634 leading_colon: Some(colon2_token),
635 segments: rest,
636 };
637 (0, None, path)
638 }
639 };
640 let qself = QSelf {
641 lt_token,
642 ty: Box::new(this),
643 position,
644 as_token,
645 gt_token,
646 };
647 Ok((Some(qself), path))
648 } else {
649 let path = Path::parse_helper(input, expr_style)?;
650 Ok((None, path))
651 }
652 }
653 }
654
655 #[cfg(feature = "printing")]
656 mod printing {
657 use super::*;
658 use crate::print::TokensOrDefault;
659 use proc_macro2::TokenStream;
660 use quote::ToTokens;
661 use std::cmp;
662
663 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
664 impl ToTokens for Path {
665 fn to_tokens(&self, tokens: &mut TokenStream) {
666 self.leading_colon.to_tokens(tokens);
667 self.segments.to_tokens(tokens);
668 }
669 }
670
671 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
672 impl ToTokens for PathSegment {
673 fn to_tokens(&self, tokens: &mut TokenStream) {
674 self.ident.to_tokens(tokens);
675 self.arguments.to_tokens(tokens);
676 }
677 }
678
679 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
680 impl ToTokens for PathArguments {
681 fn to_tokens(&self, tokens: &mut TokenStream) {
682 match self {
683 PathArguments::None => {}
684 PathArguments::AngleBracketed(arguments) => {
685 arguments.to_tokens(tokens);
686 }
687 PathArguments::Parenthesized(arguments) => {
688 arguments.to_tokens(tokens);
689 }
690 }
691 }
692 }
693
694 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
695 impl ToTokens for GenericArgument {
696 #[allow(clippy::match_same_arms)]
697 fn to_tokens(&self, tokens: &mut TokenStream) {
698 match self {
699 GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
700 GenericArgument::Type(ty) => ty.to_tokens(tokens),
701 GenericArgument::Binding(tb) => tb.to_tokens(tokens),
702 GenericArgument::Constraint(tc) => tc.to_tokens(tokens),
703 GenericArgument::Const(e) => match *e {
704 Expr::Lit(_) => e.to_tokens(tokens),
705
706 // NOTE: We should probably support parsing blocks with only
707 // expressions in them without the full feature for const
708 // generics.
709 #[cfg(feature = "full")]
710 Expr::Block(_) => e.to_tokens(tokens),
711
712 // ERROR CORRECTION: Add braces to make sure that the
713 // generated code is valid.
714 _ => token::Brace::default().surround(tokens, |tokens| {
715 e.to_tokens(tokens);
716 }),
717 },
718 }
719 }
720 }
721
722 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
723 impl ToTokens for AngleBracketedGenericArguments {
724 fn to_tokens(&self, tokens: &mut TokenStream) {
725 self.colon2_token.to_tokens(tokens);
726 self.lt_token.to_tokens(tokens);
727
728 // Print lifetimes before types and consts, all before bindings,
729 // regardless of their order in self.args.
730 //
731 // TODO: ordering rules for const arguments vs type arguments have
732 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
733 let mut trailing_or_empty = true;
734 for param in self.args.pairs() {
735 match **param.value() {
736 GenericArgument::Lifetime(_) => {
737 param.to_tokens(tokens);
738 trailing_or_empty = param.punct().is_some();
739 }
740 GenericArgument::Type(_)
741 | GenericArgument::Binding(_)
742 | GenericArgument::Constraint(_)
743 | GenericArgument::Const(_) => {}
744 }
745 }
746 for param in self.args.pairs() {
747 match **param.value() {
748 GenericArgument::Type(_) | GenericArgument::Const(_) => {
749 if !trailing_or_empty {
750 <Token![,]>::default().to_tokens(tokens);
751 }
752 param.to_tokens(tokens);
753 trailing_or_empty = param.punct().is_some();
754 }
755 GenericArgument::Lifetime(_)
756 | GenericArgument::Binding(_)
757 | GenericArgument::Constraint(_) => {}
758 }
759 }
760 for param in self.args.pairs() {
761 match **param.value() {
762 GenericArgument::Binding(_) | GenericArgument::Constraint(_) => {
763 if !trailing_or_empty {
764 <Token![,]>::default().to_tokens(tokens);
765 }
766 param.to_tokens(tokens);
767 trailing_or_empty = param.punct().is_some();
768 }
769 GenericArgument::Lifetime(_)
770 | GenericArgument::Type(_)
771 | GenericArgument::Const(_) => {}
772 }
773 }
774
775 self.gt_token.to_tokens(tokens);
776 }
777 }
778
779 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
780 impl ToTokens for Binding {
781 fn to_tokens(&self, tokens: &mut TokenStream) {
782 self.ident.to_tokens(tokens);
783 self.eq_token.to_tokens(tokens);
784 self.ty.to_tokens(tokens);
785 }
786 }
787
788 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
789 impl ToTokens for Constraint {
790 fn to_tokens(&self, tokens: &mut TokenStream) {
791 self.ident.to_tokens(tokens);
792 self.colon_token.to_tokens(tokens);
793 self.bounds.to_tokens(tokens);
794 }
795 }
796
797 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
798 impl ToTokens for ParenthesizedGenericArguments {
799 fn to_tokens(&self, tokens: &mut TokenStream) {
800 self.paren_token.surround(tokens, |tokens| {
801 self.inputs.to_tokens(tokens);
802 });
803 self.output.to_tokens(tokens);
804 }
805 }
806
807 impl private {
808 pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) {
809 let qself = match qself {
810 Some(qself) => qself,
811 None => {
812 path.to_tokens(tokens);
813 return;
814 }
815 };
816 qself.lt_token.to_tokens(tokens);
817 qself.ty.to_tokens(tokens);
818
819 let pos = cmp::min(qself.position, path.segments.len());
820 let mut segments = path.segments.pairs();
821 if pos > 0 {
822 TokensOrDefault(&qself.as_token).to_tokens(tokens);
823 path.leading_colon.to_tokens(tokens);
824 for (i, segment) in segments.by_ref().take(pos).enumerate() {
825 if i + 1 == pos {
826 segment.value().to_tokens(tokens);
827 qself.gt_token.to_tokens(tokens);
828 segment.punct().to_tokens(tokens);
829 } else {
830 segment.to_tokens(tokens);
831 }
832 }
833 } else {
834 qself.gt_token.to_tokens(tokens);
835 path.leading_colon.to_tokens(tokens);
836 }
837 for segment in segments {
838 segment.to_tokens(tokens);
839 }
840 }
841 }
842 }