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