1use super::*;
2use crate::punctuated::{Iter, IterMut, Punctuated};
3#[cfg(all(feature = "printing", feature = "extra-traits"))]
4use std::fmt::{self, Debug};
5#[cfg(all(feature = "printing", feature = "extra-traits"))]
6use std::hash::{Hash, Hasher};
7
8ast_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
23ast_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
48ast_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
64ast_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
78ast_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
95impl Default for Generics {
96 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
106impl 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`.
114 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`.
125 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`.
136 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`.
147 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`.
158 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`.
169 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.
174 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
182pub struct TypeParams<'a>(Iter<'a, GenericParam>);
183
184impl<'a> Iterator for TypeParams<'a> {
185 type Item = &'a TypeParam;
186
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
200pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
201
202impl<'a> Iterator for TypeParamsMut<'a> {
203 type Item = &'a mut TypeParam;
204
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
218pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
219
220impl<'a> Iterator for Lifetimes<'a> {
221 type Item = &'a LifetimeDef;
222
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
236pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
237
238impl<'a> Iterator for LifetimesMut<'a> {
239 type Item = &'a mut LifetimeDef;
240
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
254pub struct ConstParams<'a>(Iter<'a, GenericParam>);
255
256impl<'a> Iterator for ConstParams<'a> {
257 type Item = &'a ConstParam;
258
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
272pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
273
274impl<'a> Iterator for ConstParamsMut<'a> {
275 type Item = &'a mut ConstParam;
276
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)]
299pub 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)]
310pub 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)]
321pub struct Turbofish<'a>(&'a Generics);
322
323#[cfg(feature = "printing")]
324impl 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 )]
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")]
360macro_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")]
404generics_wrapper_impls!(ImplGenerics);
405#[cfg(feature = "printing")]
406generics_wrapper_impls!(TypeGenerics);
407#[cfg(feature = "printing")]
408generics_wrapper_impls!(Turbofish);
409
410#[cfg(feature = "printing")]
411impl<'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.*
416 pub fn as_turbofish(&self) -> Turbofish {
417 Turbofish(self.0)
418 }
419}
420
421ast_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
435impl Default for BoundLifetimes {
436 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
446impl LifetimeDef {
447 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
457impl From<Ident> for TypeParam {
458 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
470ast_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
482ast_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
498ast_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
511ast_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
524ast_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
548ast_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
565ast_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
578ast_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")]
592pub 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 {
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 {
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 {
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 {
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> {
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 {
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 {
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 impl TypeParamBound {
832 pub(crate) fn parse_multiple(
833 input: ParseStream,
834 allow_plus: bool,
835 ) -> Result<Punctuated<Self, Token![+]>> {
836 let mut bounds = Punctuated::new();
837 loop {
838 bounds.push_value(input.parse()?);
839 if !(allow_plus && input.peek(Token![+])) {
840 break;
841 }
842 bounds.push_punct(input.parse()?);
843 if !(input.peek(Ident::peek_any)
844 || input.peek(Token![::])
845 || input.peek(Token![?])
846 || input.peek(Lifetime)
847 || input.peek(token::Paren))
848 {
849 break;
850 }
851 }
852 Ok(bounds)
853 }
854 }
855
856 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
857 impl Parse for TraitBound {
858 fn parse(input: ParseStream) -> Result<Self> {
859 #[cfg(feature = "full")]
860 let tilde_const = if input.peek(Token![~]) && input.peek2(Token![const]) {
861 let tilde_token = input.parse::<Token![~]>()?;
862 let const_token = input.parse::<Token![const]>()?;
863 Some((tilde_token, const_token))
864 } else {
865 None
866 };
867
868 let modifier: TraitBoundModifier = input.parse()?;
869 let lifetimes: Option<BoundLifetimes> = input.parse()?;
870
871 let mut path: Path = input.parse()?;
872 if path.segments.last().unwrap().arguments.is_empty()
873 && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren))
874 {
875 input.parse::<Option<Token![::]>>()?;
876 let args: ParenthesizedGenericArguments = input.parse()?;
877 let parenthesized = PathArguments::Parenthesized(args);
878 path.segments.last_mut().unwrap().arguments = parenthesized;
879 }
880
881 #[cfg(feature = "full")]
882 {
883 if let Some((tilde_token, const_token)) = tilde_const {
884 path.segments.insert(
885 0,
886 PathSegment {
887 ident: Ident::new("const", const_token.span),
888 arguments: PathArguments::None,
889 },
890 );
891 let (_const, punct) = path.segments.pairs_mut().next().unwrap().into_tuple();
892 *punct.unwrap() = Token![::](tilde_token.span);
893 }
894 }
895
896 Ok(TraitBound {
897 paren_token: None,
898 modifier,
899 lifetimes,
900 path,
901 })
902 }
903 }
904
905 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
906 impl Parse for TraitBoundModifier {
907 fn parse(input: ParseStream) -> Result<Self> {
908 if input.peek(Token![?]) {
909 input.parse().map(TraitBoundModifier::Maybe)
910 } else {
911 Ok(TraitBoundModifier::None)
912 }
913 }
914 }
915
916 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
917 impl Parse for ConstParam {
918 fn parse(input: ParseStream) -> Result<Self> {
919 let mut default = None;
920 Ok(ConstParam {
921 attrs: input.call(Attribute::parse_outer)?,
922 const_token: input.parse()?,
923 ident: input.parse()?,
924 colon_token: input.parse()?,
925 ty: input.parse()?,
926 eq_token: {
927 if input.peek(Token![=]) {
928 let eq_token = input.parse()?;
929 default = Some(path::parsing::const_argument(input)?);
930 Some(eq_token)
931 } else {
932 None
933 }
934 },
935 default,
936 })
937 }
938 }
939
940 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
941 impl Parse for WhereClause {
942 fn parse(input: ParseStream) -> Result<Self> {
943 Ok(WhereClause {
944 where_token: input.parse()?,
945 predicates: {
946 let mut predicates = Punctuated::new();
947 loop {
948 if input.is_empty()
949 || input.peek(token::Brace)
950 || input.peek(Token![,])
951 || input.peek(Token![;])
952 || input.peek(Token![:]) && !input.peek(Token![::])
953 || input.peek(Token![=])
954 {
955 break;
956 }
957 let value = input.parse()?;
958 predicates.push_value(value);
959 if !input.peek(Token![,]) {
960 break;
961 }
962 let punct = input.parse()?;
963 predicates.push_punct(punct);
964 }
965 predicates
966 },
967 })
968 }
969 }
970
971 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
972 impl Parse for Option<WhereClause> {
973 fn parse(input: ParseStream) -> Result<Self> {
974 if input.peek(Token![where]) {
975 input.parse().map(Some)
976 } else {
977 Ok(None)
978 }
979 }
980 }
981
982 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
983 impl Parse for WherePredicate {
984 fn parse(input: ParseStream) -> Result<Self> {
985 if input.peek(Lifetime) && input.peek2(Token![:]) {
986 Ok(WherePredicate::Lifetime(PredicateLifetime {
987 lifetime: input.parse()?,
988 colon_token: input.parse()?,
989 bounds: {
990 let mut bounds = Punctuated::new();
991 loop {
992 if input.is_empty()
993 || input.peek(token::Brace)
994 || input.peek(Token![,])
995 || input.peek(Token![;])
996 || input.peek(Token![:])
997 || input.peek(Token![=])
998 {
999 break;
1000 }
1001 let value = input.parse()?;
1002 bounds.push_value(value);
1003 if !input.peek(Token![+]) {
1004 break;
1005 }
1006 let punct = input.parse()?;
1007 bounds.push_punct(punct);
1008 }
1009 bounds
1010 },
1011 }))
1012 } else {
1013 Ok(WherePredicate::Type(PredicateType {
1014 lifetimes: input.parse()?,
1015 bounded_ty: input.parse()?,
1016 colon_token: input.parse()?,
1017 bounds: {
1018 let mut bounds = Punctuated::new();
1019 loop {
1020 if input.is_empty()
1021 || input.peek(token::Brace)
1022 || input.peek(Token![,])
1023 || input.peek(Token![;])
1024 || input.peek(Token![:]) && !input.peek(Token![::])
1025 || input.peek(Token![=])
1026 {
1027 break;
1028 }
1029 let value = input.parse()?;
1030 bounds.push_value(value);
1031 if !input.peek(Token![+]) {
1032 break;
1033 }
1034 let punct = input.parse()?;
1035 bounds.push_punct(punct);
1036 }
1037 bounds
1038 },
1039 }))
1040 }
1041 }
1042 }
1043}
1044
1045#[cfg(feature = "printing")]
1046mod printing {
1047 use super::*;
1048 use crate::attr::FilterAttrs;
1049 use crate::print::TokensOrDefault;
1050 #[cfg(feature = "full")]
1051 use crate::punctuated::Pair;
1052 use proc_macro2::TokenStream;
1053 #[cfg(feature = "full")]
1054 use proc_macro2::TokenTree;
1055 use quote::{ToTokens, TokenStreamExt};
1056
1057 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1058 impl ToTokens for Generics {
1059 fn to_tokens(&self, tokens: &mut TokenStream) {
1060 if self.params.is_empty() {
1061 return;
1062 }
1063
1064 TokensOrDefault(&self.lt_token).to_tokens(tokens);
1065
1066 // Print lifetimes before types and consts, regardless of their
1067 // order in self.params.
1068 //
1069 // TODO: ordering rules for const parameters vs type parameters have
1070 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
1071 let mut trailing_or_empty = true;
1072 for param in self.params.pairs() {
1073 if let GenericParam::Lifetime(_) = **param.value() {
1074 param.to_tokens(tokens);
1075 trailing_or_empty = param.punct().is_some();
1076 }
1077 }
1078 for param in self.params.pairs() {
1079 match **param.value() {
1080 GenericParam::Type(_) | GenericParam::Const(_) => {
1081 if !trailing_or_empty {
1082 <Token![,]>::default().to_tokens(tokens);
1083 trailing_or_empty = true;
1084 }
1085 param.to_tokens(tokens);
1086 }
1087 GenericParam::Lifetime(_) => {}
1088 }
1089 }
1090
1091 TokensOrDefault(&self.gt_token).to_tokens(tokens);
1092 }
1093 }
1094
1095 impl<'a> ToTokens for ImplGenerics<'a> {
1096 fn to_tokens(&self, tokens: &mut TokenStream) {
1097 if self.0.params.is_empty() {
1098 return;
1099 }
1100
1101 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1102
1103 // Print lifetimes before types and consts, regardless of their
1104 // order in self.params.
1105 //
1106 // TODO: ordering rules for const parameters vs type parameters have
1107 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
1108 let mut trailing_or_empty = true;
1109 for param in self.0.params.pairs() {
1110 if let GenericParam::Lifetime(_) = **param.value() {
1111 param.to_tokens(tokens);
1112 trailing_or_empty = param.punct().is_some();
1113 }
1114 }
1115 for param in self.0.params.pairs() {
1116 if let GenericParam::Lifetime(_) = **param.value() {
1117 continue;
1118 }
1119 if !trailing_or_empty {
1120 <Token![,]>::default().to_tokens(tokens);
1121 trailing_or_empty = true;
1122 }
1123 match *param.value() {
1124 GenericParam::Lifetime(_) => unreachable!(),
1125 GenericParam::Type(param) => {
1126 // Leave off the type parameter defaults
1127 tokens.append_all(param.attrs.outer());
1128 param.ident.to_tokens(tokens);
1129 if !param.bounds.is_empty() {
1130 TokensOrDefault(¶m.colon_token).to_tokens(tokens);
1131 param.bounds.to_tokens(tokens);
1132 }
1133 }
1134 GenericParam::Const(param) => {
1135 // Leave off the const parameter defaults
1136 tokens.append_all(param.attrs.outer());
1137 param.const_token.to_tokens(tokens);
1138 param.ident.to_tokens(tokens);
1139 param.colon_token.to_tokens(tokens);
1140 param.ty.to_tokens(tokens);
1141 }
1142 }
1143 param.punct().to_tokens(tokens);
1144 }
1145
1146 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1147 }
1148 }
1149
1150 impl<'a> ToTokens for TypeGenerics<'a> {
1151 fn to_tokens(&self, tokens: &mut TokenStream) {
1152 if self.0.params.is_empty() {
1153 return;
1154 }
1155
1156 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1157
1158 // Print lifetimes before types and consts, regardless of their
1159 // order in self.params.
1160 //
1161 // TODO: ordering rules for const parameters vs type parameters have
1162 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
1163 let mut trailing_or_empty = true;
1164 for param in self.0.params.pairs() {
1165 if let GenericParam::Lifetime(def) = *param.value() {
1166 // Leave off the lifetime bounds and attributes
1167 def.lifetime.to_tokens(tokens);
1168 param.punct().to_tokens(tokens);
1169 trailing_or_empty = param.punct().is_some();
1170 }
1171 }
1172 for param in self.0.params.pairs() {
1173 if let GenericParam::Lifetime(_) = **param.value() {
1174 continue;
1175 }
1176 if !trailing_or_empty {
1177 <Token![,]>::default().to_tokens(tokens);
1178 trailing_or_empty = true;
1179 }
1180 match *param.value() {
1181 GenericParam::Lifetime(_) => unreachable!(),
1182 GenericParam::Type(param) => {
1183 // Leave off the type parameter defaults
1184 param.ident.to_tokens(tokens);
1185 }
1186 GenericParam::Const(param) => {
1187 // Leave off the const parameter defaults
1188 param.ident.to_tokens(tokens);
1189 }
1190 }
1191 param.punct().to_tokens(tokens);
1192 }
1193
1194 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1195 }
1196 }
1197
1198 impl<'a> ToTokens for Turbofish<'a> {
1199 fn to_tokens(&self, tokens: &mut TokenStream) {
1200 if !self.0.params.is_empty() {
1201 <Token![::]>::default().to_tokens(tokens);
1202 TypeGenerics(self.0).to_tokens(tokens);
1203 }
1204 }
1205 }
1206
1207 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1208 impl ToTokens for BoundLifetimes {
1209 fn to_tokens(&self, tokens: &mut TokenStream) {
1210 self.for_token.to_tokens(tokens);
1211 self.lt_token.to_tokens(tokens);
1212 self.lifetimes.to_tokens(tokens);
1213 self.gt_token.to_tokens(tokens);
1214 }
1215 }
1216
1217 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1218 impl ToTokens for LifetimeDef {
1219 fn to_tokens(&self, tokens: &mut TokenStream) {
1220 tokens.append_all(self.attrs.outer());
1221 self.lifetime.to_tokens(tokens);
1222 if !self.bounds.is_empty() {
1223 TokensOrDefault(&self.colon_token).to_tokens(tokens);
1224 self.bounds.to_tokens(tokens);
1225 }
1226 }
1227 }
1228
1229 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1230 impl ToTokens for TypeParam {
1231 fn to_tokens(&self, tokens: &mut TokenStream) {
1232 tokens.append_all(self.attrs.outer());
1233 self.ident.to_tokens(tokens);
1234 if !self.bounds.is_empty() {
1235 TokensOrDefault(&self.colon_token).to_tokens(tokens);
1236 self.bounds.to_tokens(tokens);
1237 }
1238 if let Some(default) = &self.default {
1239 #[cfg(feature = "full")]
1240 {
1241 if self.eq_token.is_none() {
1242 if let Type::Verbatim(default) = default {
1243 let mut iter = default.clone().into_iter().peekable();
1244 while let Some(token) = iter.next() {
1245 if let TokenTree::Punct(q) = token {
1246 if q.as_char() == '~' {
1247 if let Some(TokenTree::Ident(c)) = iter.peek() {
1248 if c == "const" {
1249 if self.bounds.is_empty() {
1250 TokensOrDefault(&self.colon_token)
1251 .to_tokens(tokens);
1252 }
1253 return default.to_tokens(tokens);
1254 }
1255 }
1256 }
1257 }
1258 }
1259 }
1260 }
1261 }
1262 TokensOrDefault(&self.eq_token).to_tokens(tokens);
1263 default.to_tokens(tokens);
1264 }
1265 }
1266 }
1267
1268 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1269 impl ToTokens for TraitBound {
1270 fn to_tokens(&self, tokens: &mut TokenStream) {
1271 let to_tokens = |tokens: &mut TokenStream| {
1272 #[cfg(feature = "full")]
1273 let skip = match self.path.segments.pairs().next() {
1274 Some(Pair::Punctuated(t, p)) if t.ident == "const" => {
1275 Token![~](p.spans[0]).to_tokens(tokens);
1276 t.to_tokens(tokens);
1277 1
1278 }
1279 _ => 0,
1280 };
1281 self.modifier.to_tokens(tokens);
1282 self.lifetimes.to_tokens(tokens);
1283 #[cfg(feature = "full")]
1284 {
1285 self.path.leading_colon.to_tokens(tokens);
1286 tokens.append_all(self.path.segments.pairs().skip(skip));
1287 }
1288 #[cfg(not(feature = "full"))]
1289 {
1290 self.path.to_tokens(tokens);
1291 }
1292 };
1293 match &self.paren_token {
1294 Some(paren) => paren.surround(tokens, to_tokens),
1295 None => to_tokens(tokens),
1296 }
1297 }
1298 }
1299
1300 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1301 impl ToTokens for TraitBoundModifier {
1302 fn to_tokens(&self, tokens: &mut TokenStream) {
1303 match self {
1304 TraitBoundModifier::None => {}
1305 TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
1306 }
1307 }
1308 }
1309
1310 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1311 impl ToTokens for ConstParam {
1312 fn to_tokens(&self, tokens: &mut TokenStream) {
1313 tokens.append_all(self.attrs.outer());
1314 self.const_token.to_tokens(tokens);
1315 self.ident.to_tokens(tokens);
1316 self.colon_token.to_tokens(tokens);
1317 self.ty.to_tokens(tokens);
1318 if let Some(default) = &self.default {
1319 TokensOrDefault(&self.eq_token).to_tokens(tokens);
1320 default.to_tokens(tokens);
1321 }
1322 }
1323 }
1324
1325 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1326 impl ToTokens for WhereClause {
1327 fn to_tokens(&self, tokens: &mut TokenStream) {
1328 if !self.predicates.is_empty() {
1329 self.where_token.to_tokens(tokens);
1330 self.predicates.to_tokens(tokens);
1331 }
1332 }
1333 }
1334
1335 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1336 impl ToTokens for PredicateType {
1337 fn to_tokens(&self, tokens: &mut TokenStream) {
1338 self.lifetimes.to_tokens(tokens);
1339 self.bounded_ty.to_tokens(tokens);
1340 self.colon_token.to_tokens(tokens);
1341 self.bounds.to_tokens(tokens);
1342 }
1343 }
1344
1345 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1346 impl ToTokens for PredicateLifetime {
1347 fn to_tokens(&self, tokens: &mut TokenStream) {
1348 self.lifetime.to_tokens(tokens);
1349 self.colon_token.to_tokens(tokens);
1350 self.bounds.to_tokens(tokens);
1351 }
1352 }
1353
1354 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1355 impl ToTokens for PredicateEq {
1356 fn to_tokens(&self, tokens: &mut TokenStream) {
1357 self.lhs_ty.to_tokens(tokens);
1358 self.eq_token.to_tokens(tokens);
1359 self.rhs_ty.to_tokens(tokens);
1360 }
1361 }
1362}
1363