blob: 13a850bbb2695718e060a419dea2c5be840cc836 [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 }
146}
147
Sean Griffin8fcca802018-01-15 15:45:41 -0700148pub 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 // FIXME: Remove this when ? on Option is stable
155 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
Sean Griffin8fcca802018-01-15 15:45:41 -0700167pub 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 // FIXME: Remove this when ? on Option is stable
174 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
Sean Griffin8fcca802018-01-15 15:45:41 -0700186pub 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 // FIXME: Remove this when ? on Option is stable
193 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
Sean Griffin8fcca802018-01-15 15:45:41 -0700205pub 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 // FIXME: Remove this when ? on Option is stable
212 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
Sean Griffin8fcca802018-01-15 15:45:41 -0700224pub 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 // FIXME: Remove this when ? on Option is stable
231 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
Sean Griffin8fcca802018-01-15 15:45:41 -0700243pub 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 // FIXME: Remove this when ? on Option is stable
250 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
David Tolnay461d98e2018-01-07 11:07:19 -0800262/// Returned by `Generics::split_for_impl`.
263///
264/// *This type is available if Syn is built with the `"derive"` or `"full"`
265/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700266#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400267#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
268#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400269pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700270
David Tolnay461d98e2018-01-07 11:07:19 -0800271/// Returned by `Generics::split_for_impl`.
272///
273/// *This type is available if Syn is built with the `"derive"` or `"full"`
274/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700275#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400276#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
277#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800278pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700279
David Tolnay461d98e2018-01-07 11:07:19 -0800280/// Returned by `TypeGenerics::as_turbofish`.
281///
282/// *This type is available if Syn is built with the `"derive"` or `"full"`
283/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800284#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400285#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
286#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400287pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800288
David Tolnaye95cc9f2017-01-25 15:57:09 -0800289#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700290impl Generics {
291 /// Split a type's generics into the pieces required for impl'ing a trait
292 /// for that type.
293 ///
294 /// ```
295 /// # extern crate syn;
296 /// # #[macro_use]
297 /// # extern crate quote;
298 /// # fn main() {
299 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700300 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -0700301 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
302 /// quote! {
303 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
304 /// // ...
305 /// }
306 /// }
307 /// # ;
308 /// # }
309 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800310 ///
311 /// *This method is available if Syn is built with the `"derive"` or
312 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500313 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800314 (
315 ImplGenerics(self),
316 TypeGenerics(self),
317 self.where_clause.as_ref(),
318 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700319 }
320}
321
David Tolnaye95cc9f2017-01-25 15:57:09 -0800322#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800323impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800324 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
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 Tolnayc879a502017-01-25 15:51:32 -0800328 pub fn as_turbofish(&self) -> Turbofish {
329 Turbofish(self.0)
330 }
331}
332
Alex Crichton62a0a592017-05-22 13:58:53 -0700333ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800334 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800335 ///
336 /// *This type is available if Syn is built with the `"derive"` or `"full"`
337 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700338 #[derive(Default)]
339 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800340 pub for_token: Token![for],
341 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500342 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800343 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700344 }
345}
346
David Tolnayf9505b52016-10-02 09:18:52 -0700347impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700348 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700349 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700350 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700351 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700352 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500353 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700354 }
355 }
356}
357
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800358impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700359 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800360 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700361 attrs: vec![],
362 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700363 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500364 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700365 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700366 default: None,
367 }
368 }
369}
370
David Tolnay40fb8ce2018-01-02 10:53:46 -0800371ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800372 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800373 ///
374 /// *This type is available if Syn is built with the `"derive"` or `"full"`
375 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800376 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800377 pub Trait(TraitBound),
378 pub Lifetime(Lifetime),
379 }
380}
381
382ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800383 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800384 ///
385 /// *This type is available if Syn is built with the `"derive"` or `"full"`
386 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800387 pub struct TraitBound {
388 pub modifier: TraitBoundModifier,
389 /// The `for<'a>` in `for<'a> Foo<&'a T>`
390 pub lifetimes: Option<BoundLifetimes>,
391 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
392 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700393 }
David Tolnay55337722016-09-11 12:58:56 -0700394}
395
Alex Crichton62a0a592017-05-22 13:58:53 -0700396ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800397 /// A modifier on a trait bound, currently only used for the `?` in
398 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"derive"` or `"full"`
401 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700402 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub enum TraitBoundModifier {
404 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800405 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700406 }
David Tolnay55337722016-09-11 12:58:56 -0700407}
408
Alex Crichton62a0a592017-05-22 13:58:53 -0700409ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800410 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
411 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800412 ///
413 /// *This type is available if Syn is built with the `"derive"` or `"full"`
414 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700415 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500416 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500417 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700418 }
David Tolnayb79ee962016-09-04 09:39:20 -0700419}
420
Alex Crichton62a0a592017-05-22 13:58:53 -0700421ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800422 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800423 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800424 /// *This type is available if Syn is built with the `"derive"` or `"full"`
425 /// feature.*
426 ///
David Tolnay614a0142018-01-07 10:25:43 -0800427 /// # Syntax tree enum
428 ///
429 /// This type is a [syntax tree enum].
430 ///
431 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700432 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800433 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800434 ///
435 /// *This type is available if Syn is built with the `"derive"` or
436 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800437 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700438 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800439 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700440 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800441 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800442 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700443 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500444 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700445 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700446
David Tolnayed906d12018-01-07 01:20:29 -0800447 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800448 ///
449 /// *This type is available if Syn is built with the `"derive"` or
450 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800451 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700452 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800453 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500454 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700455 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700456
David Tolnayed906d12018-01-07 01:20:29 -0800457 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800458 ///
459 /// *This type is available if Syn is built with the `"derive"` or
460 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800461 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800462 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800463 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800464 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700465 }),
466 }
David Tolnayf8e08832017-01-23 00:04:32 -0800467}
468
David Tolnay86eca752016-09-04 11:26:41 -0700469#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700470pub mod parsing {
471 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700472
David Tolnay63e3dee2017-06-03 20:13:17 -0700473 use synom::Synom;
David Tolnay56080682018-01-06 14:01:52 -0800474 use punctuated::Pair;
Alex Crichton954046c2017-05-30 21:49:42 -0700475
476 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400477 named!(parse -> Self, map!(
478 alt!(
479 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800480 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500481 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400482 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800483 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500484 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400485 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800486 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400487 (lifetimes, ty_params, Some(lt), Some(gt))
488 )
489 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500490 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400491 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700492 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400493 lt_token: lt,
David Tolnay56080682018-01-06 14:01:52 -0800494 params: lifetimes.into_pairs()
495 .map(Pair::into_tuple)
496 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800497 .chain(ty_params.unwrap_or_default()
David Tolnay56080682018-01-06 14:01:52 -0800498 .into_pairs()
499 .map(Pair::into_tuple)
500 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
David Tolnay660fd1f2017-12-31 01:52:57 -0500501 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800502 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500503 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400504 }
Michael Layzell92639a52017-06-01 00:07:44 -0400505 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800506
507 fn description() -> Option<&'static str> {
508 Some("generic parameters in declaration")
509 }
Alex Crichton954046c2017-05-30 21:49:42 -0700510 }
511
David Tolnay36454bb2018-01-07 22:40:02 -0800512 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
Alex Crichton954046c2017-05-30 21:49:42 -0700526 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400527 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500528 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400529 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800530 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400531 bounds: cond!(
532 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500533 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400534 ) >>
535 (LifetimeDef {
536 attrs: attrs,
537 lifetime: life,
538 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500539 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400540 })
541 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800542
543 fn description() -> Option<&'static str> {
544 Some("lifetime definition")
545 }
Alex Crichton954046c2017-05-30 21:49:42 -0700546 }
547
548 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400549 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800550 for_: keyword!(for) >>
551 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500552 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800553 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400554 (BoundLifetimes {
555 for_token: for_,
556 lt_token: lt,
557 gt_token: gt,
558 lifetimes: lifetimes,
559 })
560 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800561
562 fn description() -> Option<&'static str> {
563 Some("bound lifetimes")
564 }
Alex Crichton954046c2017-05-30 21:49:42 -0700565 }
David Tolnay55337722016-09-11 12:58:56 -0700566
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800567 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400568 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500569 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400570 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800571 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400572 bounds: cond!(
573 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500574 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400575 ) >>
576 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800577 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800578 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400579 (eq, ty)
580 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800581 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400582 attrs: attrs,
583 ident: id,
584 bounds: bounds.unwrap_or_default(),
585 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800586 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400587 default: default.map(|d| d.1),
588 })
589 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800590
591 fn description() -> Option<&'static str> {
592 Some("type parameter")
593 }
Alex Crichton954046c2017-05-30 21:49:42 -0700594 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700595
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800596 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400597 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800598 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400599 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800600 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400601 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800602 parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
Michael Layzell92639a52017-06-01 00:07:44 -0400603 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700604
605 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500606 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700607 }
608 }
609
David Tolnay40fb8ce2018-01-02 10:53:46 -0800610 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!(
David Tolnay56080682018-01-06 14:01:52 -0800616 path.segments.last().unwrap().value().arguments.is_empty(),
David Tolnay40fb8ce2018-01-02 10:53:46 -0800617 syn!(ParenthesizedGenericArguments)
618 )) >>
619 ({
620 if let Some(parenthesized) = parenthesized {
621 let parenthesized = PathArguments::Parenthesized(parenthesized);
David Tolnay56080682018-01-06 14:01:52 -0800622 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800623 }
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
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500649 impl Synom for ConstParam {
650 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500651 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500652 const_: keyword!(const) >>
653 ident: syn!(Ident) >>
654 colon: punct!(:) >>
655 ty: syn!(Type) >>
656 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800657 ({
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 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500671 })
672 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800673
674 fn description() -> Option<&'static str> {
675 Some("generic `const` parameter")
676 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500677 }
678
Alex Crichton954046c2017-05-30 21:49:42 -0700679 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500680 named!(parse -> Self, do_parse!(
681 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500682 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500683 (WhereClause {
684 predicates: predicates,
685 where_token: where_,
686 })
Michael Layzell92639a52017-06-01 00:07:44 -0400687 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700688
689 fn description() -> Option<&'static str> {
690 Some("where clause")
691 }
692 }
693
694 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400695 named!(parse -> Self, alt!(
696 do_parse!(
697 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800698 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400699 bounds: cond!(
700 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500701 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400702 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800703 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400704 lifetime: ident,
705 bounds: bounds.unwrap_or_default(),
706 colon_token: colon,
707 }))
708 )
709 |
710 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800711 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800712 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800713 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500714 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800715 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800716 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400717 bounded_ty: bounded_ty,
718 bounds: bounds,
719 colon_token: colon,
720 }))
721 )
722 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800723
724 fn description() -> Option<&'static str> {
725 Some("predicate in where clause")
726 }
Alex Crichton954046c2017-05-30 21:49:42 -0700727 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700728}
David Tolnay87d0b442016-09-04 11:52:12 -0700729
730#[cfg(feature = "printing")]
731mod printing {
732 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700733 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500734 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700735
David Tolnay8ef93042016-09-04 14:08:40 -0700736 impl ToTokens for Generics {
737 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800738 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400739 return;
740 }
741
Alex Crichton259ee532017-07-14 06:51:02 -0700742 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800743
744 // Print lifetimes before types and consts, regardless of their
745 // order in self.params.
746 //
747 // TODO: ordering rules for const parameters vs type parameters have
748 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
749 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
Alex Crichton259ee532017-07-14 06:51:02 -0700769 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700770 }
771 }
772
David Tolnaye7678922016-10-13 20:44:03 -0700773 impl<'a> ToTokens for ImplGenerics<'a> {
774 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800775 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400776 return;
777 }
778
Alex Crichton259ee532017-07-14 06:51:02 -0700779 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800780
781 // Print lifetimes before types and consts, regardless of their
782 // order in self.params.
783 //
784 // TODO: ordering rules for const parameters vs type parameters have
785 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
786 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800787 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800788 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 }
David Tolnay56080682018-01-06 14:01:52 -0800801 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800802 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800803 GenericParam::Type(ref param) => {
804 // Leave off the type parameter defaults
805 tokens.append_all(param.attrs.outer());
806 param.ident.to_tokens(tokens);
807 if !param.bounds.is_empty() {
808 TokensOrDefault(&param.colon_token).to_tokens(tokens);
809 param.bounds.to_tokens(tokens);
810 }
811 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500812 GenericParam::Const(ref param) => {
813 // Leave off the const parameter defaults
814 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 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400820 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500821 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700822 }
David Tolnay225aca62018-01-11 20:51:46 -0800823
Alex Crichton259ee532017-07-14 06:51:02 -0700824 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700825 }
826 }
827
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800828 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700829 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800830 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400831 return;
832 }
833
Alex Crichton259ee532017-07-14 06:51:02 -0700834 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800835
836 // Print lifetimes before types and consts, regardless of their
837 // order in self.params.
838 //
839 // TODO: ordering rules for const parameters vs type parameters have
840 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
841 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800842 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800843 if let GenericParam::Lifetime(ref def) = **param.value() {
844 // Leave off the lifetime bounds and attributes
845 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 }
David Tolnay56080682018-01-06 14:01:52 -0800858 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800859 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800860 GenericParam::Type(ref param) => {
861 // Leave off the type parameter defaults
862 param.ident.to_tokens(tokens);
863 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500864 GenericParam::Const(ref param) => {
865 // Leave off the const parameter defaults
866 param.ident.to_tokens(tokens);
867 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800868 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500869 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700870 }
David Tolnay225aca62018-01-11 20:51:46 -0800871
Alex Crichton259ee532017-07-14 06:51:02 -0700872 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700873 }
874 }
875
David Tolnayc879a502017-01-25 15:51:32 -0800876 impl<'a> ToTokens for Turbofish<'a> {
877 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800878 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800879 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800880 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800881 }
882 }
883 }
884
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700885 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
David Tolnay87d0b442016-09-04 11:52:12 -0700894 impl ToTokens for LifetimeDef {
895 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700896 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700897 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400898 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700899 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400900 self.bounds.to_tokens(tokens);
901 }
David Tolnay87d0b442016-09-04 11:52:12 -0700902 }
903 }
904
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800905 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700906 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700907 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700908 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400909 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700910 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400911 self.bounds.to_tokens(tokens);
912 }
913 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700914 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400915 self.default.to_tokens(tokens);
916 }
David Tolnay8ef93042016-09-04 14:08:40 -0700917 }
918 }
919
David Tolnay40fb8ce2018-01-02 10:53:46 -0800920 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700921 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800922 self.modifier.to_tokens(tokens);
923 self.lifetimes.to_tokens(tokens);
924 self.path.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700925 }
926 }
927
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700928 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
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500937 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() {
David Tolnay78ee5202017-12-04 22:17:54 -0800945 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500946 self.default.to_tokens(tokens);
947 }
948 }
949 }
950
David Tolnay55337722016-09-11 12:58:56 -0700951 impl ToTokens for WhereClause {
952 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay2a0b02f2018-03-09 00:50:45 -0800953 if !self.predicates.is_empty() {
954 self.where_token.to_tokens(tokens);
955 self.predicates.to_tokens(tokens);
956 }
David Tolnay87d0b442016-09-04 11:52:12 -0700957 }
958 }
David Tolnay8ef93042016-09-04 14:08:40 -0700959
David Tolnayd4add852018-01-01 20:13:24 -0800960 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700961 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800962 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700963 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700964 self.colon_token.to_tokens(tokens);
965 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700966 }
967 }
968
David Tolnayd4add852018-01-01 20:13:24 -0800969 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700970 fn to_tokens(&self, tokens: &mut Tokens) {
971 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400972 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700973 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400974 self.bounds.to_tokens(tokens);
975 }
David Tolnay8ef93042016-09-04 14:08:40 -0700976 }
977 }
David Tolnayf8e08832017-01-23 00:04:32 -0800978
David Tolnayd4add852018-01-01 20:13:24 -0800979 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -0800980 fn to_tokens(&self, tokens: &mut Tokens) {
981 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700982 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800983 self.rhs_ty.to_tokens(tokens);
984 }
985 }
David Tolnay87d0b442016-09-04 11:52:12 -0700986}