blob: 737a80145ede0acee34c1667fe9cdb1835c4a8e5 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayb79ee962016-09-04 09:39:20 -07009use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -050010use punctuated::Punctuated;
David Tolnayb79ee962016-09-04 09:39:20 -070011
Alex Crichton62a0a592017-05-22 13:58:53 -070012ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -080013 /// Lifetimes and type parameters attached to a declaration of a function,
14 /// enum, trait, etc.
David Tolnay461d98e2018-01-07 11:07:19 -080015 ///
16 /// *This type is available if Syn is built with the `"derive"` or `"full"`
17 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070018 #[derive(Default)]
19 pub struct Generics {
David Tolnayf8db7ba2017-11-11 22:52:16 -080020 pub lt_token: Option<Token![<]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050021 pub params: Punctuated<GenericParam, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080022 pub gt_token: Option<Token![>]>,
David Tolnayac997dd2017-12-27 23:18:22 -050023 pub where_clause: Option<WhereClause>,
Alex Crichton62a0a592017-05-22 13:58:53 -070024 }
David Tolnayb79ee962016-09-04 09:39:20 -070025}
26
David Tolnayc2f1aba2017-11-12 20:29:22 -080027ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -080028 /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
29 /// `'a: 'b`, `const LEN: usize`.
David Tolnay614a0142018-01-07 10:25:43 -080030 ///
David Tolnay461d98e2018-01-07 11:07:19 -080031 /// *This type is available if Syn is built with the `"derive"` or `"full"`
32 /// feature.*
33 ///
David Tolnay614a0142018-01-07 10:25:43 -080034 /// # Syntax tree enum
35 ///
36 /// This type is a [syntax tree enum].
37 ///
38 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnayc2f1aba2017-11-12 20:29:22 -080039 pub enum GenericParam {
David Tolnayed906d12018-01-07 01:20:29 -080040 /// A generic type parameter: `T: Into<String>`.
David Tolnay461d98e2018-01-07 11:07:19 -080041 ///
42 /// *This type is available if Syn is built with the `"derive"` or
43 /// `"full"` feature.*
David Tolnayc2f1aba2017-11-12 20:29:22 -080044 pub Type(TypeParam {
45 pub attrs: Vec<Attribute>,
46 pub ident: Ident,
47 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050048 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080049 pub eq_token: Option<Token![=]>,
50 pub default: Option<Type>,
51 }),
David Tolnayed906d12018-01-07 01:20:29 -080052
53 /// A lifetime definition: `'a: 'b + 'c + 'd`.
David Tolnay461d98e2018-01-07 11:07:19 -080054 ///
55 /// *This type is available if Syn is built with the `"derive"` or
56 /// `"full"` feature.*
David Tolnay517f3692018-01-01 20:17:23 -080057 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 }),
David Tolnayed906d12018-01-07 01:20:29 -080063
64 /// A const generic parameter: `const LENGTH: usize`.
David Tolnay461d98e2018-01-07 11:07:19 -080065 ///
66 /// *This type is available if Syn is built with the `"derive"` or
67 /// `"full"` feature.*
Nika Layzellf1fdc0b2017-12-04 19:58:32 -050068 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 }),
David Tolnayc2f1aba2017-11-12 20:29:22 -080077 }
78}
79
David Tolnay461d98e2018-01-07 11:07:19 -080080/// Returned by `Generics::split_for_impl`.
81///
82/// *This type is available if Syn is built with the `"derive"` or `"full"`
83/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -070084#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040085#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
86#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -040087pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070088
David Tolnay461d98e2018-01-07 11:07:19 -080089/// Returned by `Generics::split_for_impl`.
90///
91/// *This type is available if Syn is built with the `"derive"` or `"full"`
92/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -070093#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040094#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
95#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080096pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070097
David Tolnay461d98e2018-01-07 11:07:19 -080098/// Returned by `TypeGenerics::as_turbofish`.
99///
100/// *This type is available if Syn is built with the `"derive"` or `"full"`
101/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800102#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400103#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
104#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400105pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800106
David Tolnaye95cc9f2017-01-25 15:57:09 -0800107#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700108impl Generics {
109 /// Split a type's generics into the pieces required for impl'ing a trait
110 /// for that type.
111 ///
112 /// ```
113 /// # extern crate syn;
114 /// # #[macro_use]
115 /// # extern crate quote;
116 /// # fn main() {
117 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700118 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -0700119 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
120 /// quote! {
121 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
122 /// // ...
123 /// }
124 /// }
125 /// # ;
126 /// # }
127 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800128 ///
129 /// *This method is available if Syn is built with the `"derive"` or
130 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500131 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800132 (
133 ImplGenerics(self),
134 TypeGenerics(self),
135 self.where_clause.as_ref(),
136 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700137 }
138}
139
David Tolnaye95cc9f2017-01-25 15:57:09 -0800140#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800141impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800142 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800143 ///
144 /// *This method is available if Syn is built with the `"derive"` or
145 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800146 pub fn as_turbofish(&self) -> Turbofish {
147 Turbofish(self.0)
148 }
149}
150
Alex Crichton62a0a592017-05-22 13:58:53 -0700151ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800152 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800153 ///
154 /// *This type is available if Syn is built with the `"derive"` or `"full"`
155 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700156 #[derive(Default)]
157 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800158 pub for_token: Token![for],
159 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500160 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800161 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700162 }
163}
164
David Tolnayf9505b52016-10-02 09:18:52 -0700165impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700166 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700167 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700168 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700169 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700170 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500171 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700172 }
173 }
174}
175
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800176impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700177 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800178 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700179 attrs: vec![],
180 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700181 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500182 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700183 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700184 default: None,
185 }
186 }
187}
188
David Tolnay40fb8ce2018-01-02 10:53:46 -0800189ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800190 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800191 ///
192 /// *This type is available if Syn is built with the `"derive"` or `"full"`
193 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800194 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800195 pub Trait(TraitBound),
196 pub Lifetime(Lifetime),
197 }
198}
199
200ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800201 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800202 ///
203 /// *This type is available if Syn is built with the `"derive"` or `"full"`
204 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800205 pub struct TraitBound {
206 pub modifier: TraitBoundModifier,
207 /// The `for<'a>` in `for<'a> Foo<&'a T>`
208 pub lifetimes: Option<BoundLifetimes>,
209 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
210 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700211 }
David Tolnay55337722016-09-11 12:58:56 -0700212}
213
Alex Crichton62a0a592017-05-22 13:58:53 -0700214ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800215 /// A modifier on a trait bound, currently only used for the `?` in
216 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800217 ///
218 /// *This type is available if Syn is built with the `"derive"` or `"full"`
219 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700220 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 pub enum TraitBoundModifier {
222 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800223 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700224 }
David Tolnay55337722016-09-11 12:58:56 -0700225}
226
Alex Crichton62a0a592017-05-22 13:58:53 -0700227ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800228 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
229 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800230 ///
231 /// *This type is available if Syn is built with the `"derive"` or `"full"`
232 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700233 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500234 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500235 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 }
David Tolnayb79ee962016-09-04 09:39:20 -0700237}
238
Alex Crichton62a0a592017-05-22 13:58:53 -0700239ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800240 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800241 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800242 /// *This type is available if Syn is built with the `"derive"` or `"full"`
243 /// feature.*
244 ///
David Tolnay614a0142018-01-07 10:25:43 -0800245 /// # Syntax tree enum
246 ///
247 /// This type is a [syntax tree enum].
248 ///
249 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800251 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800252 ///
253 /// *This type is available if Syn is built with the `"derive"` or
254 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800255 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700256 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800257 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700258 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800259 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800260 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500262 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700263 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700264
David Tolnayed906d12018-01-07 01:20:29 -0800265 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800266 ///
267 /// *This type is available if Syn is built with the `"derive"` or
268 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800269 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700270 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800271 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500272 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700273 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700274
David Tolnayed906d12018-01-07 01:20:29 -0800275 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800276 ///
277 /// *This type is available if Syn is built with the `"derive"` or
278 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800279 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800280 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800281 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800282 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700283 }),
284 }
David Tolnayf8e08832017-01-23 00:04:32 -0800285}
286
David Tolnay86eca752016-09-04 11:26:41 -0700287#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700288pub mod parsing {
289 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700290
David Tolnay63e3dee2017-06-03 20:13:17 -0700291 use synom::Synom;
David Tolnay56080682018-01-06 14:01:52 -0800292 use punctuated::Pair;
Alex Crichton954046c2017-05-30 21:49:42 -0700293
294 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400295 named!(parse -> Self, map!(
296 alt!(
297 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800298 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500299 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400300 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800301 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500302 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400303 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800304 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400305 (lifetimes, ty_params, Some(lt), Some(gt))
306 )
307 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500308 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400309 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700310 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400311 lt_token: lt,
David Tolnay56080682018-01-06 14:01:52 -0800312 params: lifetimes.into_pairs()
313 .map(Pair::into_tuple)
314 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800315 .chain(ty_params.unwrap_or_default()
David Tolnay56080682018-01-06 14:01:52 -0800316 .into_pairs()
317 .map(Pair::into_tuple)
318 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
David Tolnay660fd1f2017-12-31 01:52:57 -0500319 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800320 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500321 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400322 }
Michael Layzell92639a52017-06-01 00:07:44 -0400323 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800324
325 fn description() -> Option<&'static str> {
326 Some("generic parameters in declaration")
327 }
Alex Crichton954046c2017-05-30 21:49:42 -0700328 }
329
David Tolnay36454bb2018-01-07 22:40:02 -0800330 impl Synom for GenericParam {
331 named!(parse -> Self, alt!(
332 syn!(TypeParam) => { GenericParam::Type }
333 |
334 syn!(LifetimeDef) => { GenericParam::Lifetime }
335 |
336 syn!(ConstParam) => { GenericParam::Const }
337 ));
338
339 fn description() -> Option<&'static str> {
340 Some("generic parameter")
341 }
342 }
343
Alex Crichton954046c2017-05-30 21:49:42 -0700344 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400345 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500346 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400347 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800348 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400349 bounds: cond!(
350 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500351 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400352 ) >>
353 (LifetimeDef {
354 attrs: attrs,
355 lifetime: life,
356 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500357 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400358 })
359 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800360
361 fn description() -> Option<&'static str> {
362 Some("lifetime definition")
363 }
Alex Crichton954046c2017-05-30 21:49:42 -0700364 }
365
366 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400367 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800368 for_: keyword!(for) >>
369 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500370 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400372 (BoundLifetimes {
373 for_token: for_,
374 lt_token: lt,
375 gt_token: gt,
376 lifetimes: lifetimes,
377 })
378 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800379
380 fn description() -> Option<&'static str> {
381 Some("bound lifetimes")
382 }
Alex Crichton954046c2017-05-30 21:49:42 -0700383 }
David Tolnay55337722016-09-11 12:58:56 -0700384
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800385 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400386 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500387 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400388 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800389 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400390 bounds: cond!(
391 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500392 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400393 ) >>
394 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800395 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800396 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400397 (eq, ty)
398 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800399 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400400 attrs: attrs,
401 ident: id,
402 bounds: bounds.unwrap_or_default(),
403 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800404 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400405 default: default.map(|d| d.1),
406 })
407 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800408
409 fn description() -> Option<&'static str> {
410 Some("type parameter")
411 }
Alex Crichton954046c2017-05-30 21:49:42 -0700412 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700413
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800414 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400415 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800416 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400417 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800418 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400419 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800420 parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
Michael Layzell92639a52017-06-01 00:07:44 -0400421 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700422
423 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500424 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700425 }
426 }
427
David Tolnay40fb8ce2018-01-02 10:53:46 -0800428 impl Synom for TraitBound {
429 named!(parse -> Self, do_parse!(
430 modifier: syn!(TraitBoundModifier) >>
431 lifetimes: option!(syn!(BoundLifetimes)) >>
432 mut path: syn!(Path) >>
433 parenthesized: option!(cond_reduce!(
David Tolnay56080682018-01-06 14:01:52 -0800434 path.segments.last().unwrap().value().arguments.is_empty(),
David Tolnay40fb8ce2018-01-02 10:53:46 -0800435 syn!(ParenthesizedGenericArguments)
436 )) >>
437 ({
438 if let Some(parenthesized) = parenthesized {
439 let parenthesized = PathArguments::Parenthesized(parenthesized);
David Tolnay56080682018-01-06 14:01:52 -0800440 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800441 }
442 TraitBound {
443 modifier: modifier,
444 lifetimes: lifetimes,
445 path: path,
446 }
447 })
448 ));
449
450 fn description() -> Option<&'static str> {
451 Some("trait bound")
452 }
453 }
454
455 impl Synom for TraitBoundModifier {
456 named!(parse -> Self, alt!(
457 punct!(?) => { TraitBoundModifier::Maybe }
458 |
459 epsilon!() => { |_| TraitBoundModifier::None }
460 ));
461
462 fn description() -> Option<&'static str> {
463 Some("trait bound modifier")
464 }
465 }
466
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500467 impl Synom for ConstParam {
468 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500469 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500470 const_: keyword!(const) >>
471 ident: syn!(Ident) >>
472 colon: punct!(:) >>
473 ty: syn!(Type) >>
474 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800475 ({
476 let (eq_token, default) = match eq_def {
477 Some((eq_token, default)) => (Some(eq_token), Some(default)),
478 None => (None, None),
479 };
480 ConstParam {
481 attrs: attrs,
482 const_token: const_,
483 ident: ident,
484 colon_token: colon,
485 ty: ty,
486 eq_token: eq_token,
487 default: default,
488 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500489 })
490 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800491
492 fn description() -> Option<&'static str> {
493 Some("generic `const` parameter")
494 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500495 }
496
Alex Crichton954046c2017-05-30 21:49:42 -0700497 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500498 named!(parse -> Self, do_parse!(
499 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500500 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500501 (WhereClause {
502 predicates: predicates,
503 where_token: where_,
504 })
Michael Layzell92639a52017-06-01 00:07:44 -0400505 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700506
507 fn description() -> Option<&'static str> {
508 Some("where clause")
509 }
510 }
511
512 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400513 named!(parse -> Self, alt!(
514 do_parse!(
515 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800516 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400517 bounds: cond!(
518 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500519 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400520 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800521 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400522 lifetime: ident,
523 bounds: bounds.unwrap_or_default(),
524 colon_token: colon,
525 }))
526 )
527 |
528 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800529 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800530 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800531 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500532 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800533 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800534 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400535 bounded_ty: bounded_ty,
536 bounds: bounds,
537 colon_token: colon,
538 }))
539 )
540 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800541
542 fn description() -> Option<&'static str> {
543 Some("predicate in where clause")
544 }
Alex Crichton954046c2017-05-30 21:49:42 -0700545 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700546}
David Tolnay87d0b442016-09-04 11:52:12 -0700547
548#[cfg(feature = "printing")]
549mod printing {
550 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700551 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500552 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700553
Michael Layzell3936ceb2017-07-08 00:28:36 -0400554 /// Returns true if the generics object has no lifetimes or ty_params.
555 fn empty_normal_generics(generics: &Generics) -> bool {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800556 generics.params.is_empty()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400557 }
558
David Tolnay8ef93042016-09-04 14:08:40 -0700559 impl ToTokens for Generics {
560 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400561 if empty_normal_generics(self) {
562 return;
563 }
564
Alex Crichton259ee532017-07-14 06:51:02 -0700565 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800566 self.params.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700567 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700568 }
569 }
570
David Tolnaye7678922016-10-13 20:44:03 -0700571 impl<'a> ToTokens for ImplGenerics<'a> {
572 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500573 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400574 return;
575 }
576
Alex Crichton259ee532017-07-14 06:51:02 -0700577 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -0800578 for param in self.0.params.pairs() {
579 match **param.value() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800580 GenericParam::Lifetime(ref param) => {
581 param.to_tokens(tokens);
582 }
583 GenericParam::Type(ref param) => {
584 // Leave off the type parameter defaults
585 tokens.append_all(param.attrs.outer());
586 param.ident.to_tokens(tokens);
587 if !param.bounds.is_empty() {
588 TokensOrDefault(&param.colon_token).to_tokens(tokens);
589 param.bounds.to_tokens(tokens);
590 }
591 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500592 GenericParam::Const(ref param) => {
593 // Leave off the const parameter defaults
594 tokens.append_all(param.attrs.outer());
595 param.const_token.to_tokens(tokens);
596 param.ident.to_tokens(tokens);
597 param.colon_token.to_tokens(tokens);
598 param.ty.to_tokens(tokens);
599 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400600 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500601 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700602 }
Alex Crichton259ee532017-07-14 06:51:02 -0700603 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700604 }
605 }
606
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800607 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700608 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500609 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400610 return;
611 }
612
Alex Crichton259ee532017-07-14 06:51:02 -0700613 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -0800614 for param in self.0.params.pairs() {
615 match **param.value() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800616 GenericParam::Lifetime(ref param) => {
617 // Leave off the lifetime bounds and attributes
618 param.lifetime.to_tokens(tokens);
619 }
620 GenericParam::Type(ref param) => {
621 // Leave off the type parameter defaults
622 param.ident.to_tokens(tokens);
623 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500624 GenericParam::Const(ref param) => {
625 // Leave off the const parameter defaults
626 param.ident.to_tokens(tokens);
627 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800628 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500629 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700630 }
Alex Crichton259ee532017-07-14 06:51:02 -0700631 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700632 }
633 }
634
David Tolnayc879a502017-01-25 15:51:32 -0800635 impl<'a> ToTokens for Turbofish<'a> {
636 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500637 if !empty_normal_generics(self.0) {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800638 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800639 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800640 }
641 }
642 }
643
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700644 impl ToTokens for BoundLifetimes {
645 fn to_tokens(&self, tokens: &mut Tokens) {
646 self.for_token.to_tokens(tokens);
647 self.lt_token.to_tokens(tokens);
648 self.lifetimes.to_tokens(tokens);
649 self.gt_token.to_tokens(tokens);
650 }
651 }
652
David Tolnay87d0b442016-09-04 11:52:12 -0700653 impl ToTokens for LifetimeDef {
654 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700655 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700656 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400657 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700658 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400659 self.bounds.to_tokens(tokens);
660 }
David Tolnay87d0b442016-09-04 11:52:12 -0700661 }
662 }
663
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800664 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700665 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700666 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700667 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400668 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700669 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400670 self.bounds.to_tokens(tokens);
671 }
672 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700673 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400674 self.default.to_tokens(tokens);
675 }
David Tolnay8ef93042016-09-04 14:08:40 -0700676 }
677 }
678
David Tolnay40fb8ce2018-01-02 10:53:46 -0800679 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700680 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800681 self.modifier.to_tokens(tokens);
682 self.lifetimes.to_tokens(tokens);
683 self.path.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700684 }
685 }
686
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700687 impl ToTokens for TraitBoundModifier {
688 fn to_tokens(&self, tokens: &mut Tokens) {
689 match *self {
690 TraitBoundModifier::None => {}
691 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
692 }
693 }
694 }
695
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500696 impl ToTokens for ConstParam {
697 fn to_tokens(&self, tokens: &mut Tokens) {
698 tokens.append_all(self.attrs.outer());
699 self.const_token.to_tokens(tokens);
700 self.ident.to_tokens(tokens);
701 self.colon_token.to_tokens(tokens);
702 self.ty.to_tokens(tokens);
703 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800704 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500705 self.default.to_tokens(tokens);
706 }
707 }
708 }
709
David Tolnay55337722016-09-11 12:58:56 -0700710 impl ToTokens for WhereClause {
711 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayac997dd2017-12-27 23:18:22 -0500712 self.where_token.to_tokens(tokens);
713 self.predicates.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700714 }
715 }
David Tolnay8ef93042016-09-04 14:08:40 -0700716
David Tolnayd4add852018-01-01 20:13:24 -0800717 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700718 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800719 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700720 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700721 self.colon_token.to_tokens(tokens);
722 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700723 }
724 }
725
David Tolnayd4add852018-01-01 20:13:24 -0800726 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700727 fn to_tokens(&self, tokens: &mut Tokens) {
728 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400729 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700730 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400731 self.bounds.to_tokens(tokens);
732 }
David Tolnay8ef93042016-09-04 14:08:40 -0700733 }
734 }
David Tolnayf8e08832017-01-23 00:04:32 -0800735
David Tolnayd4add852018-01-01 20:13:24 -0800736 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -0800737 fn to_tokens(&self, tokens: &mut Tokens) {
738 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700739 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800740 self.rhs_ty.to_tokens(tokens);
741 }
742 }
David Tolnay87d0b442016-09-04 11:52:12 -0700743}