blob: 4c2858de787d22d5ca60e2b0cb8aa1f0532ba643 [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 /// ```
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700310 /// # extern crate proc_macro2;
David Tolnayb153dbc2016-10-04 23:39:10 -0700311 /// # extern crate syn;
312 /// # #[macro_use]
313 /// # extern crate quote;
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700314 /// # use proc_macro2::{Span, Ident};
David Tolnayb153dbc2016-10-04 23:39:10 -0700315 /// # fn main() {
316 /// # let generics: syn::Generics = Default::default();
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700317 /// # let name = Ident::new("MyType", Span::call_site());
David Tolnayb153dbc2016-10-04 23:39:10 -0700318 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
319 /// quote! {
320 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
321 /// // ...
322 /// }
323 /// }
324 /// # ;
325 /// # }
326 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This method is available if Syn is built with the `"derive"` or
329 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500330 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800331 (
332 ImplGenerics(self),
333 TypeGenerics(self),
334 self.where_clause.as_ref(),
335 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700336 }
337}
338
David Tolnaye95cc9f2017-01-25 15:57:09 -0800339#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800340impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800341 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800342 ///
343 /// *This method is available if Syn is built with the `"derive"` or
344 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800345 pub fn as_turbofish(&self) -> Turbofish {
346 Turbofish(self.0)
347 }
348}
349
Alex Crichton62a0a592017-05-22 13:58:53 -0700350ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800351 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800352 ///
353 /// *This type is available if Syn is built with the `"derive"` or `"full"`
354 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700355 #[derive(Default)]
356 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800357 pub for_token: Token![for],
358 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500359 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800360 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700361 }
362}
363
David Tolnayf9505b52016-10-02 09:18:52 -0700364impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700365 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700366 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700367 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700368 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700369 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500370 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700371 }
372 }
373}
374
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800375impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700376 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800377 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700378 attrs: vec![],
379 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700380 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500381 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700382 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700383 default: None,
384 }
385 }
386}
387
David Tolnay40fb8ce2018-01-02 10:53:46 -0800388ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800389 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800390 ///
391 /// *This type is available if Syn is built with the `"derive"` or `"full"`
392 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800393 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800394 pub Trait(TraitBound),
395 pub Lifetime(Lifetime),
396 }
397}
398
399ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800400 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800401 ///
402 /// *This type is available if Syn is built with the `"derive"` or `"full"`
403 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800404 pub struct TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200405 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800406 pub modifier: TraitBoundModifier,
407 /// The `for<'a>` in `for<'a> Foo<&'a T>`
408 pub lifetimes: Option<BoundLifetimes>,
409 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
410 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700411 }
David Tolnay55337722016-09-11 12:58:56 -0700412}
413
Alex Crichton62a0a592017-05-22 13:58:53 -0700414ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800415 /// A modifier on a trait bound, currently only used for the `?` in
416 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800417 ///
418 /// *This type is available if Syn is built with the `"derive"` or `"full"`
419 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700420 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700421 pub enum TraitBoundModifier {
422 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800423 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700424 }
David Tolnay55337722016-09-11 12:58:56 -0700425}
426
Alex Crichton62a0a592017-05-22 13:58:53 -0700427ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800428 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
429 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800430 ///
431 /// *This type is available if Syn is built with the `"derive"` or `"full"`
432 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700433 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500434 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500435 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 }
David Tolnayb79ee962016-09-04 09:39:20 -0700437}
438
Alex Crichton62a0a592017-05-22 13:58:53 -0700439ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800440 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800441 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800442 /// *This type is available if Syn is built with the `"derive"` or `"full"`
443 /// feature.*
444 ///
David Tolnay614a0142018-01-07 10:25:43 -0800445 /// # Syntax tree enum
446 ///
447 /// This type is a [syntax tree enum].
448 ///
449 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700450 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800451 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800452 ///
453 /// *This type is available if Syn is built with the `"derive"` or
454 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800455 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700456 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800457 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700458 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800459 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800460 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700461 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500462 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700463 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700464
David Tolnayed906d12018-01-07 01:20:29 -0800465 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800466 ///
467 /// *This type is available if Syn is built with the `"derive"` or
468 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800469 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800471 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500472 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700473 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700474
David Tolnayed906d12018-01-07 01:20:29 -0800475 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800476 ///
477 /// *This type is available if Syn is built with the `"derive"` or
478 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800479 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800480 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800481 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800482 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700483 }),
484 }
David Tolnayf8e08832017-01-23 00:04:32 -0800485}
486
David Tolnay86eca752016-09-04 11:26:41 -0700487#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700488pub mod parsing {
489 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700490
David Tolnay56080682018-01-06 14:01:52 -0800491 use punctuated::Pair;
David Tolnay94d2b792018-04-29 12:26:10 -0700492 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -0700493
494 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400495 named!(parse -> Self, map!(
496 alt!(
497 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800498 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500499 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400500 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800501 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500502 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400503 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800504 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400505 (lifetimes, ty_params, Some(lt), Some(gt))
506 )
507 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500508 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400509 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700510 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400511 lt_token: lt,
David Tolnay56080682018-01-06 14:01:52 -0800512 params: lifetimes.into_pairs()
513 .map(Pair::into_tuple)
514 .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800515 .chain(ty_params.unwrap_or_default()
David Tolnay56080682018-01-06 14:01:52 -0800516 .into_pairs()
517 .map(Pair::into_tuple)
518 .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
David Tolnay660fd1f2017-12-31 01:52:57 -0500519 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800520 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500521 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400522 }
Michael Layzell92639a52017-06-01 00:07:44 -0400523 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800524
525 fn description() -> Option<&'static str> {
526 Some("generic parameters in declaration")
527 }
Alex Crichton954046c2017-05-30 21:49:42 -0700528 }
529
David Tolnay36454bb2018-01-07 22:40:02 -0800530 impl Synom for GenericParam {
531 named!(parse -> Self, alt!(
532 syn!(TypeParam) => { GenericParam::Type }
533 |
534 syn!(LifetimeDef) => { GenericParam::Lifetime }
535 |
536 syn!(ConstParam) => { GenericParam::Const }
537 ));
538
539 fn description() -> Option<&'static str> {
540 Some("generic parameter")
541 }
542 }
543
Alex Crichton954046c2017-05-30 21:49:42 -0700544 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400545 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500546 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400547 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800548 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400549 bounds: cond!(
550 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500551 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400552 ) >>
553 (LifetimeDef {
554 attrs: attrs,
555 lifetime: life,
556 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500557 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400558 })
559 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800560
561 fn description() -> Option<&'static str> {
562 Some("lifetime definition")
563 }
Alex Crichton954046c2017-05-30 21:49:42 -0700564 }
565
566 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400567 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800568 for_: keyword!(for) >>
569 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500570 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800571 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400572 (BoundLifetimes {
573 for_token: for_,
574 lt_token: lt,
575 gt_token: gt,
576 lifetimes: lifetimes,
577 })
578 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800579
580 fn description() -> Option<&'static str> {
581 Some("bound lifetimes")
582 }
Alex Crichton954046c2017-05-30 21:49:42 -0700583 }
David Tolnay55337722016-09-11 12:58:56 -0700584
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800585 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400586 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500587 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400588 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800589 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400590 bounds: cond!(
591 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500592 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400593 ) >>
594 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800595 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800596 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400597 (eq, ty)
598 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800599 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400600 attrs: attrs,
601 ident: id,
602 bounds: bounds.unwrap_or_default(),
603 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800604 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400605 default: default.map(|d| d.1),
606 })
607 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800608
609 fn description() -> Option<&'static str> {
610 Some("type parameter")
611 }
Alex Crichton954046c2017-05-30 21:49:42 -0700612 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700613
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800614 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400615 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800616 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400617 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800618 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400619 |
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200620 parens!(syn!(TraitBound)) => {|(parens, mut bound)| {
621 bound.paren_token = Some(parens);
622 TypeParamBound::Trait(bound)
623 }}
Michael Layzell92639a52017-06-01 00:07:44 -0400624 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700625
626 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500627 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700628 }
629 }
630
David Tolnay40fb8ce2018-01-02 10:53:46 -0800631 impl Synom for TraitBound {
632 named!(parse -> Self, do_parse!(
633 modifier: syn!(TraitBoundModifier) >>
634 lifetimes: option!(syn!(BoundLifetimes)) >>
635 mut path: syn!(Path) >>
636 parenthesized: option!(cond_reduce!(
David Tolnay56080682018-01-06 14:01:52 -0800637 path.segments.last().unwrap().value().arguments.is_empty(),
David Tolnay40fb8ce2018-01-02 10:53:46 -0800638 syn!(ParenthesizedGenericArguments)
639 )) >>
640 ({
641 if let Some(parenthesized) = parenthesized {
642 let parenthesized = PathArguments::Parenthesized(parenthesized);
David Tolnay56080682018-01-06 14:01:52 -0800643 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800644 }
645 TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200646 paren_token: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800647 modifier: modifier,
648 lifetimes: lifetimes,
649 path: path,
650 }
651 })
652 ));
653
654 fn description() -> Option<&'static str> {
655 Some("trait bound")
656 }
657 }
658
659 impl Synom for TraitBoundModifier {
660 named!(parse -> Self, alt!(
661 punct!(?) => { TraitBoundModifier::Maybe }
662 |
663 epsilon!() => { |_| TraitBoundModifier::None }
664 ));
665
666 fn description() -> Option<&'static str> {
667 Some("trait bound modifier")
668 }
669 }
670
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500671 impl Synom for ConstParam {
672 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500673 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500674 const_: keyword!(const) >>
675 ident: syn!(Ident) >>
676 colon: punct!(:) >>
677 ty: syn!(Type) >>
678 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800679 ({
680 let (eq_token, default) = match eq_def {
681 Some((eq_token, default)) => (Some(eq_token), Some(default)),
682 None => (None, None),
683 };
684 ConstParam {
685 attrs: attrs,
686 const_token: const_,
687 ident: ident,
688 colon_token: colon,
689 ty: ty,
690 eq_token: eq_token,
691 default: default,
692 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500693 })
694 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800695
696 fn description() -> Option<&'static str> {
697 Some("generic `const` parameter")
698 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500699 }
700
Alex Crichton954046c2017-05-30 21:49:42 -0700701 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500702 named!(parse -> Self, do_parse!(
703 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500704 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500705 (WhereClause {
706 predicates: predicates,
707 where_token: where_,
708 })
Michael Layzell92639a52017-06-01 00:07:44 -0400709 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700710
711 fn description() -> Option<&'static str> {
712 Some("where clause")
713 }
714 }
715
716 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400717 named!(parse -> Self, alt!(
718 do_parse!(
719 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800720 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400721 bounds: cond!(
722 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500723 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400724 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800725 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400726 lifetime: ident,
727 bounds: bounds.unwrap_or_default(),
728 colon_token: colon,
729 }))
730 )
731 |
732 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800733 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800734 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800735 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500736 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800737 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800738 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400739 bounded_ty: bounded_ty,
740 bounds: bounds,
741 colon_token: colon,
742 }))
743 )
744 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800745
746 fn description() -> Option<&'static str> {
747 Some("predicate in where clause")
748 }
Alex Crichton954046c2017-05-30 21:49:42 -0700749 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700750}
David Tolnay87d0b442016-09-04 11:52:12 -0700751
752#[cfg(feature = "printing")]
753mod printing {
754 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700755 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700756 use quote::{ToTokens, TokenStreamExt};
757 use proc_macro2::TokenStream;
David Tolnay87d0b442016-09-04 11:52:12 -0700758
David Tolnay8ef93042016-09-04 14:08:40 -0700759 impl ToTokens for Generics {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700760 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800761 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400762 return;
763 }
764
Alex Crichton259ee532017-07-14 06:51:02 -0700765 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800766
767 // Print lifetimes before types and consts, regardless of their
768 // order in self.params.
769 //
770 // TODO: ordering rules for const parameters vs type parameters have
771 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
772 let mut trailing_or_empty = true;
773 for param in self.params.pairs() {
774 if let GenericParam::Lifetime(_) = **param.value() {
775 param.to_tokens(tokens);
776 trailing_or_empty = param.punct().is_some();
777 }
778 }
779 for param in self.params.pairs() {
780 match **param.value() {
781 GenericParam::Type(_) | GenericParam::Const(_) => {
782 if !trailing_or_empty {
783 <Token![,]>::default().to_tokens(tokens);
784 trailing_or_empty = true;
785 }
786 param.to_tokens(tokens);
787 }
788 GenericParam::Lifetime(_) => {}
789 }
790 }
791
Alex Crichton259ee532017-07-14 06:51:02 -0700792 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700793 }
794 }
795
David Tolnaye7678922016-10-13 20:44:03 -0700796 impl<'a> ToTokens for ImplGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700797 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800798 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400799 return;
800 }
801
Alex Crichton259ee532017-07-14 06:51:02 -0700802 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800803
804 // Print lifetimes before types and consts, regardless of their
805 // order in self.params.
806 //
807 // TODO: ordering rules for const parameters vs type parameters have
808 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
809 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800810 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800811 if let GenericParam::Lifetime(_) = **param.value() {
812 param.to_tokens(tokens);
813 trailing_or_empty = param.punct().is_some();
814 }
815 }
816 for param in self.0.params.pairs() {
817 if let GenericParam::Lifetime(_) = **param.value() {
818 continue;
819 }
820 if !trailing_or_empty {
821 <Token![,]>::default().to_tokens(tokens);
822 trailing_or_empty = true;
823 }
David Tolnay56080682018-01-06 14:01:52 -0800824 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800825 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800826 GenericParam::Type(ref param) => {
827 // Leave off the type parameter defaults
828 tokens.append_all(param.attrs.outer());
829 param.ident.to_tokens(tokens);
830 if !param.bounds.is_empty() {
831 TokensOrDefault(&param.colon_token).to_tokens(tokens);
832 param.bounds.to_tokens(tokens);
833 }
834 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500835 GenericParam::Const(ref param) => {
836 // Leave off the const parameter defaults
837 tokens.append_all(param.attrs.outer());
838 param.const_token.to_tokens(tokens);
839 param.ident.to_tokens(tokens);
840 param.colon_token.to_tokens(tokens);
841 param.ty.to_tokens(tokens);
842 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400843 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500844 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700845 }
David Tolnay225aca62018-01-11 20:51:46 -0800846
Alex Crichton259ee532017-07-14 06:51:02 -0700847 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700848 }
849 }
850
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800851 impl<'a> ToTokens for TypeGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700852 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800853 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400854 return;
855 }
856
Alex Crichton259ee532017-07-14 06:51:02 -0700857 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800858
859 // Print lifetimes before types and consts, regardless of their
860 // order in self.params.
861 //
862 // TODO: ordering rules for const parameters vs type parameters have
863 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
864 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800865 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800866 if let GenericParam::Lifetime(ref def) = **param.value() {
867 // Leave off the lifetime bounds and attributes
868 def.lifetime.to_tokens(tokens);
869 param.punct().to_tokens(tokens);
870 trailing_or_empty = param.punct().is_some();
871 }
872 }
873 for param in self.0.params.pairs() {
874 if let GenericParam::Lifetime(_) = **param.value() {
875 continue;
876 }
877 if !trailing_or_empty {
878 <Token![,]>::default().to_tokens(tokens);
879 trailing_or_empty = true;
880 }
David Tolnay56080682018-01-06 14:01:52 -0800881 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800882 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800883 GenericParam::Type(ref param) => {
884 // Leave off the type parameter defaults
885 param.ident.to_tokens(tokens);
886 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500887 GenericParam::Const(ref param) => {
888 // Leave off the const parameter defaults
889 param.ident.to_tokens(tokens);
890 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800891 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500892 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700893 }
David Tolnay225aca62018-01-11 20:51:46 -0800894
Alex Crichton259ee532017-07-14 06:51:02 -0700895 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700896 }
897 }
898
David Tolnayc879a502017-01-25 15:51:32 -0800899 impl<'a> ToTokens for Turbofish<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700900 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800901 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800902 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800903 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800904 }
905 }
906 }
907
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700908 impl ToTokens for BoundLifetimes {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700909 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700910 self.for_token.to_tokens(tokens);
911 self.lt_token.to_tokens(tokens);
912 self.lifetimes.to_tokens(tokens);
913 self.gt_token.to_tokens(tokens);
914 }
915 }
916
David Tolnay87d0b442016-09-04 11:52:12 -0700917 impl ToTokens for LifetimeDef {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700918 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -0700919 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700920 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400921 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700922 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400923 self.bounds.to_tokens(tokens);
924 }
David Tolnay87d0b442016-09-04 11:52:12 -0700925 }
926 }
927
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800928 impl ToTokens for TypeParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700929 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -0700930 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700931 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400932 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700933 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400934 self.bounds.to_tokens(tokens);
935 }
936 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700937 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400938 self.default.to_tokens(tokens);
939 }
David Tolnay8ef93042016-09-04 14:08:40 -0700940 }
941 }
942
David Tolnay40fb8ce2018-01-02 10:53:46 -0800943 impl ToTokens for TraitBound {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700944 fn to_tokens(&self, tokens: &mut TokenStream) {
945 let to_tokens = |tokens: &mut TokenStream| {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200946 self.modifier.to_tokens(tokens);
947 self.lifetimes.to_tokens(tokens);
948 self.path.to_tokens(tokens);
949 };
950 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +0200951 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200952 None => to_tokens(tokens),
953 }
David Tolnay55337722016-09-11 12:58:56 -0700954 }
955 }
956
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700957 impl ToTokens for TraitBoundModifier {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700958 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700959 match *self {
960 TraitBoundModifier::None => {}
961 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
962 }
963 }
964 }
965
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500966 impl ToTokens for ConstParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700967 fn to_tokens(&self, tokens: &mut TokenStream) {
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500968 tokens.append_all(self.attrs.outer());
969 self.const_token.to_tokens(tokens);
970 self.ident.to_tokens(tokens);
971 self.colon_token.to_tokens(tokens);
972 self.ty.to_tokens(tokens);
973 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800974 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500975 self.default.to_tokens(tokens);
976 }
977 }
978 }
979
David Tolnay55337722016-09-11 12:58:56 -0700980 impl ToTokens for WhereClause {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700981 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2a0b02f2018-03-09 00:50:45 -0800982 if !self.predicates.is_empty() {
983 self.where_token.to_tokens(tokens);
984 self.predicates.to_tokens(tokens);
985 }
David Tolnay87d0b442016-09-04 11:52:12 -0700986 }
987 }
David Tolnay8ef93042016-09-04 14:08:40 -0700988
David Tolnayd4add852018-01-01 20:13:24 -0800989 impl ToTokens for PredicateType {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700990 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800991 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700992 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700993 self.colon_token.to_tokens(tokens);
994 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700995 }
996 }
997
David Tolnayd4add852018-01-01 20:13:24 -0800998 impl ToTokens for PredicateLifetime {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700999 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay8ef93042016-09-04 14:08:40 -07001000 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001001 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001002 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001003 self.bounds.to_tokens(tokens);
1004 }
David Tolnay8ef93042016-09-04 14:08:40 -07001005 }
1006 }
David Tolnayf8e08832017-01-23 00:04:32 -08001007
David Tolnayd4add852018-01-01 20:13:24 -08001008 impl ToTokens for PredicateEq {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001009 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8e08832017-01-23 00:04:32 -08001010 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001011 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001012 self.rhs_ty.to_tokens(tokens);
1013 }
1014 }
David Tolnay87d0b442016-09-04 11:52:12 -07001015}