blob: 919b5fe846dee3ef6704f7711028f3d9b381b146 [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::*;
Sean Griffin8fcca802018-01-15 15:45:41 -070010use punctuated::{Iter, IterMut, 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
Sean Griffin8fcca802018-01-15 15:45:41 -070080impl Generics {
David Tolnayef5199b2018-01-17 10:56:03 -080081 /// Returns an
82 /// <code
83 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
84 /// href="struct.TypeParam.html"><code
85 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
86 /// style="padding-left:0;">&gt;</code>
87 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070088 pub fn type_params(&self) -> TypeParams {
89 TypeParams(self.params.iter())
90 }
91
David Tolnayef5199b2018-01-17 10:56:03 -080092 /// Returns an
93 /// <code
94 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
95 /// href="struct.TypeParam.html"><code
96 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
97 /// style="padding-left:0;">&gt;</code>
98 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070099 pub fn type_params_mut(&mut self) -> TypeParamsMut {
100 TypeParamsMut(self.params.iter_mut())
101 }
102
David Tolnayef5199b2018-01-17 10:56:03 -0800103 /// Returns an
104 /// <code
105 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
106 /// href="struct.LifetimeDef.html"><code
107 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
108 /// style="padding-left:0;">&gt;</code>
109 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700110 pub fn lifetimes(&self) -> Lifetimes {
111 Lifetimes(self.params.iter())
112 }
113
David Tolnayef5199b2018-01-17 10:56:03 -0800114 /// Returns an
115 /// <code
116 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
117 /// href="struct.LifetimeDef.html"><code
118 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
119 /// style="padding-left:0;">&gt;</code>
120 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700121 pub fn lifetimes_mut(&mut self) -> LifetimesMut {
122 LifetimesMut(self.params.iter_mut())
123 }
124
David Tolnayef5199b2018-01-17 10:56:03 -0800125 /// Returns an
126 /// <code
127 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
128 /// href="struct.ConstParam.html"><code
129 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
130 /// style="padding-left:0;">&gt;</code>
131 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700132 pub fn const_params(&self) -> ConstParams {
133 ConstParams(self.params.iter())
134 }
135
David Tolnayef5199b2018-01-17 10:56:03 -0800136 /// Returns an
137 /// <code
138 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
139 /// href="struct.ConstParam.html"><code
140 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
141 /// style="padding-left:0;">&gt;</code>
142 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700143 pub fn const_params_mut(&mut self) -> ConstParamsMut {
144 ConstParamsMut(self.params.iter_mut())
145 }
David Tolnay7f9954d2018-04-01 16:52:15 +0200146
147 /// Initializes an empty `where`-clause if there is not one present already.
148 pub fn make_where_clause(&mut self) -> &mut WhereClause {
149 // This is Option::get_or_insert_with in Rust 1.20.
150 if self.where_clause.is_none() {
151 self.where_clause = Some(WhereClause {
152 where_token: Default::default(),
153 predicates: Punctuated::new(),
154 });
155 }
156 match self.where_clause {
157 Some(ref mut where_clause) => where_clause,
158 None => unreachable!(),
159 }
160 }
Sean Griffin8fcca802018-01-15 15:45:41 -0700161}
162
David Tolnay8095c302018-03-31 19:34:17 +0200163pub struct TypeParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700164
165impl<'a> Iterator for TypeParams<'a> {
166 type Item = &'a TypeParam;
167
168 fn next(&mut self) -> Option<Self::Item> {
169 // FIXME: Remove this when ? on Option is stable
170 let next = match self.0.next() {
171 Some(item) => item,
172 None => return None,
173 };
174 if let GenericParam::Type(ref type_param) = *next {
175 Some(type_param)
176 } else {
177 self.next()
178 }
179 }
180}
181
David Tolnay8095c302018-03-31 19:34:17 +0200182pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700183
184impl<'a> Iterator for TypeParamsMut<'a> {
185 type Item = &'a mut TypeParam;
186
187 fn next(&mut self) -> Option<Self::Item> {
188 // FIXME: Remove this when ? on Option is stable
189 let next = match self.0.next() {
190 Some(item) => item,
191 None => return None,
192 };
193 if let GenericParam::Type(ref mut type_param) = *next {
194 Some(type_param)
195 } else {
196 self.next()
197 }
198 }
199}
200
David Tolnay8095c302018-03-31 19:34:17 +0200201pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700202
203impl<'a> Iterator for Lifetimes<'a> {
204 type Item = &'a LifetimeDef;
205
206 fn next(&mut self) -> Option<Self::Item> {
207 // FIXME: Remove this when ? on Option is stable
208 let next = match self.0.next() {
209 Some(item) => item,
210 None => return None,
211 };
212 if let GenericParam::Lifetime(ref lifetime) = *next {
213 Some(lifetime)
214 } else {
215 self.next()
216 }
217 }
218}
219
David Tolnay8095c302018-03-31 19:34:17 +0200220pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700221
222impl<'a> Iterator for LifetimesMut<'a> {
223 type Item = &'a mut LifetimeDef;
224
225 fn next(&mut self) -> Option<Self::Item> {
226 // FIXME: Remove this when ? on Option is stable
227 let next = match self.0.next() {
228 Some(item) => item,
229 None => return None,
230 };
231 if let GenericParam::Lifetime(ref mut lifetime) = *next {
232 Some(lifetime)
233 } else {
234 self.next()
235 }
236 }
237}
238
David Tolnay8095c302018-03-31 19:34:17 +0200239pub struct ConstParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700240
241impl<'a> Iterator for ConstParams<'a> {
242 type Item = &'a ConstParam;
243
244 fn next(&mut self) -> Option<Self::Item> {
245 // FIXME: Remove this when ? on Option is stable
246 let next = match self.0.next() {
247 Some(item) => item,
248 None => return None,
249 };
250 if let GenericParam::Const(ref const_param) = *next {
251 Some(const_param)
252 } else {
253 self.next()
254 }
255 }
256}
257
David Tolnay8095c302018-03-31 19:34:17 +0200258pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700259
260impl<'a> Iterator for ConstParamsMut<'a> {
261 type Item = &'a mut ConstParam;
262
263 fn next(&mut self) -> Option<Self::Item> {
264 // FIXME: Remove this when ? on Option is stable
265 let next = match self.0.next() {
266 Some(item) => item,
267 None => return None,
268 };
269 if let GenericParam::Const(ref mut const_param) = *next {
270 Some(const_param)
271 } else {
272 self.next()
273 }
274 }
275}
276
David Tolnay461d98e2018-01-07 11:07:19 -0800277/// Returned by `Generics::split_for_impl`.
278///
279/// *This type is available if Syn is built with the `"derive"` or `"full"`
280/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700281#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400282#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
283#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400284pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700285
David Tolnay461d98e2018-01-07 11:07:19 -0800286/// Returned by `Generics::split_for_impl`.
287///
288/// *This type is available if Syn is built with the `"derive"` or `"full"`
289/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700290#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400291#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
292#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800293pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700294
David Tolnay461d98e2018-01-07 11:07:19 -0800295/// Returned by `TypeGenerics::as_turbofish`.
296///
297/// *This type is available if Syn is built with the `"derive"` or `"full"`
298/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800299#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400300#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
301#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400302pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800303
David Tolnaye95cc9f2017-01-25 15:57:09 -0800304#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700305impl Generics {
306 /// Split a type's generics into the pieces required for impl'ing a trait
307 /// for that type.
308 ///
309 /// ```
310 /// # extern crate syn;
311 /// # #[macro_use]
312 /// # extern crate quote;
313 /// # fn main() {
314 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700315 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -0700316 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
317 /// quote! {
318 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
319 /// // ...
320 /// }
321 /// }
322 /// # ;
323 /// # }
324 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800325 ///
326 /// *This method is available if Syn is built with the `"derive"` or
327 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500328 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800329 (
330 ImplGenerics(self),
331 TypeGenerics(self),
332 self.where_clause.as_ref(),
333 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700334 }
335}
336
David Tolnaye95cc9f2017-01-25 15:57:09 -0800337#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800338impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800339 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800340 ///
341 /// *This method is available if Syn is built with the `"derive"` or
342 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800343 pub fn as_turbofish(&self) -> Turbofish {
344 Turbofish(self.0)
345 }
346}
347
Alex Crichton62a0a592017-05-22 13:58:53 -0700348ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800349 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800350 ///
351 /// *This type is available if Syn is built with the `"derive"` or `"full"`
352 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700353 #[derive(Default)]
354 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800355 pub for_token: Token![for],
356 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500357 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800358 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700359 }
360}
361
David Tolnayf9505b52016-10-02 09:18:52 -0700362impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700363 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700364 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700365 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700366 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700367 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500368 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700369 }
370 }
371}
372
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800373impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700374 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800375 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700376 attrs: vec![],
377 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700378 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500379 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700380 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700381 default: None,
382 }
383 }
384}
385
David Tolnay40fb8ce2018-01-02 10:53:46 -0800386ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800387 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800388 ///
389 /// *This type is available if Syn is built with the `"derive"` or `"full"`
390 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800391 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800392 pub Trait(TraitBound),
393 pub Lifetime(Lifetime),
394 }
395}
396
397ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800398 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"derive"` or `"full"`
401 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800402 pub struct TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200403 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800404 pub modifier: TraitBoundModifier,
405 /// The `for<'a>` in `for<'a> Foo<&'a T>`
406 pub lifetimes: Option<BoundLifetimes>,
407 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
408 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700409 }
David Tolnay55337722016-09-11 12:58:56 -0700410}
411
Alex Crichton62a0a592017-05-22 13:58:53 -0700412ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800413 /// A modifier on a trait bound, currently only used for the `?` in
414 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800415 ///
416 /// *This type is available if Syn is built with the `"derive"` or `"full"`
417 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700418 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700419 pub enum TraitBoundModifier {
420 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800421 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700422 }
David Tolnay55337722016-09-11 12:58:56 -0700423}
424
Alex Crichton62a0a592017-05-22 13:58:53 -0700425ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800426 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
427 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800428 ///
429 /// *This type is available if Syn is built with the `"derive"` or `"full"`
430 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700431 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500432 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500433 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700434 }
David Tolnayb79ee962016-09-04 09:39:20 -0700435}
436
Alex Crichton62a0a592017-05-22 13:58:53 -0700437ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800438 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800439 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800440 /// *This type is available if Syn is built with the `"derive"` or `"full"`
441 /// feature.*
442 ///
David Tolnay614a0142018-01-07 10:25:43 -0800443 /// # Syntax tree enum
444 ///
445 /// This type is a [syntax tree enum].
446 ///
447 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800449 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800450 ///
451 /// *This type is available if Syn is built with the `"derive"` or
452 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800453 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700454 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800455 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700456 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800457 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800458 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700459 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500460 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700461 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700462
David Tolnayed906d12018-01-07 01:20:29 -0800463 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800464 ///
465 /// *This type is available if Syn is built with the `"derive"` or
466 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800467 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800469 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500470 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700471 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700472
David Tolnayed906d12018-01-07 01:20:29 -0800473 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800474 ///
475 /// *This type is available if Syn is built with the `"derive"` or
476 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800477 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800478 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800479 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800480 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700481 }),
482 }
David Tolnayf8e08832017-01-23 00:04:32 -0800483}
484
David Tolnay86eca752016-09-04 11:26:41 -0700485#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700486pub mod parsing {
487 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700488
David Tolnay56080682018-01-06 14:01:52 -0800489 use punctuated::Pair;
David Tolnay94d2b792018-04-29 12:26:10 -0700490 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700491
492 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400493 named!(parse -> Self, map!(
494 alt!(
495 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800496 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500497 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400498 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800499 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500500 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400501 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800502 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400503 (lifetimes, ty_params, Some(lt), Some(gt))
504 )
505 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500506 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400507 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700508 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400509 lt_token: lt,
David Tolnay56080682018-01-06 14:01:52 -0800510 params: lifetimes.into_pairs()
511 .map(Pair::into_tuple)
512 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800513 .chain(ty_params.unwrap_or_default()
David Tolnay56080682018-01-06 14:01:52 -0800514 .into_pairs()
515 .map(Pair::into_tuple)
516 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
David Tolnay660fd1f2017-12-31 01:52:57 -0500517 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800518 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500519 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400520 }
Michael Layzell92639a52017-06-01 00:07:44 -0400521 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800522
523 fn description() -> Option<&'static str> {
524 Some("generic parameters in declaration")
525 }
Alex Crichton954046c2017-05-30 21:49:42 -0700526 }
527
David Tolnay36454bb2018-01-07 22:40:02 -0800528 impl Synom for GenericParam {
529 named!(parse -> Self, alt!(
530 syn!(TypeParam) => { GenericParam::Type }
531 |
532 syn!(LifetimeDef) => { GenericParam::Lifetime }
533 |
534 syn!(ConstParam) => { GenericParam::Const }
535 ));
536
537 fn description() -> Option<&'static str> {
538 Some("generic parameter")
539 }
540 }
541
Alex Crichton954046c2017-05-30 21:49:42 -0700542 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400543 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500544 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400545 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800546 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400547 bounds: cond!(
548 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500549 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400550 ) >>
551 (LifetimeDef {
552 attrs: attrs,
553 lifetime: life,
554 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500555 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400556 })
557 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800558
559 fn description() -> Option<&'static str> {
560 Some("lifetime definition")
561 }
Alex Crichton954046c2017-05-30 21:49:42 -0700562 }
563
564 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400565 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800566 for_: keyword!(for) >>
567 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500568 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800569 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400570 (BoundLifetimes {
571 for_token: for_,
572 lt_token: lt,
573 gt_token: gt,
574 lifetimes: lifetimes,
575 })
576 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800577
578 fn description() -> Option<&'static str> {
579 Some("bound lifetimes")
580 }
Alex Crichton954046c2017-05-30 21:49:42 -0700581 }
David Tolnay55337722016-09-11 12:58:56 -0700582
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800583 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400584 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500585 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400586 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800587 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400588 bounds: cond!(
589 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500590 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400591 ) >>
592 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800593 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800594 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400595 (eq, ty)
596 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800597 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400598 attrs: attrs,
599 ident: id,
600 bounds: bounds.unwrap_or_default(),
601 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800602 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400603 default: default.map(|d| d.1),
604 })
605 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800606
607 fn description() -> Option<&'static str> {
608 Some("type parameter")
609 }
Alex Crichton954046c2017-05-30 21:49:42 -0700610 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700611
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800612 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400613 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800614 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400615 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800616 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400617 |
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200618 parens!(syn!(TraitBound)) => {|(parens, mut bound)| {
619 bound.paren_token = Some(parens);
620 TypeParamBound::Trait(bound)
621 }}
Michael Layzell92639a52017-06-01 00:07:44 -0400622 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700623
624 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500625 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700626 }
627 }
628
David Tolnay40fb8ce2018-01-02 10:53:46 -0800629 impl Synom for TraitBound {
630 named!(parse -> Self, do_parse!(
631 modifier: syn!(TraitBoundModifier) >>
632 lifetimes: option!(syn!(BoundLifetimes)) >>
633 mut path: syn!(Path) >>
634 parenthesized: option!(cond_reduce!(
David Tolnay56080682018-01-06 14:01:52 -0800635 path.segments.last().unwrap().value().arguments.is_empty(),
David Tolnay40fb8ce2018-01-02 10:53:46 -0800636 syn!(ParenthesizedGenericArguments)
637 )) >>
638 ({
639 if let Some(parenthesized) = parenthesized {
640 let parenthesized = PathArguments::Parenthesized(parenthesized);
David Tolnay56080682018-01-06 14:01:52 -0800641 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800642 }
643 TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200644 paren_token: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800645 modifier: modifier,
646 lifetimes: lifetimes,
647 path: path,
648 }
649 })
650 ));
651
652 fn description() -> Option<&'static str> {
653 Some("trait bound")
654 }
655 }
656
657 impl Synom for TraitBoundModifier {
658 named!(parse -> Self, alt!(
659 punct!(?) => { TraitBoundModifier::Maybe }
660 |
661 epsilon!() => { |_| TraitBoundModifier::None }
662 ));
663
664 fn description() -> Option<&'static str> {
665 Some("trait bound modifier")
666 }
667 }
668
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500669 impl Synom for ConstParam {
670 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500671 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500672 const_: keyword!(const) >>
673 ident: syn!(Ident) >>
674 colon: punct!(:) >>
675 ty: syn!(Type) >>
676 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800677 ({
678 let (eq_token, default) = match eq_def {
679 Some((eq_token, default)) => (Some(eq_token), Some(default)),
680 None => (None, None),
681 };
682 ConstParam {
683 attrs: attrs,
684 const_token: const_,
685 ident: ident,
686 colon_token: colon,
687 ty: ty,
688 eq_token: eq_token,
689 default: default,
690 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500691 })
692 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800693
694 fn description() -> Option<&'static str> {
695 Some("generic `const` parameter")
696 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500697 }
698
Alex Crichton954046c2017-05-30 21:49:42 -0700699 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500700 named!(parse -> Self, do_parse!(
701 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500702 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500703 (WhereClause {
704 predicates: predicates,
705 where_token: where_,
706 })
Michael Layzell92639a52017-06-01 00:07:44 -0400707 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700708
709 fn description() -> Option<&'static str> {
710 Some("where clause")
711 }
712 }
713
714 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400715 named!(parse -> Self, alt!(
716 do_parse!(
717 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800718 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400719 bounds: cond!(
720 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500721 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400722 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800723 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400724 lifetime: ident,
725 bounds: bounds.unwrap_or_default(),
726 colon_token: colon,
727 }))
728 )
729 |
730 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800731 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800732 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800733 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500734 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800735 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800736 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400737 bounded_ty: bounded_ty,
738 bounds: bounds,
739 colon_token: colon,
740 }))
741 )
742 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800743
744 fn description() -> Option<&'static str> {
745 Some("predicate in where clause")
746 }
Alex Crichton954046c2017-05-30 21:49:42 -0700747 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700748}
David Tolnay87d0b442016-09-04 11:52:12 -0700749
750#[cfg(feature = "printing")]
751mod printing {
752 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700753 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500754 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700755
David Tolnay8ef93042016-09-04 14:08:40 -0700756 impl ToTokens for Generics {
757 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800758 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400759 return;
760 }
761
Alex Crichton259ee532017-07-14 06:51:02 -0700762 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800763
764 // Print lifetimes before types and consts, regardless of their
765 // order in self.params.
766 //
767 // TODO: ordering rules for const parameters vs type parameters have
768 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
769 let mut trailing_or_empty = true;
770 for param in self.params.pairs() {
771 if let GenericParam::Lifetime(_) = **param.value() {
772 param.to_tokens(tokens);
773 trailing_or_empty = param.punct().is_some();
774 }
775 }
776 for param in self.params.pairs() {
777 match **param.value() {
778 GenericParam::Type(_) | GenericParam::Const(_) => {
779 if !trailing_or_empty {
780 <Token![,]>::default().to_tokens(tokens);
781 trailing_or_empty = true;
782 }
783 param.to_tokens(tokens);
784 }
785 GenericParam::Lifetime(_) => {}
786 }
787 }
788
Alex Crichton259ee532017-07-14 06:51:02 -0700789 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700790 }
791 }
792
David Tolnaye7678922016-10-13 20:44:03 -0700793 impl<'a> ToTokens for ImplGenerics<'a> {
794 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800795 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400796 return;
797 }
798
Alex Crichton259ee532017-07-14 06:51:02 -0700799 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800800
801 // Print lifetimes before types and consts, regardless of their
802 // order in self.params.
803 //
804 // TODO: ordering rules for const parameters vs type parameters have
805 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
806 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800807 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800808 if let GenericParam::Lifetime(_) = **param.value() {
809 param.to_tokens(tokens);
810 trailing_or_empty = param.punct().is_some();
811 }
812 }
813 for param in self.0.params.pairs() {
814 if let GenericParam::Lifetime(_) = **param.value() {
815 continue;
816 }
817 if !trailing_or_empty {
818 <Token![,]>::default().to_tokens(tokens);
819 trailing_or_empty = true;
820 }
David Tolnay56080682018-01-06 14:01:52 -0800821 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800822 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800823 GenericParam::Type(ref param) => {
824 // Leave off the type parameter defaults
825 tokens.append_all(param.attrs.outer());
826 param.ident.to_tokens(tokens);
827 if !param.bounds.is_empty() {
828 TokensOrDefault(&param.colon_token).to_tokens(tokens);
829 param.bounds.to_tokens(tokens);
830 }
831 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500832 GenericParam::Const(ref param) => {
833 // Leave off the const parameter defaults
834 tokens.append_all(param.attrs.outer());
835 param.const_token.to_tokens(tokens);
836 param.ident.to_tokens(tokens);
837 param.colon_token.to_tokens(tokens);
838 param.ty.to_tokens(tokens);
839 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400840 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500841 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700842 }
David Tolnay225aca62018-01-11 20:51:46 -0800843
Alex Crichton259ee532017-07-14 06:51:02 -0700844 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700845 }
846 }
847
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800848 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700849 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800850 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400851 return;
852 }
853
Alex Crichton259ee532017-07-14 06:51:02 -0700854 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800855
856 // Print lifetimes before types and consts, regardless of their
857 // order in self.params.
858 //
859 // TODO: ordering rules for const parameters vs type parameters have
860 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
861 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800862 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800863 if let GenericParam::Lifetime(ref def) = **param.value() {
864 // Leave off the lifetime bounds and attributes
865 def.lifetime.to_tokens(tokens);
866 param.punct().to_tokens(tokens);
867 trailing_or_empty = param.punct().is_some();
868 }
869 }
870 for param in self.0.params.pairs() {
871 if let GenericParam::Lifetime(_) = **param.value() {
872 continue;
873 }
874 if !trailing_or_empty {
875 <Token![,]>::default().to_tokens(tokens);
876 trailing_or_empty = true;
877 }
David Tolnay56080682018-01-06 14:01:52 -0800878 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800879 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800880 GenericParam::Type(ref param) => {
881 // Leave off the type parameter defaults
882 param.ident.to_tokens(tokens);
883 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500884 GenericParam::Const(ref param) => {
885 // Leave off the const parameter defaults
886 param.ident.to_tokens(tokens);
887 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800888 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500889 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700890 }
David Tolnay225aca62018-01-11 20:51:46 -0800891
Alex Crichton259ee532017-07-14 06:51:02 -0700892 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700893 }
894 }
895
David Tolnayc879a502017-01-25 15:51:32 -0800896 impl<'a> ToTokens for Turbofish<'a> {
897 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800898 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800899 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800900 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800901 }
902 }
903 }
904
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700905 impl ToTokens for BoundLifetimes {
906 fn to_tokens(&self, tokens: &mut Tokens) {
907 self.for_token.to_tokens(tokens);
908 self.lt_token.to_tokens(tokens);
909 self.lifetimes.to_tokens(tokens);
910 self.gt_token.to_tokens(tokens);
911 }
912 }
913
David Tolnay87d0b442016-09-04 11:52:12 -0700914 impl ToTokens for LifetimeDef {
915 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700916 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700917 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400918 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700919 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400920 self.bounds.to_tokens(tokens);
921 }
David Tolnay87d0b442016-09-04 11:52:12 -0700922 }
923 }
924
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800925 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700926 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700927 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700928 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400929 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700930 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400931 self.bounds.to_tokens(tokens);
932 }
933 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700934 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400935 self.default.to_tokens(tokens);
936 }
David Tolnay8ef93042016-09-04 14:08:40 -0700937 }
938 }
939
David Tolnay40fb8ce2018-01-02 10:53:46 -0800940 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700941 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200942 let to_tokens = |tokens: &mut Tokens| {
943 self.modifier.to_tokens(tokens);
944 self.lifetimes.to_tokens(tokens);
945 self.path.to_tokens(tokens);
946 };
947 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +0200948 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200949 None => to_tokens(tokens),
950 }
David Tolnay55337722016-09-11 12:58:56 -0700951 }
952 }
953
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700954 impl ToTokens for TraitBoundModifier {
955 fn to_tokens(&self, tokens: &mut Tokens) {
956 match *self {
957 TraitBoundModifier::None => {}
958 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
959 }
960 }
961 }
962
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500963 impl ToTokens for ConstParam {
964 fn to_tokens(&self, tokens: &mut Tokens) {
965 tokens.append_all(self.attrs.outer());
966 self.const_token.to_tokens(tokens);
967 self.ident.to_tokens(tokens);
968 self.colon_token.to_tokens(tokens);
969 self.ty.to_tokens(tokens);
970 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800971 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500972 self.default.to_tokens(tokens);
973 }
974 }
975 }
976
David Tolnay55337722016-09-11 12:58:56 -0700977 impl ToTokens for WhereClause {
978 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay2a0b02f2018-03-09 00:50:45 -0800979 if !self.predicates.is_empty() {
980 self.where_token.to_tokens(tokens);
981 self.predicates.to_tokens(tokens);
982 }
David Tolnay87d0b442016-09-04 11:52:12 -0700983 }
984 }
David Tolnay8ef93042016-09-04 14:08:40 -0700985
David Tolnayd4add852018-01-01 20:13:24 -0800986 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700987 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800988 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700989 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700990 self.colon_token.to_tokens(tokens);
991 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700992 }
993 }
994
David Tolnayd4add852018-01-01 20:13:24 -0800995 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700996 fn to_tokens(&self, tokens: &mut Tokens) {
997 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400998 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700999 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001000 self.bounds.to_tokens(tokens);
1001 }
David Tolnay8ef93042016-09-04 14:08:40 -07001002 }
1003 }
David Tolnayf8e08832017-01-23 00:04:32 -08001004
David Tolnayd4add852018-01-01 20:13:24 -08001005 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -08001006 fn to_tokens(&self, tokens: &mut Tokens) {
1007 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001008 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001009 self.rhs_ty.to_tokens(tokens);
1010 }
1011 }
David Tolnay87d0b442016-09-04 11:52:12 -07001012}