1use super::*;
10use punctuated::{Iter, IterMut, Punctuated};
11
12ast_struct! {
13 #[derive(Default)]
19 pub struct Generics {
20 pub lt_token: Option<Token![<]>,
21 pub params: Punctuated<GenericParam, Token![,]>,
22 pub gt_token: Option<Token![>]>,
23 pub where_clause: Option<WhereClause>,
24 }
25}
26
27ast_enum_of_structs! {
28 pub enum GenericParam {
40 pub Type(TypeParam {
45 pub attrs: Vec<Attribute>,
46 pub ident: Ident,
47 pub colon_token: Option<Token![:]>,
48 pub bounds: Punctuated<TypeParamBound, Token![+]>,
49 pub eq_token: Option<Token![=]>,
50 pub default: Option<Type>,
51 }),
52
53 pub Lifetime(LifetimeDef {
58 pub attrs: Vec<Attribute>,
59 pub lifetime: Lifetime,
60 pub colon_token: Option<Token![:]>,
61 pub bounds: Punctuated<Lifetime, Token![+]>,
62 }),
63
64 pub Const(ConstParam {
69 pub attrs: Vec<Attribute>,
70 pub const_token: Token![const],
71 pub ident: Ident,
72 pub colon_token: Token![:],
73 pub ty: Type,
74 pub eq_token: Option<Token![=]>,
75 pub default: Option<Expr>,
76 }),
77 }
78}
79
80impl Generics {
81 pub fn type_params(&self) -> TypeParams {
89 TypeParams(self.params.iter())
90 }
91
92 pub fn type_params_mut(&mut self) -> TypeParamsMut {
100 TypeParamsMut(self.params.iter_mut())
101 }
102
103 pub fn lifetimes(&self) -> Lifetimes {
111 Lifetimes(self.params.iter())
112 }
113
114 pub fn lifetimes_mut(&mut self) -> LifetimesMut {
122 LifetimesMut(self.params.iter_mut())
123 }
124
125 pub fn const_params(&self) -> ConstParams {
133 ConstParams(self.params.iter())
134 }
135
136 pub fn const_params_mut(&mut self) -> ConstParamsMut {
144 ConstParamsMut(self.params.iter_mut())
145 }
146}
147
148pub struct TypeParams<'a>(Iter<'a, GenericParam, Token![,]>);
149
150impl<'a> Iterator for TypeParams<'a> {
151 type Item = &'a TypeParam;
152
153 fn next(&mut self) -> Option<Self::Item> {
154 let next = match self.0.next() {
156 Some(item) => item,
157 None => return None,
158 };
159 if let GenericParam::Type(ref type_param) = *next {
160 Some(type_param)
161 } else {
162 self.next()
163 }
164 }
165}
166
167pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam, Token![,]>);
168
169impl<'a> Iterator for TypeParamsMut<'a> {
170 type Item = &'a mut TypeParam;
171
172 fn next(&mut self) -> Option<Self::Item> {
173 let next = match self.0.next() {
175 Some(item) => item,
176 None => return None,
177 };
178 if let GenericParam::Type(ref mut type_param) = *next {
179 Some(type_param)
180 } else {
181 self.next()
182 }
183 }
184}
185
186pub struct Lifetimes<'a>(Iter<'a, GenericParam, Token![,]>);
187
188impl<'a> Iterator for Lifetimes<'a> {
189 type Item = &'a LifetimeDef;
190
191 fn next(&mut self) -> Option<Self::Item> {
192 let next = match self.0.next() {
194 Some(item) => item,
195 None => return None,
196 };
197 if let GenericParam::Lifetime(ref lifetime) = *next {
198 Some(lifetime)
199 } else {
200 self.next()
201 }
202 }
203}
204
205pub struct LifetimesMut<'a>(IterMut<'a, GenericParam, Token![,]>);
206
207impl<'a> Iterator for LifetimesMut<'a> {
208 type Item = &'a mut LifetimeDef;
209
210 fn next(&mut self) -> Option<Self::Item> {
211 let next = match self.0.next() {
213 Some(item) => item,
214 None => return None,
215 };
216 if let GenericParam::Lifetime(ref mut lifetime) = *next {
217 Some(lifetime)
218 } else {
219 self.next()
220 }
221 }
222}
223
224pub struct ConstParams<'a>(Iter<'a, GenericParam, Token![,]>);
225
226impl<'a> Iterator for ConstParams<'a> {
227 type Item = &'a ConstParam;
228
229 fn next(&mut self) -> Option<Self::Item> {
230 let next = match self.0.next() {
232 Some(item) => item,
233 None => return None,
234 };
235 if let GenericParam::Const(ref const_param) = *next {
236 Some(const_param)
237 } else {
238 self.next()
239 }
240 }
241}
242
243pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam, Token![,]>);
244
245impl<'a> Iterator for ConstParamsMut<'a> {
246 type Item = &'a mut ConstParam;
247
248 fn next(&mut self) -> Option<Self::Item> {
249 let next = match self.0.next() {
251 Some(item) => item,
252 None => return None,
253 };
254 if let GenericParam::Const(ref mut const_param) = *next {
255 Some(const_param)
256 } else {
257 self.next()
258 }
259 }
260}
261
262#[cfg(feature = "printing")]
267#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
268#[cfg_attr(feature = "clone-impls", derive(Clone))]
269pub struct ImplGenerics<'a>(&'a Generics);
270
271#[cfg(feature = "printing")]
276#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
277#[cfg_attr(feature = "clone-impls", derive(Clone))]
278pub struct TypeGenerics<'a>(&'a Generics);
279
280#[cfg(feature = "printing")]
285#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
286#[cfg_attr(feature = "clone-impls", derive(Clone))]
287pub struct Turbofish<'a>(&'a Generics);
288
289#[cfg(feature = "printing")]
290impl Generics {
291 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
314 (
315 ImplGenerics(self),
316 TypeGenerics(self),
317 self.where_clause.as_ref(),
318 )
319 }
320}
321
322#[cfg(feature = "printing")]
323impl<'a> TypeGenerics<'a> {
324 pub fn as_turbofish(&self) -> Turbofish {
329 Turbofish(self.0)
330 }
331}
332
333ast_struct! {
334 #[derive(Default)]
339 pub struct BoundLifetimes {
340 pub for_token: Token![for],
341 pub lt_token: Token![<],
342 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
343 pub gt_token: Token![>],
344 }
345}
346
347impl LifetimeDef {
348 pub fn new(lifetime: Lifetime) -> Self {
349 LifetimeDef {
350 attrs: Vec::new(),
351 lifetime: lifetime,
352 colon_token: None,
353 bounds: Punctuated::new(),
354 }
355 }
356}
357
358impl From<Ident> for TypeParam {
359 fn from(ident: Ident) -> Self {
360 TypeParam {
361 attrs: vec![],
362 ident: ident,
363 colon_token: None,
364 bounds: Punctuated::new(),
365 eq_token: None,
366 default: None,
367 }
368 }
369}
370
371ast_enum_of_structs! {
372 pub enum TypeParamBound {
377 pub Trait(TraitBound),
378 pub Lifetime(Lifetime),
379 }
380}
381
382ast_struct! {
383 pub struct TraitBound {
388 pub modifier: TraitBoundModifier,
389 pub lifetimes: Option<BoundLifetimes>,
391 pub path: Path,
393 }
394}
395
396ast_enum! {
397 #[cfg_attr(feature = "clone-impls", derive(Copy))]
403 pub enum TraitBoundModifier {
404 None,
405 Maybe(Token![?]),
406 }
407}
408
409ast_struct! {
410 pub struct WhereClause {
416 pub where_token: Token![where],
417 pub predicates: Punctuated<WherePredicate, Token![,]>,
418 }
419}
420
421ast_enum_of_structs! {
422 pub enum WherePredicate {
433 pub Type(PredicateType {
438 pub lifetimes: Option<BoundLifetimes>,
440 pub bounded_ty: Type,
442 pub colon_token: Token![:],
443 pub bounds: Punctuated<TypeParamBound, Token![+]>,
445 }),
446
447 pub Lifetime(PredicateLifetime {
452 pub lifetime: Lifetime,
453 pub colon_token: Option<Token![:]>,
454 pub bounds: Punctuated<Lifetime, Token![+]>,
455 }),
456
457 pub Eq(PredicateEq {
462 pub lhs_ty: Type,
463 pub eq_token: Token![=],
464 pub rhs_ty: Type,
465 }),
466 }
467}
468
469#[cfg(feature = "parsing")]
470pub mod parsing {
471 use super::*;
472
473 use synom::Synom;
474 use punctuated::Pair;
475
476 impl Synom for Generics {
477 named!(parse -> Self, map!(
478 alt!(
479 do_parse!(
480 lt: punct!(<) >>
481 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
482 ty_params: cond!(
483 lifetimes.empty_or_trailing(),
484 Punctuated::<TypeParam, Token![,]>::parse_terminated
485 ) >>
486 gt: punct!(>) >>
487 (lifetimes, ty_params, Some(lt), Some(gt))
488 )
489 |
490 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
491 ),
492 |(lifetimes, ty_params, lt, gt)| Generics {
493 lt_token: lt,
494 params: lifetimes.into_pairs()
495 .map(Pair::into_tuple)
496 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
497 .chain(ty_params.unwrap_or_default()
498 .into_pairs()
499 .map(Pair::into_tuple)
500 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
501 .collect(),
502 gt_token: gt,
503 where_clause: None,
504 }
505 ));
506
507 fn description() -> Option<&'static str> {
508 Some("generic parameters in declaration")
509 }
510 }
511
512 impl Synom for GenericParam {
513 named!(parse -> Self, alt!(
514 syn!(TypeParam) => { GenericParam::Type }
515 |
516 syn!(LifetimeDef) => { GenericParam::Lifetime }
517 |
518 syn!(ConstParam) => { GenericParam::Const }
519 ));
520
521 fn description() -> Option<&'static str> {
522 Some("generic parameter")
523 }
524 }
525
526 impl Synom for LifetimeDef {
527 named!(parse -> Self, do_parse!(
528 attrs: many0!(Attribute::parse_outer) >>
529 life: syn!(Lifetime) >>
530 colon: option!(punct!(:)) >>
531 bounds: cond!(
532 colon.is_some(),
533 Punctuated::parse_separated_nonempty
534 ) >>
535 (LifetimeDef {
536 attrs: attrs,
537 lifetime: life,
538 bounds: bounds.unwrap_or_default(),
539 colon_token: colon,
540 })
541 ));
542
543 fn description() -> Option<&'static str> {
544 Some("lifetime definition")
545 }
546 }
547
548 impl Synom for BoundLifetimes {
549 named!(parse -> Self, do_parse!(
550 for_: keyword!(for) >>
551 lt: punct!(<) >>
552 lifetimes: call!(Punctuated::parse_terminated) >>
553 gt: punct!(>) >>
554 (BoundLifetimes {
555 for_token: for_,
556 lt_token: lt,
557 gt_token: gt,
558 lifetimes: lifetimes,
559 })
560 ));
561
562 fn description() -> Option<&'static str> {
563 Some("bound lifetimes")
564 }
565 }
566
567 impl Synom for TypeParam {
568 named!(parse -> Self, do_parse!(
569 attrs: many0!(Attribute::parse_outer) >>
570 id: syn!(Ident) >>
571 colon: option!(punct!(:)) >>
572 bounds: cond!(
573 colon.is_some(),
574 Punctuated::parse_separated_nonempty
575 ) >>
576 default: option!(do_parse!(
577 eq: punct!(=) >>
578 ty: syn!(Type) >>
579 (eq, ty)
580 )) >>
581 (TypeParam {
582 attrs: attrs,
583 ident: id,
584 bounds: bounds.unwrap_or_default(),
585 colon_token: colon,
586 eq_token: default.as_ref().map(|d| Token.0)),
587 default: default.map(|d| d.1),
588 })
589 ));
590
591 fn description() -> Option<&'static str> {
592 Some("type parameter")
593 }
594 }
595
596 impl Synom for TypeParamBound {
597 named!(parse -> Self, alt!(
598 syn!(Lifetime) => { TypeParamBound::Lifetime }
599 |
600 syn!(TraitBound) => { TypeParamBound::Trait }
601 |
602 parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
603 ));
604
605 fn description() -> Option<&'static str> {
606 Some("type parameter bound")
607 }
608 }
609
610 impl Synom for TraitBound {
611 named!(parse -> Self, do_parse!(
612 modifier: syn!(TraitBoundModifier) >>
613 lifetimes: option!(syn!(BoundLifetimes)) >>
614 mut path: syn!(Path) >>
615 parenthesized: option!(cond_reduce!(
616 path.segments.last().unwrap().value().arguments.is_empty(),
617 syn!(ParenthesizedGenericArguments)
618 )) >>
619 ({
620 if let Some(parenthesized) = parenthesized {
621 let parenthesized = PathArguments::Parenthesized(parenthesized);
622 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
623 }
624 TraitBound {
625 modifier: modifier,
626 lifetimes: lifetimes,
627 path: path,
628 }
629 })
630 ));
631
632 fn description() -> Option<&'static str> {
633 Some("trait bound")
634 }
635 }
636
637 impl Synom for TraitBoundModifier {
638 named!(parse -> Self, alt!(
639 punct!(?) => { TraitBoundModifier::Maybe }
640 |
641 epsilon!() => { |_| TraitBoundModifier::None }
642 ));
643
644 fn description() -> Option<&'static str> {
645 Some("trait bound modifier")
646 }
647 }
648
649 impl Synom for ConstParam {
650 named!(parse -> Self, do_parse!(
651 attrs: many0!(Attribute::parse_outer) >>
652 const_: keyword!(const) >>
653 ident: syn!(Ident) >>
654 colon: punct!(:) >>
655 ty: syn!(Type) >>
656 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
657 ({
658 let (eq_token, default) = match eq_def {
659 Some((eq_token, default)) => (Some(eq_token), Some(default)),
660 None => (None, None),
661 };
662 ConstParam {
663 attrs: attrs,
664 const_token: const_,
665 ident: ident,
666 colon_token: colon,
667 ty: ty,
668 eq_token: eq_token,
669 default: default,
670 }
671 })
672 ));
673
674 fn description() -> Option<&'static str> {
675 Some("generic `const` parameter")
676 }
677 }
678
679 impl Synom for WhereClause {
680 named!(parse -> Self, do_parse!(
681 where_: keyword!(where) >>
682 predicates: call!(Punctuated::parse_terminated) >>
683 (WhereClause {
684 predicates: predicates,
685 where_token: where_,
686 })
687 ));
688
689 fn description() -> Option<&'static str> {
690 Some("where clause")
691 }
692 }
693
694 impl Synom for WherePredicate {
695 named!(parse -> Self, alt!(
696 do_parse!(
697 ident: syn!(Lifetime) >>
698 colon: option!(punct!(:)) >>
699 bounds: cond!(
700 colon.is_some(),
701 Punctuated::parse_separated
702 ) >>
703 (WherePredicate::Lifetime(PredicateLifetime {
704 lifetime: ident,
705 bounds: bounds.unwrap_or_default(),
706 colon_token: colon,
707 }))
708 )
709 |
710 do_parse!(
711 lifetimes: option!(syn!(BoundLifetimes)) >>
712 bounded_ty: syn!(Type) >>
713 colon: punct!(:) >>
714 bounds: call!(Punctuated::parse_separated_nonempty) >>
715 (WherePredicate::Type(PredicateType {
716 lifetimes: lifetimes,
717 bounded_ty: bounded_ty,
718 bounds: bounds,
719 colon_token: colon,
720 }))
721 )
722 ));
723
724 fn description() -> Option<&'static str> {
725 Some("predicate in where clause")
726 }
727 }
728}
729
730#[cfg(feature = "printing")]
731mod printing {
732 use super::*;
733 use attr::FilterAttrs;
734 use quote::{ToTokens, Tokens};
735
736 impl ToTokens for Generics {
737 fn to_tokens(&self, tokens: &mut Tokens) {
738 if self.params.is_empty() {
739 return;
740 }
741
742 TokensOrDefault(&self.lt_token).to_tokens(tokens);
743
744 let mut trailing_or_empty = true;
750 for param in self.params.pairs() {
751 if let GenericParam::Lifetime(_) = **param.value() {
752 param.to_tokens(tokens);
753 trailing_or_empty = param.punct().is_some();
754 }
755 }
756 for param in self.params.pairs() {
757 match **param.value() {
758 GenericParam::Type(_) | GenericParam::Const(_) => {
759 if !trailing_or_empty {
760 <Token![,]>::default().to_tokens(tokens);
761 trailing_or_empty = true;
762 }
763 param.to_tokens(tokens);
764 }
765 GenericParam::Lifetime(_) => {}
766 }
767 }
768
769 TokensOrDefault(&self.gt_token).to_tokens(tokens);
770 }
771 }
772
773 impl<'a> ToTokens for ImplGenerics<'a> {
774 fn to_tokens(&self, tokens: &mut Tokens) {
775 if self.0.params.is_empty() {
776 return;
777 }
778
779 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
780
781 let mut trailing_or_empty = true;
787 for param in self.0.params.pairs() {
788 if let GenericParam::Lifetime(_) = **param.value() {
789 param.to_tokens(tokens);
790 trailing_or_empty = param.punct().is_some();
791 }
792 }
793 for param in self.0.params.pairs() {
794 if let GenericParam::Lifetime(_) = **param.value() {
795 continue;
796 }
797 if !trailing_or_empty {
798 <Token![,]>::default().to_tokens(tokens);
799 trailing_or_empty = true;
800 }
801 match **param.value() {
802 GenericParam::Lifetime(_) => unreachable!(),
803 GenericParam::Type(ref param) => {
804 tokens.append_all(param.attrs.outer());
806 param.ident.to_tokens(tokens);
807 if !param.bounds.is_empty() {
808 TokensOrDefault(¶m.colon_token).to_tokens(tokens);
809 param.bounds.to_tokens(tokens);
810 }
811 }
812 GenericParam::Const(ref param) => {
813 tokens.append_all(param.attrs.outer());
815 param.const_token.to_tokens(tokens);
816 param.ident.to_tokens(tokens);
817 param.colon_token.to_tokens(tokens);
818 param.ty.to_tokens(tokens);
819 }
820 }
821 param.punct().to_tokens(tokens);
822 }
823
824 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
825 }
826 }
827
828 impl<'a> ToTokens for TypeGenerics<'a> {
829 fn to_tokens(&self, tokens: &mut Tokens) {
830 if self.0.params.is_empty() {
831 return;
832 }
833
834 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
835
836 let mut trailing_or_empty = true;
842 for param in self.0.params.pairs() {
843 if let GenericParam::Lifetime(ref def) = **param.value() {
844 def.lifetime.to_tokens(tokens);
846 param.punct().to_tokens(tokens);
847 trailing_or_empty = param.punct().is_some();
848 }
849 }
850 for param in self.0.params.pairs() {
851 if let GenericParam::Lifetime(_) = **param.value() {
852 continue;
853 }
854 if !trailing_or_empty {
855 <Token![,]>::default().to_tokens(tokens);
856 trailing_or_empty = true;
857 }
858 match **param.value() {
859 GenericParam::Lifetime(_) => unreachable!(),
860 GenericParam::Type(ref param) => {
861 param.ident.to_tokens(tokens);
863 }
864 GenericParam::Const(ref param) => {
865 param.ident.to_tokens(tokens);
867 }
868 }
869 param.punct().to_tokens(tokens);
870 }
871
872 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
873 }
874 }
875
876 impl<'a> ToTokens for Turbofish<'a> {
877 fn to_tokens(&self, tokens: &mut Tokens) {
878 if !self.0.params.is_empty() {
879 <Token![::]>::default().to_tokens(tokens);
880 TypeGenerics(self.0).to_tokens(tokens);
881 }
882 }
883 }
884
885 impl ToTokens for BoundLifetimes {
886 fn to_tokens(&self, tokens: &mut Tokens) {
887 self.for_token.to_tokens(tokens);
888 self.lt_token.to_tokens(tokens);
889 self.lifetimes.to_tokens(tokens);
890 self.gt_token.to_tokens(tokens);
891 }
892 }
893
894 impl ToTokens for LifetimeDef {
895 fn to_tokens(&self, tokens: &mut Tokens) {
896 tokens.append_all(self.attrs.outer());
897 self.lifetime.to_tokens(tokens);
898 if !self.bounds.is_empty() {
899 TokensOrDefault(&self.colon_token).to_tokens(tokens);
900 self.bounds.to_tokens(tokens);
901 }
902 }
903 }
904
905 impl ToTokens for TypeParam {
906 fn to_tokens(&self, tokens: &mut Tokens) {
907 tokens.append_all(self.attrs.outer());
908 self.ident.to_tokens(tokens);
909 if !self.bounds.is_empty() {
910 TokensOrDefault(&self.colon_token).to_tokens(tokens);
911 self.bounds.to_tokens(tokens);
912 }
913 if self.default.is_some() {
914 TokensOrDefault(&self.eq_token).to_tokens(tokens);
915 self.default.to_tokens(tokens);
916 }
917 }
918 }
919
920 impl ToTokens for TraitBound {
921 fn to_tokens(&self, tokens: &mut Tokens) {
922 self.modifier.to_tokens(tokens);
923 self.lifetimes.to_tokens(tokens);
924 self.path.to_tokens(tokens);
925 }
926 }
927
928 impl ToTokens for TraitBoundModifier {
929 fn to_tokens(&self, tokens: &mut Tokens) {
930 match *self {
931 TraitBoundModifier::None => {}
932 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
933 }
934 }
935 }
936
937 impl ToTokens for ConstParam {
938 fn to_tokens(&self, tokens: &mut Tokens) {
939 tokens.append_all(self.attrs.outer());
940 self.const_token.to_tokens(tokens);
941 self.ident.to_tokens(tokens);
942 self.colon_token.to_tokens(tokens);
943 self.ty.to_tokens(tokens);
944 if self.default.is_some() {
945 TokensOrDefault(&self.eq_token).to_tokens(tokens);
946 self.default.to_tokens(tokens);
947 }
948 }
949 }
950
951 impl ToTokens for WhereClause {
952 fn to_tokens(&self, tokens: &mut Tokens) {
953 self.where_token.to_tokens(tokens);
954 self.predicates.to_tokens(tokens);
955 }
956 }
957
958 impl ToTokens for PredicateType {
959 fn to_tokens(&self, tokens: &mut Tokens) {
960 self.lifetimes.to_tokens(tokens);
961 self.bounded_ty.to_tokens(tokens);
962 self.colon_token.to_tokens(tokens);
963 self.bounds.to_tokens(tokens);
964 }
965 }
966
967 impl ToTokens for PredicateLifetime {
968 fn to_tokens(&self, tokens: &mut Tokens) {
969 self.lifetime.to_tokens(tokens);
970 if !self.bounds.is_empty() {
971 TokensOrDefault(&self.colon_token).to_tokens(tokens);
972 self.bounds.to_tokens(tokens);
973 }
974 }
975 }
976
977 impl ToTokens for PredicateEq {
978 fn to_tokens(&self, tokens: &mut Tokens) {
979 self.lhs_ty.to_tokens(tokens);
980 self.eq_token.to_tokens(tokens);
981 self.rhs_ty.to_tokens(tokens);
982 }
983 }
984}