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