blob: c63cb6906e9677b1b2aa963b4866b23a7cf3a768 [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 {
David Tolnayd228b332018-06-27 23:56:05 -0700152 where_token: <Token![where]>::default(),
David Tolnay7f9954d2018-04-01 16:52:15 +0200153 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> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700169 let next = match self.0.next() {
170 Some(item) => item,
171 None => return None,
172 };
173 if let GenericParam::Type(ref type_param) = *next {
174 Some(type_param)
175 } else {
176 self.next()
177 }
178 }
179}
180
David Tolnay8095c302018-03-31 19:34:17 +0200181pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700182
183impl<'a> Iterator for TypeParamsMut<'a> {
184 type Item = &'a mut TypeParam;
185
186 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700187 let next = match self.0.next() {
188 Some(item) => item,
189 None => return None,
190 };
191 if let GenericParam::Type(ref mut type_param) = *next {
192 Some(type_param)
193 } else {
194 self.next()
195 }
196 }
197}
198
David Tolnay8095c302018-03-31 19:34:17 +0200199pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700200
201impl<'a> Iterator for Lifetimes<'a> {
202 type Item = &'a LifetimeDef;
203
204 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700205 let next = match self.0.next() {
206 Some(item) => item,
207 None => return None,
208 };
209 if let GenericParam::Lifetime(ref lifetime) = *next {
210 Some(lifetime)
211 } else {
212 self.next()
213 }
214 }
215}
216
David Tolnay8095c302018-03-31 19:34:17 +0200217pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700218
219impl<'a> Iterator for LifetimesMut<'a> {
220 type Item = &'a mut LifetimeDef;
221
222 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700223 let next = match self.0.next() {
224 Some(item) => item,
225 None => return None,
226 };
227 if let GenericParam::Lifetime(ref mut lifetime) = *next {
228 Some(lifetime)
229 } else {
230 self.next()
231 }
232 }
233}
234
David Tolnay8095c302018-03-31 19:34:17 +0200235pub struct ConstParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700236
237impl<'a> Iterator for ConstParams<'a> {
238 type Item = &'a ConstParam;
239
240 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700241 let next = match self.0.next() {
242 Some(item) => item,
243 None => return None,
244 };
245 if let GenericParam::Const(ref const_param) = *next {
246 Some(const_param)
247 } else {
248 self.next()
249 }
250 }
251}
252
David Tolnay8095c302018-03-31 19:34:17 +0200253pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700254
255impl<'a> Iterator for ConstParamsMut<'a> {
256 type Item = &'a mut ConstParam;
257
258 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700259 let next = match self.0.next() {
260 Some(item) => item,
261 None => return None,
262 };
263 if let GenericParam::Const(ref mut const_param) = *next {
264 Some(const_param)
265 } else {
266 self.next()
267 }
268 }
269}
270
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))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400278pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700279
David Tolnay461d98e2018-01-07 11:07:19 -0800280/// Returned by `Generics::split_for_impl`.
281///
282/// *This type is available if Syn is built with the `"derive"` or `"full"`
283/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700284#[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))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800287pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700288
David Tolnay461d98e2018-01-07 11:07:19 -0800289/// Returned by `TypeGenerics::as_turbofish`.
290///
291/// *This type is available if Syn is built with the `"derive"` or `"full"`
292/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800293#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400294#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
295#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400296pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800297
David Tolnaye95cc9f2017-01-25 15:57:09 -0800298#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700299impl Generics {
300 /// Split a type's generics into the pieces required for impl'ing a trait
301 /// for that type.
302 ///
303 /// ```
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700304 /// # extern crate proc_macro2;
David Tolnayb153dbc2016-10-04 23:39:10 -0700305 /// # extern crate syn;
David Tolnayb153dbc2016-10-04 23:39:10 -0700306 /// # extern crate quote;
David Tolnay9b00f652018-09-01 10:31:02 -0700307 /// #
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700308 /// # use proc_macro2::{Span, Ident};
David Tolnay9b00f652018-09-01 10:31:02 -0700309 /// # use quote::quote;
310 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700311 /// # fn main() {
David Tolnay9b00f652018-09-01 10:31:02 -0700312 /// # let generics: syn::Generics = Default::default();
313 /// # let name = Ident::new("MyType", Span::call_site());
314 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700315 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
316 /// quote! {
317 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
318 /// // ...
319 /// }
320 /// }
David Tolnay9b00f652018-09-01 10:31:02 -0700321 /// # ;
David Tolnayb153dbc2016-10-04 23:39:10 -0700322 /// # }
323 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800324 ///
325 /// *This method is available if Syn is built with the `"derive"` or
326 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500327 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800328 (
329 ImplGenerics(self),
330 TypeGenerics(self),
331 self.where_clause.as_ref(),
332 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700333 }
334}
335
David Tolnaye95cc9f2017-01-25 15:57:09 -0800336#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800337impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800338 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800339 ///
340 /// *This method is available if Syn is built with the `"derive"` or
341 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800342 pub fn as_turbofish(&self) -> Turbofish {
343 Turbofish(self.0)
344 }
345}
346
Alex Crichton62a0a592017-05-22 13:58:53 -0700347ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800348 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800349 ///
350 /// *This type is available if Syn is built with the `"derive"` or `"full"`
351 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700352 #[derive(Default)]
353 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800354 pub for_token: Token![for],
355 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500356 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800357 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700358 }
359}
360
David Tolnayf9505b52016-10-02 09:18:52 -0700361impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700362 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700363 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700364 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700365 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700366 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500367 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700368 }
369 }
370}
371
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800372impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700373 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800374 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700375 attrs: vec![],
376 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700377 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500378 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700379 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700380 default: None,
381 }
382 }
383}
384
David Tolnay40fb8ce2018-01-02 10:53:46 -0800385ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800386 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"derive"` or `"full"`
389 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800390 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800391 pub Trait(TraitBound),
392 pub Lifetime(Lifetime),
393 }
394}
395
396ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800397 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800398 ///
399 /// *This type is available if Syn is built with the `"derive"` or `"full"`
400 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800401 pub struct TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200402 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800403 pub modifier: TraitBoundModifier,
404 /// The `for<'a>` in `for<'a> Foo<&'a T>`
405 pub lifetimes: Option<BoundLifetimes>,
406 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
407 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700408 }
David Tolnay55337722016-09-11 12:58:56 -0700409}
410
Alex Crichton62a0a592017-05-22 13:58:53 -0700411ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800412 /// A modifier on a trait bound, currently only used for the `?` in
413 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800414 ///
415 /// *This type is available if Syn is built with the `"derive"` or `"full"`
416 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700417 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700418 pub enum TraitBoundModifier {
419 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800420 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700421 }
David Tolnay55337722016-09-11 12:58:56 -0700422}
423
Alex Crichton62a0a592017-05-22 13:58:53 -0700424ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800425 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
426 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800427 ///
428 /// *This type is available if Syn is built with the `"derive"` or `"full"`
429 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700430 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500431 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500432 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700433 }
David Tolnayb79ee962016-09-04 09:39:20 -0700434}
435
Alex Crichton62a0a592017-05-22 13:58:53 -0700436ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800437 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800438 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800439 /// *This type is available if Syn is built with the `"derive"` or `"full"`
440 /// feature.*
441 ///
David Tolnay614a0142018-01-07 10:25:43 -0800442 /// # Syntax tree enum
443 ///
444 /// This type is a [syntax tree enum].
445 ///
446 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700447 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800448 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'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 Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700453 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800454 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700455 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800456 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800457 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700458 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500459 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700460 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700461
David Tolnayed906d12018-01-07 01:20:29 -0800462 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800463 ///
464 /// *This type is available if Syn is built with the `"derive"` or
465 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800466 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700467 pub lifetime: Lifetime,
David Tolnay1b8e2852018-08-26 08:25:18 -0400468 pub colon_token: Token![:],
David Tolnayf2cfd722017-12-31 18:02:51 -0500469 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700471
David Tolnayed906d12018-01-07 01:20:29 -0800472 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800473 ///
474 /// *This type is available if Syn is built with the `"derive"` or
475 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800476 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800477 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800478 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800479 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
481 }
David Tolnayf8e08832017-01-23 00:04:32 -0800482}
483
David Tolnay86eca752016-09-04 11:26:41 -0700484#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700485pub mod parsing {
486 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700487
David Tolnay1b8e2852018-08-26 08:25:18 -0400488 use parse::{Parse, ParseStream, Result};
Alex Crichton954046c2017-05-30 21:49:42 -0700489
David Tolnay1b8e2852018-08-26 08:25:18 -0400490 impl Parse for Generics {
491 fn parse(input: ParseStream) -> Result<Self> {
492 let mut params = Punctuated::new();
493
494 if !input.peek(Token![<]) {
495 return Ok(Generics {
496 lt_token: None,
497 params: params,
498 gt_token: None,
499 where_clause: None,
500 });
Michael Layzell416724e2017-05-24 21:12:34 -0400501 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800502
David Tolnay1b8e2852018-08-26 08:25:18 -0400503 let lt_token: Token![<] = input.parse()?;
Alex Crichton954046c2017-05-30 21:49:42 -0700504
David Tolnay1b8e2852018-08-26 08:25:18 -0400505 let mut has_type_param = false;
506 loop {
507 if input.peek(Token![>]) {
508 break;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800509 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400510
511 let attrs = input.call(Attribute::parse_outer)?;
512 let lookahead = input.lookahead1();
513 if !has_type_param && lookahead.peek(Lifetime) {
514 params.push_value(GenericParam::Lifetime(LifetimeDef {
515 attrs: attrs,
516 ..input.parse()?
517 }));
518 } else if lookahead.peek(Ident) {
519 has_type_param = true;
520 params.push_value(GenericParam::Type(TypeParam {
521 attrs: attrs,
522 ..input.parse()?
523 }));
524 } else {
525 return Err(lookahead.error());
David Tolnay40fb8ce2018-01-02 10:53:46 -0800526 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400527
528 if input.peek(Token![>]) {
529 break;
530 }
531 let punct = input.parse()?;
532 params.push_punct(punct);
533 }
534
535 let gt_token: Token![>] = input.parse()?;
536
537 Ok(Generics {
538 lt_token: Some(lt_token),
539 params: params,
540 gt_token: Some(gt_token),
541 where_clause: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800542 })
David Tolnay40fb8ce2018-01-02 10:53:46 -0800543 }
544 }
545
David Tolnay1b8e2852018-08-26 08:25:18 -0400546 impl Parse for GenericParam {
547 fn parse(input: ParseStream) -> Result<Self> {
548 let attrs = input.call(Attribute::parse_outer)?;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800549
David Tolnay1b8e2852018-08-26 08:25:18 -0400550 let lookahead = input.lookahead1();
551 if lookahead.peek(Ident) {
552 Ok(GenericParam::Type(TypeParam {
David Tolnay78ee5202017-12-04 22:17:54 -0800553 attrs: attrs,
David Tolnay1b8e2852018-08-26 08:25:18 -0400554 ..input.parse()?
555 }))
556 } else if lookahead.peek(Lifetime) {
557 Ok(GenericParam::Lifetime(LifetimeDef {
558 attrs: attrs,
559 ..input.parse()?
560 }))
561 } else if lookahead.peek(Token![const]) {
562 Ok(GenericParam::Const(ConstParam {
563 attrs: attrs,
564 ..input.parse()?
565 }))
566 } else {
567 Err(lookahead.error())
568 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800569 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500570 }
571
David Tolnay1b8e2852018-08-26 08:25:18 -0400572 impl Parse for LifetimeDef {
573 fn parse(input: ParseStream) -> Result<Self> {
574 let has_colon;
575 Ok(LifetimeDef {
576 attrs: input.call(Attribute::parse_outer)?,
577 lifetime: input.parse()?,
578 colon_token: {
579 if input.peek(Token![:]) {
580 has_colon = true;
581 Some(input.parse()?)
582 } else {
583 has_colon = false;
584 None
585 }
586 },
587 bounds: {
588 let mut bounds = Punctuated::new();
589 if has_colon {
590 loop {
591 if input.peek(Token![,]) || input.peek(Token![>]) {
592 break;
593 }
594 let value = input.parse()?;
595 bounds.push_value(value);
596 if !input.peek(Token![+]) {
597 break;
598 }
599 let punct = input.parse()?;
600 bounds.push_punct(punct);
601 }
602 }
603 bounds
604 },
David Tolnayac997dd2017-12-27 23:18:22 -0500605 })
Alex Crichton954046c2017-05-30 21:49:42 -0700606 }
607 }
608
David Tolnay1b8e2852018-08-26 08:25:18 -0400609 impl Parse for BoundLifetimes {
610 fn parse(input: ParseStream) -> Result<Self> {
611 Ok(BoundLifetimes {
612 for_token: input.parse()?,
613 lt_token: input.parse()?,
David Tolnayf5ebc192018-08-30 18:23:46 -0700614 lifetimes: {
615 let mut lifetimes = Punctuated::new();
616 while !input.peek(Token![>]) {
617 lifetimes.push_value(input.parse()?);
618 if input.peek(Token![>]) {
619 break;
620 }
621 lifetimes.push_punct(input.parse()?);
622 }
623 lifetimes
624 },
David Tolnay1b8e2852018-08-26 08:25:18 -0400625 gt_token: input.parse()?,
626 })
627 }
628 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800629
David Tolnay1b8e2852018-08-26 08:25:18 -0400630 impl Parse for Option<BoundLifetimes> {
631 fn parse(input: ParseStream) -> Result<Self> {
632 if input.peek(Token![for]) {
633 input.parse().map(Some)
634 } else {
635 Ok(None)
636 }
637 }
638 }
639
640 impl Parse for TypeParam {
641 fn parse(input: ParseStream) -> Result<Self> {
642 let has_colon;
643 let has_default;
644 Ok(TypeParam {
645 attrs: input.call(Attribute::parse_outer)?,
646 ident: input.parse()?,
647 colon_token: {
648 if input.peek(Token![:]) {
649 has_colon = true;
650 Some(input.parse()?)
651 } else {
652 has_colon = false;
653 None
654 }
655 },
656 bounds: {
657 let mut bounds = Punctuated::new();
658 if has_colon {
659 loop {
660 if input.peek(Token![,]) || input.peek(Token![>]) {
661 break;
662 }
663 let value = input.parse()?;
664 bounds.push_value(value);
665 if !input.peek(Token![+]) {
666 break;
667 }
668 let punct = input.parse()?;
669 bounds.push_punct(punct);
670 }
671 }
672 bounds
673 },
674 eq_token: {
675 if input.peek(Token![=]) {
676 has_default = true;
677 Some(input.parse()?)
678 } else {
679 has_default = false;
680 None
681 }
682 },
683 default: {
684 if has_default {
David Tolnaya7d69fc2018-08-26 13:30:24 -0400685 Some(input.parse()?)
David Tolnay1b8e2852018-08-26 08:25:18 -0400686 } else {
687 None
688 }
689 },
690 })
691 }
692 }
693
694 impl Parse for TypeParamBound {
695 fn parse(input: ParseStream) -> Result<Self> {
696 if input.peek(Lifetime) {
697 return input.parse().map(TypeParamBound::Lifetime);
698 }
699
700 if input.peek(token::Paren) {
701 let content;
702 let paren_token = parenthesized!(content in input);
703 let mut bound: TraitBound = content.parse()?;
704 bound.paren_token = Some(paren_token);
705 return Ok(TypeParamBound::Trait(bound));
706 }
707
708 input.parse().map(TypeParamBound::Trait)
709 }
710 }
711
712 impl Parse for TraitBound {
713 fn parse(input: ParseStream) -> Result<Self> {
714 let modifier: TraitBoundModifier = input.parse()?;
715 let lifetimes: Option<BoundLifetimes> = input.parse()?;
716
717 let mut path: Path = input.parse()?;
718 if path.segments.last().unwrap().value().arguments.is_empty()
719 && input.peek(token::Paren)
720 {
721 let parenthesized = PathArguments::Parenthesized(input.parse()?);
722 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
723 }
724
725 Ok(TraitBound {
726 paren_token: None,
727 modifier: modifier,
728 lifetimes: lifetimes,
729 path: path,
730 })
731 }
732 }
733
734 impl Parse for TraitBoundModifier {
735 fn parse(input: ParseStream) -> Result<Self> {
736 if input.peek(Token![?]) {
737 input.parse().map(TraitBoundModifier::Maybe)
738 } else {
739 Ok(TraitBoundModifier::None)
740 }
741 }
742 }
743
744 impl Parse for ConstParam {
745 fn parse(input: ParseStream) -> Result<Self> {
746 let mut default = None;
747 Ok(ConstParam {
748 attrs: input.call(Attribute::parse_outer)?,
749 const_token: input.parse()?,
750 ident: input.parse()?,
751 colon_token: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400752 ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400753 eq_token: {
754 if input.peek(Token![=]) {
755 let eq_token = input.parse()?;
David Tolnay9389c382018-08-27 09:13:37 -0700756 default = Some(input.parse::<Expr>()?);
David Tolnay1b8e2852018-08-26 08:25:18 -0400757 Some(eq_token)
758 } else {
759 None
760 }
761 },
762 default: default,
763 })
764 }
765 }
766
767 impl Parse for WhereClause {
768 fn parse(input: ParseStream) -> Result<Self> {
769 Ok(WhereClause {
770 where_token: input.parse()?,
771 predicates: {
772 let mut predicates = Punctuated::new();
773 loop {
David Tolnay38012de2018-09-02 13:32:47 -0700774 if input.is_empty()
775 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400776 || input.peek(Token![,])
777 || input.peek(Token![;])
778 || input.peek(Token![:]) && !input.peek(Token![::])
779 || input.peek(Token![=])
780 {
781 break;
782 }
783 let value = input.parse()?;
784 predicates.push_value(value);
785 if !input.peek(Token![,]) {
786 break;
787 }
788 let punct = input.parse()?;
789 predicates.push_punct(punct);
790 }
791 predicates
792 },
793 })
794 }
795 }
796
797 impl Parse for Option<WhereClause> {
798 fn parse(input: ParseStream) -> Result<Self> {
799 if input.peek(Token![where]) {
800 input.parse().map(Some)
801 } else {
802 Ok(None)
803 }
804 }
805 }
806
807 impl Parse for WherePredicate {
808 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay66cb0c42018-08-31 09:01:30 -0700809 if input.peek(Lifetime) && input.peek2(Token![:]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400810 Ok(WherePredicate::Lifetime(PredicateLifetime {
811 lifetime: input.parse()?,
812 colon_token: input.parse()?,
813 bounds: {
814 let mut bounds = Punctuated::new();
815 loop {
816 if input.peek(token::Brace)
817 || input.peek(Token![,])
818 || input.peek(Token![;])
819 || input.peek(Token![:])
820 || input.peek(Token![=])
821 {
822 break;
823 }
824 let value = input.parse()?;
825 bounds.push_value(value);
826 if !input.peek(Token![+]) {
827 break;
828 }
829 let punct = input.parse()?;
830 bounds.push_punct(punct);
831 }
832 bounds
833 },
834 }))
835 } else {
836 Ok(WherePredicate::Type(PredicateType {
837 lifetimes: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400838 bounded_ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400839 colon_token: input.parse()?,
840 bounds: {
841 let mut bounds = Punctuated::new();
842 loop {
843 if input.peek(token::Brace)
844 || input.peek(Token![,])
845 || input.peek(Token![;])
846 || input.peek(Token![:]) && !input.peek(Token![::])
847 || input.peek(Token![=])
848 {
849 break;
850 }
851 let value = input.parse()?;
852 bounds.push_value(value);
853 if !input.peek(Token![+]) {
854 break;
855 }
856 let punct = input.parse()?;
857 bounds.push_punct(punct);
858 }
859 bounds
860 },
861 }))
862 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800863 }
Alex Crichton954046c2017-05-30 21:49:42 -0700864 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700865}
David Tolnay87d0b442016-09-04 11:52:12 -0700866
867#[cfg(feature = "printing")]
868mod printing {
869 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700870
Alex Crichtona74a1c82018-05-16 10:20:44 -0700871 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700872 use quote::{ToTokens, TokenStreamExt};
David Tolnay87d0b442016-09-04 11:52:12 -0700873
David Tolnay64023912018-08-31 09:51:12 -0700874 use attr::FilterAttrs;
875 use print::TokensOrDefault;
876
David Tolnay8ef93042016-09-04 14:08:40 -0700877 impl ToTokens for Generics {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700878 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800879 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400880 return;
881 }
882
Alex Crichton259ee532017-07-14 06:51:02 -0700883 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800884
885 // Print lifetimes before types and consts, regardless of their
886 // order in self.params.
887 //
888 // TODO: ordering rules for const parameters vs type parameters have
889 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
890 let mut trailing_or_empty = true;
891 for param in self.params.pairs() {
892 if let GenericParam::Lifetime(_) = **param.value() {
893 param.to_tokens(tokens);
894 trailing_or_empty = param.punct().is_some();
895 }
896 }
897 for param in self.params.pairs() {
898 match **param.value() {
899 GenericParam::Type(_) | GenericParam::Const(_) => {
900 if !trailing_or_empty {
901 <Token![,]>::default().to_tokens(tokens);
902 trailing_or_empty = true;
903 }
904 param.to_tokens(tokens);
905 }
906 GenericParam::Lifetime(_) => {}
907 }
908 }
909
Alex Crichton259ee532017-07-14 06:51:02 -0700910 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700911 }
912 }
913
David Tolnaye7678922016-10-13 20:44:03 -0700914 impl<'a> ToTokens for ImplGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700915 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800916 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400917 return;
918 }
919
Alex Crichton259ee532017-07-14 06:51:02 -0700920 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800921
922 // Print lifetimes before types and consts, regardless of their
923 // order in self.params.
924 //
925 // TODO: ordering rules for const parameters vs type parameters have
926 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
927 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800928 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800929 if let GenericParam::Lifetime(_) = **param.value() {
930 param.to_tokens(tokens);
931 trailing_or_empty = param.punct().is_some();
932 }
933 }
934 for param in self.0.params.pairs() {
935 if let GenericParam::Lifetime(_) = **param.value() {
936 continue;
937 }
938 if !trailing_or_empty {
939 <Token![,]>::default().to_tokens(tokens);
940 trailing_or_empty = true;
941 }
David Tolnay56080682018-01-06 14:01:52 -0800942 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800943 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800944 GenericParam::Type(ref param) => {
945 // Leave off the type parameter defaults
946 tokens.append_all(param.attrs.outer());
947 param.ident.to_tokens(tokens);
948 if !param.bounds.is_empty() {
949 TokensOrDefault(&param.colon_token).to_tokens(tokens);
950 param.bounds.to_tokens(tokens);
951 }
952 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500953 GenericParam::Const(ref param) => {
954 // Leave off the const parameter defaults
955 tokens.append_all(param.attrs.outer());
956 param.const_token.to_tokens(tokens);
957 param.ident.to_tokens(tokens);
958 param.colon_token.to_tokens(tokens);
959 param.ty.to_tokens(tokens);
960 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400961 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500962 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700963 }
David Tolnay225aca62018-01-11 20:51:46 -0800964
Alex Crichton259ee532017-07-14 06:51:02 -0700965 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700966 }
967 }
968
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800969 impl<'a> ToTokens for TypeGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700970 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800971 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400972 return;
973 }
974
Alex Crichton259ee532017-07-14 06:51:02 -0700975 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800976
977 // Print lifetimes before types and consts, regardless of their
978 // order in self.params.
979 //
980 // TODO: ordering rules for const parameters vs type parameters have
981 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
982 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800983 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800984 if let GenericParam::Lifetime(ref def) = **param.value() {
985 // Leave off the lifetime bounds and attributes
986 def.lifetime.to_tokens(tokens);
987 param.punct().to_tokens(tokens);
988 trailing_or_empty = param.punct().is_some();
989 }
990 }
991 for param in self.0.params.pairs() {
992 if let GenericParam::Lifetime(_) = **param.value() {
993 continue;
994 }
995 if !trailing_or_empty {
996 <Token![,]>::default().to_tokens(tokens);
997 trailing_or_empty = true;
998 }
David Tolnay56080682018-01-06 14:01:52 -0800999 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -08001000 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -08001001 GenericParam::Type(ref param) => {
1002 // Leave off the type parameter defaults
1003 param.ident.to_tokens(tokens);
1004 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001005 GenericParam::Const(ref param) => {
1006 // Leave off the const parameter defaults
1007 param.ident.to_tokens(tokens);
1008 }
David Tolnayc2f1aba2017-11-12 20:29:22 -08001009 }
David Tolnayf2cfd722017-12-31 18:02:51 -05001010 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001011 }
David Tolnay225aca62018-01-11 20:51:46 -08001012
Alex Crichton259ee532017-07-14 06:51:02 -07001013 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -07001014 }
1015 }
1016
David Tolnayc879a502017-01-25 15:51:32 -08001017 impl<'a> ToTokens for Turbofish<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001018 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -08001019 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08001020 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001021 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -08001022 }
1023 }
1024 }
1025
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001026 impl ToTokens for BoundLifetimes {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001027 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001028 self.for_token.to_tokens(tokens);
1029 self.lt_token.to_tokens(tokens);
1030 self.lifetimes.to_tokens(tokens);
1031 self.gt_token.to_tokens(tokens);
1032 }
1033 }
1034
David Tolnay87d0b442016-09-04 11:52:12 -07001035 impl ToTokens for LifetimeDef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001036 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001037 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -07001038 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001039 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001040 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001041 self.bounds.to_tokens(tokens);
1042 }
David Tolnay87d0b442016-09-04 11:52:12 -07001043 }
1044 }
1045
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001046 impl ToTokens for TypeParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001047 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001048 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -07001049 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001050 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001051 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001052 self.bounds.to_tokens(tokens);
1053 }
1054 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07001055 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001056 self.default.to_tokens(tokens);
1057 }
David Tolnay8ef93042016-09-04 14:08:40 -07001058 }
1059 }
1060
David Tolnay40fb8ce2018-01-02 10:53:46 -08001061 impl ToTokens for TraitBound {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001062 fn to_tokens(&self, tokens: &mut TokenStream) {
1063 let to_tokens = |tokens: &mut TokenStream| {
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001064 self.modifier.to_tokens(tokens);
1065 self.lifetimes.to_tokens(tokens);
1066 self.path.to_tokens(tokens);
1067 };
1068 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +02001069 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001070 None => to_tokens(tokens),
1071 }
David Tolnay55337722016-09-11 12:58:56 -07001072 }
1073 }
1074
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001075 impl ToTokens for TraitBoundModifier {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001076 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001077 match *self {
1078 TraitBoundModifier::None => {}
1079 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
1080 }
1081 }
1082 }
1083
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001084 impl ToTokens for ConstParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001085 fn to_tokens(&self, tokens: &mut TokenStream) {
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001086 tokens.append_all(self.attrs.outer());
1087 self.const_token.to_tokens(tokens);
1088 self.ident.to_tokens(tokens);
1089 self.colon_token.to_tokens(tokens);
1090 self.ty.to_tokens(tokens);
1091 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -08001092 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001093 self.default.to_tokens(tokens);
1094 }
1095 }
1096 }
1097
David Tolnay55337722016-09-11 12:58:56 -07001098 impl ToTokens for WhereClause {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001099 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2a0b02f2018-03-09 00:50:45 -08001100 if !self.predicates.is_empty() {
1101 self.where_token.to_tokens(tokens);
1102 self.predicates.to_tokens(tokens);
1103 }
David Tolnay87d0b442016-09-04 11:52:12 -07001104 }
1105 }
David Tolnay8ef93042016-09-04 14:08:40 -07001106
David Tolnayd4add852018-01-01 20:13:24 -08001107 impl ToTokens for PredicateType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001108 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay40fb8ce2018-01-02 10:53:46 -08001109 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001110 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001111 self.colon_token.to_tokens(tokens);
1112 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001113 }
1114 }
1115
David Tolnayd4add852018-01-01 20:13:24 -08001116 impl ToTokens for PredicateLifetime {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001117 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay8ef93042016-09-04 14:08:40 -07001118 self.lifetime.to_tokens(tokens);
David Tolnay1b8e2852018-08-26 08:25:18 -04001119 self.colon_token.to_tokens(tokens);
1120 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001121 }
1122 }
David Tolnayf8e08832017-01-23 00:04:32 -08001123
David Tolnayd4add852018-01-01 20:13:24 -08001124 impl ToTokens for PredicateEq {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001125 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8e08832017-01-23 00:04:32 -08001126 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001127 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001128 self.rhs_ty.to_tokens(tokens);
1129 }
1130 }
David Tolnay87d0b442016-09-04 11:52:12 -07001131}