blob: eaade9278bcb28a1ee373d83d0cc6cf2b9103592 [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
David Tolnay8095c302018-03-31 19:34:17 +0200148pub struct TypeParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700149
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
David Tolnay8095c302018-03-31 19:34:17 +0200167pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700168
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
David Tolnay8095c302018-03-31 19:34:17 +0200186pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700187
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
David Tolnay8095c302018-03-31 19:34:17 +0200205pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700206
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
David Tolnay8095c302018-03-31 19:34:17 +0200224pub struct ConstParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700225
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
David Tolnay8095c302018-03-31 19:34:17 +0200243pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700244
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 {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200388 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800389 pub modifier: TraitBoundModifier,
390 /// The `for<'a>` in `for<'a> Foo<&'a T>`
391 pub lifetimes: Option<BoundLifetimes>,
392 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
393 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }
David Tolnay55337722016-09-11 12:58:56 -0700395}
396
Alex Crichton62a0a592017-05-22 13:58:53 -0700397ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800398 /// A modifier on a trait bound, currently only used for the `?` in
399 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or `"full"`
402 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700403 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700404 pub enum TraitBoundModifier {
405 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800406 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700407 }
David Tolnay55337722016-09-11 12:58:56 -0700408}
409
Alex Crichton62a0a592017-05-22 13:58:53 -0700410ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800411 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
412 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800413 ///
414 /// *This type is available if Syn is built with the `"derive"` or `"full"`
415 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500417 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500418 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700419 }
David Tolnayb79ee962016-09-04 09:39:20 -0700420}
421
Alex Crichton62a0a592017-05-22 13:58:53 -0700422ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800423 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800424 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800425 /// *This type is available if Syn is built with the `"derive"` or `"full"`
426 /// feature.*
427 ///
David Tolnay614a0142018-01-07 10:25:43 -0800428 /// # Syntax tree enum
429 ///
430 /// This type is a [syntax tree enum].
431 ///
432 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700433 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800434 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800435 ///
436 /// *This type is available if Syn is built with the `"derive"` or
437 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800438 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700439 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800440 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700441 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800442 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800443 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700444 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500445 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700447
David Tolnayed906d12018-01-07 01:20:29 -0800448 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"derive"` or
451 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800452 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700453 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800454 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500455 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700456 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700457
David Tolnayed906d12018-01-07 01:20:29 -0800458 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800459 ///
460 /// *This type is available if Syn is built with the `"derive"` or
461 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800462 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800463 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800464 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800465 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700466 }),
467 }
David Tolnayf8e08832017-01-23 00:04:32 -0800468}
469
David Tolnay86eca752016-09-04 11:26:41 -0700470#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700471pub mod parsing {
472 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700473
David Tolnay63e3dee2017-06-03 20:13:17 -0700474 use synom::Synom;
David Tolnay56080682018-01-06 14:01:52 -0800475 use punctuated::Pair;
Alex Crichton954046c2017-05-30 21:49:42 -0700476
477 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400478 named!(parse -> Self, map!(
479 alt!(
480 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800481 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500482 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400483 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800484 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500485 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400486 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800487 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400488 (lifetimes, ty_params, Some(lt), Some(gt))
489 )
490 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500491 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400492 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700493 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400494 lt_token: lt,
David Tolnay56080682018-01-06 14:01:52 -0800495 params: lifetimes.into_pairs()
496 .map(Pair::into_tuple)
497 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800498 .chain(ty_params.unwrap_or_default()
David Tolnay56080682018-01-06 14:01:52 -0800499 .into_pairs()
500 .map(Pair::into_tuple)
501 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
David Tolnay660fd1f2017-12-31 01:52:57 -0500502 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800503 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500504 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400505 }
Michael Layzell92639a52017-06-01 00:07:44 -0400506 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800507
508 fn description() -> Option<&'static str> {
509 Some("generic parameters in declaration")
510 }
Alex Crichton954046c2017-05-30 21:49:42 -0700511 }
512
David Tolnay36454bb2018-01-07 22:40:02 -0800513 impl Synom for GenericParam {
514 named!(parse -> Self, alt!(
515 syn!(TypeParam) => { GenericParam::Type }
516 |
517 syn!(LifetimeDef) => { GenericParam::Lifetime }
518 |
519 syn!(ConstParam) => { GenericParam::Const }
520 ));
521
522 fn description() -> Option<&'static str> {
523 Some("generic parameter")
524 }
525 }
526
Alex Crichton954046c2017-05-30 21:49:42 -0700527 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400528 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500529 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400530 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800531 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400532 bounds: cond!(
533 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500534 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400535 ) >>
536 (LifetimeDef {
537 attrs: attrs,
538 lifetime: life,
539 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500540 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400541 })
542 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800543
544 fn description() -> Option<&'static str> {
545 Some("lifetime definition")
546 }
Alex Crichton954046c2017-05-30 21:49:42 -0700547 }
548
549 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400550 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800551 for_: keyword!(for) >>
552 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500553 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800554 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400555 (BoundLifetimes {
556 for_token: for_,
557 lt_token: lt,
558 gt_token: gt,
559 lifetimes: lifetimes,
560 })
561 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800562
563 fn description() -> Option<&'static str> {
564 Some("bound lifetimes")
565 }
Alex Crichton954046c2017-05-30 21:49:42 -0700566 }
David Tolnay55337722016-09-11 12:58:56 -0700567
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800568 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400569 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500570 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400571 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800572 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400573 bounds: cond!(
574 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500575 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400576 ) >>
577 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800578 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800579 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400580 (eq, ty)
581 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800582 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400583 attrs: attrs,
584 ident: id,
585 bounds: bounds.unwrap_or_default(),
586 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800587 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400588 default: default.map(|d| d.1),
589 })
590 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800591
592 fn description() -> Option<&'static str> {
593 Some("type parameter")
594 }
Alex Crichton954046c2017-05-30 21:49:42 -0700595 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700596
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800597 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400598 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800599 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400600 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800601 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400602 |
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200603 parens!(syn!(TraitBound)) => {|(parens, mut bound)| {
604 bound.paren_token = Some(parens);
605 TypeParamBound::Trait(bound)
606 }}
Michael Layzell92639a52017-06-01 00:07:44 -0400607 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700608
609 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500610 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700611 }
612 }
613
David Tolnay40fb8ce2018-01-02 10:53:46 -0800614 impl Synom for TraitBound {
615 named!(parse -> Self, do_parse!(
616 modifier: syn!(TraitBoundModifier) >>
617 lifetimes: option!(syn!(BoundLifetimes)) >>
618 mut path: syn!(Path) >>
619 parenthesized: option!(cond_reduce!(
David Tolnay56080682018-01-06 14:01:52 -0800620 path.segments.last().unwrap().value().arguments.is_empty(),
David Tolnay40fb8ce2018-01-02 10:53:46 -0800621 syn!(ParenthesizedGenericArguments)
622 )) >>
623 ({
624 if let Some(parenthesized) = parenthesized {
625 let parenthesized = PathArguments::Parenthesized(parenthesized);
David Tolnay56080682018-01-06 14:01:52 -0800626 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800627 }
628 TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200629 paren_token: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800630 modifier: modifier,
631 lifetimes: lifetimes,
632 path: path,
633 }
634 })
635 ));
636
637 fn description() -> Option<&'static str> {
638 Some("trait bound")
639 }
640 }
641
642 impl Synom for TraitBoundModifier {
643 named!(parse -> Self, alt!(
644 punct!(?) => { TraitBoundModifier::Maybe }
645 |
646 epsilon!() => { |_| TraitBoundModifier::None }
647 ));
648
649 fn description() -> Option<&'static str> {
650 Some("trait bound modifier")
651 }
652 }
653
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500654 impl Synom for ConstParam {
655 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500656 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500657 const_: keyword!(const) >>
658 ident: syn!(Ident) >>
659 colon: punct!(:) >>
660 ty: syn!(Type) >>
661 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800662 ({
663 let (eq_token, default) = match eq_def {
664 Some((eq_token, default)) => (Some(eq_token), Some(default)),
665 None => (None, None),
666 };
667 ConstParam {
668 attrs: attrs,
669 const_token: const_,
670 ident: ident,
671 colon_token: colon,
672 ty: ty,
673 eq_token: eq_token,
674 default: default,
675 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500676 })
677 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800678
679 fn description() -> Option<&'static str> {
680 Some("generic `const` parameter")
681 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500682 }
683
Alex Crichton954046c2017-05-30 21:49:42 -0700684 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500685 named!(parse -> Self, do_parse!(
686 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500687 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500688 (WhereClause {
689 predicates: predicates,
690 where_token: where_,
691 })
Michael Layzell92639a52017-06-01 00:07:44 -0400692 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700693
694 fn description() -> Option<&'static str> {
695 Some("where clause")
696 }
697 }
698
699 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400700 named!(parse -> Self, alt!(
701 do_parse!(
702 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800703 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400704 bounds: cond!(
705 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500706 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400707 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800708 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400709 lifetime: ident,
710 bounds: bounds.unwrap_or_default(),
711 colon_token: colon,
712 }))
713 )
714 |
715 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800716 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800717 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800718 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500719 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800720 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800721 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400722 bounded_ty: bounded_ty,
723 bounds: bounds,
724 colon_token: colon,
725 }))
726 )
727 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800728
729 fn description() -> Option<&'static str> {
730 Some("predicate in where clause")
731 }
Alex Crichton954046c2017-05-30 21:49:42 -0700732 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700733}
David Tolnay87d0b442016-09-04 11:52:12 -0700734
735#[cfg(feature = "printing")]
736mod printing {
737 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700738 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500739 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700740
David Tolnay8ef93042016-09-04 14:08:40 -0700741 impl ToTokens for Generics {
742 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800743 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400744 return;
745 }
746
Alex Crichton259ee532017-07-14 06:51:02 -0700747 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800748
749 // Print lifetimes before types and consts, regardless of their
750 // order in self.params.
751 //
752 // TODO: ordering rules for const parameters vs type parameters have
753 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
754 let mut trailing_or_empty = true;
755 for param in self.params.pairs() {
756 if let GenericParam::Lifetime(_) = **param.value() {
757 param.to_tokens(tokens);
758 trailing_or_empty = param.punct().is_some();
759 }
760 }
761 for param in self.params.pairs() {
762 match **param.value() {
763 GenericParam::Type(_) | GenericParam::Const(_) => {
764 if !trailing_or_empty {
765 <Token![,]>::default().to_tokens(tokens);
766 trailing_or_empty = true;
767 }
768 param.to_tokens(tokens);
769 }
770 GenericParam::Lifetime(_) => {}
771 }
772 }
773
Alex Crichton259ee532017-07-14 06:51:02 -0700774 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700775 }
776 }
777
David Tolnaye7678922016-10-13 20:44:03 -0700778 impl<'a> ToTokens for ImplGenerics<'a> {
779 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800780 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400781 return;
782 }
783
Alex Crichton259ee532017-07-14 06:51:02 -0700784 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800785
786 // Print lifetimes before types and consts, regardless of their
787 // order in self.params.
788 //
789 // TODO: ordering rules for const parameters vs type parameters have
790 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
791 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800792 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800793 if let GenericParam::Lifetime(_) = **param.value() {
794 param.to_tokens(tokens);
795 trailing_or_empty = param.punct().is_some();
796 }
797 }
798 for param in self.0.params.pairs() {
799 if let GenericParam::Lifetime(_) = **param.value() {
800 continue;
801 }
802 if !trailing_or_empty {
803 <Token![,]>::default().to_tokens(tokens);
804 trailing_or_empty = true;
805 }
David Tolnay56080682018-01-06 14:01:52 -0800806 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800807 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800808 GenericParam::Type(ref param) => {
809 // Leave off the type parameter defaults
810 tokens.append_all(param.attrs.outer());
811 param.ident.to_tokens(tokens);
812 if !param.bounds.is_empty() {
813 TokensOrDefault(&param.colon_token).to_tokens(tokens);
814 param.bounds.to_tokens(tokens);
815 }
816 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500817 GenericParam::Const(ref param) => {
818 // Leave off the const parameter defaults
819 tokens.append_all(param.attrs.outer());
820 param.const_token.to_tokens(tokens);
821 param.ident.to_tokens(tokens);
822 param.colon_token.to_tokens(tokens);
823 param.ty.to_tokens(tokens);
824 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400825 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500826 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700827 }
David Tolnay225aca62018-01-11 20:51:46 -0800828
Alex Crichton259ee532017-07-14 06:51:02 -0700829 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700830 }
831 }
832
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800833 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700834 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800835 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400836 return;
837 }
838
Alex Crichton259ee532017-07-14 06:51:02 -0700839 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800840
841 // Print lifetimes before types and consts, regardless of their
842 // order in self.params.
843 //
844 // TODO: ordering rules for const parameters vs type parameters have
845 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
846 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800847 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800848 if let GenericParam::Lifetime(ref def) = **param.value() {
849 // Leave off the lifetime bounds and attributes
850 def.lifetime.to_tokens(tokens);
851 param.punct().to_tokens(tokens);
852 trailing_or_empty = param.punct().is_some();
853 }
854 }
855 for param in self.0.params.pairs() {
856 if let GenericParam::Lifetime(_) = **param.value() {
857 continue;
858 }
859 if !trailing_or_empty {
860 <Token![,]>::default().to_tokens(tokens);
861 trailing_or_empty = true;
862 }
David Tolnay56080682018-01-06 14:01:52 -0800863 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800864 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800865 GenericParam::Type(ref param) => {
866 // Leave off the type parameter defaults
867 param.ident.to_tokens(tokens);
868 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500869 GenericParam::Const(ref param) => {
870 // Leave off the const parameter defaults
871 param.ident.to_tokens(tokens);
872 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800873 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500874 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700875 }
David Tolnay225aca62018-01-11 20:51:46 -0800876
Alex Crichton259ee532017-07-14 06:51:02 -0700877 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700878 }
879 }
880
David Tolnayc879a502017-01-25 15:51:32 -0800881 impl<'a> ToTokens for Turbofish<'a> {
882 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800883 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800884 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800885 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800886 }
887 }
888 }
889
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700890 impl ToTokens for BoundLifetimes {
891 fn to_tokens(&self, tokens: &mut Tokens) {
892 self.for_token.to_tokens(tokens);
893 self.lt_token.to_tokens(tokens);
894 self.lifetimes.to_tokens(tokens);
895 self.gt_token.to_tokens(tokens);
896 }
897 }
898
David Tolnay87d0b442016-09-04 11:52:12 -0700899 impl ToTokens for LifetimeDef {
900 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700901 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700902 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400903 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700904 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400905 self.bounds.to_tokens(tokens);
906 }
David Tolnay87d0b442016-09-04 11:52:12 -0700907 }
908 }
909
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800910 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700911 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700912 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700913 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400914 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700915 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400916 self.bounds.to_tokens(tokens);
917 }
918 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700919 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400920 self.default.to_tokens(tokens);
921 }
David Tolnay8ef93042016-09-04 14:08:40 -0700922 }
923 }
924
David Tolnay40fb8ce2018-01-02 10:53:46 -0800925 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700926 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200927 let to_tokens = |tokens: &mut Tokens| {
928 self.modifier.to_tokens(tokens);
929 self.lifetimes.to_tokens(tokens);
930 self.path.to_tokens(tokens);
931 };
932 match self.paren_token {
933 Some(paren) => paren.surround(tokens, to_tokens),
934 None => to_tokens(tokens),
935 }
David Tolnay55337722016-09-11 12:58:56 -0700936 }
937 }
938
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700939 impl ToTokens for TraitBoundModifier {
940 fn to_tokens(&self, tokens: &mut Tokens) {
941 match *self {
942 TraitBoundModifier::None => {}
943 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
944 }
945 }
946 }
947
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500948 impl ToTokens for ConstParam {
949 fn to_tokens(&self, tokens: &mut Tokens) {
950 tokens.append_all(self.attrs.outer());
951 self.const_token.to_tokens(tokens);
952 self.ident.to_tokens(tokens);
953 self.colon_token.to_tokens(tokens);
954 self.ty.to_tokens(tokens);
955 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800956 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500957 self.default.to_tokens(tokens);
958 }
959 }
960 }
961
David Tolnay55337722016-09-11 12:58:56 -0700962 impl ToTokens for WhereClause {
963 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay2a0b02f2018-03-09 00:50:45 -0800964 if !self.predicates.is_empty() {
965 self.where_token.to_tokens(tokens);
966 self.predicates.to_tokens(tokens);
967 }
David Tolnay87d0b442016-09-04 11:52:12 -0700968 }
969 }
David Tolnay8ef93042016-09-04 14:08:40 -0700970
David Tolnayd4add852018-01-01 20:13:24 -0800971 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700972 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800973 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700974 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700975 self.colon_token.to_tokens(tokens);
976 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700977 }
978 }
979
David Tolnayd4add852018-01-01 20:13:24 -0800980 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700981 fn to_tokens(&self, tokens: &mut Tokens) {
982 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400983 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700984 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400985 self.bounds.to_tokens(tokens);
986 }
David Tolnay8ef93042016-09-04 14:08:40 -0700987 }
988 }
David Tolnayf8e08832017-01-23 00:04:32 -0800989
David Tolnayd4add852018-01-01 20:13:24 -0800990 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -0800991 fn to_tokens(&self, tokens: &mut Tokens) {
992 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700993 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800994 self.rhs_ty.to_tokens(tokens);
995 }
996 }
David Tolnay87d0b442016-09-04 11:52:12 -0700997}