blob: d9d652dfc704ad7bbed80cebaf48204ca556360d [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
Sean Griffin8fcca802018-01-15 15:45:41 -07002use punctuated::{Iter, IterMut, Punctuated};
David Tolnayb79ee962016-09-04 09:39:20 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -08005 /// Lifetimes and type parameters attached to a declaration of a function,
6 /// enum, trait, etc.
David Tolnay461d98e2018-01-07 11:07:19 -08007 ///
8 /// *This type is available if Syn is built with the `"derive"` or `"full"`
9 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -070010 #[derive(Default)]
11 pub struct Generics {
David Tolnayf8db7ba2017-11-11 22:52:16 -080012 pub lt_token: Option<Token![<]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050013 pub params: Punctuated<GenericParam, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080014 pub gt_token: Option<Token![>]>,
David Tolnayac997dd2017-12-27 23:18:22 -050015 pub where_clause: Option<WhereClause>,
Alex Crichton62a0a592017-05-22 13:58:53 -070016 }
David Tolnayb79ee962016-09-04 09:39:20 -070017}
18
David Tolnayc2f1aba2017-11-12 20:29:22 -080019ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -080020 /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
21 /// `'a: 'b`, `const LEN: usize`.
David Tolnay614a0142018-01-07 10:25:43 -080022 ///
David Tolnay461d98e2018-01-07 11:07:19 -080023 /// *This type is available if Syn is built with the `"derive"` or `"full"`
24 /// feature.*
25 ///
David Tolnay614a0142018-01-07 10:25:43 -080026 /// # Syntax tree enum
27 ///
28 /// This type is a [syntax tree enum].
29 ///
30 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnayb8dec882019-07-20 09:46:14 -070031 //
32 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
33 // blocked on https://github.com/rust-lang/rust/issues/62833
David Tolnayc2f1aba2017-11-12 20:29:22 -080034 pub enum GenericParam {
David Tolnayed906d12018-01-07 01:20:29 -080035 /// A generic type parameter: `T: Into<String>`.
David Tolnay461d98e2018-01-07 11:07:19 -080036 ///
37 /// *This type is available if Syn is built with the `"derive"` or
38 /// `"full"` feature.*
David Tolnayc2f1aba2017-11-12 20:29:22 -080039 pub Type(TypeParam {
40 pub attrs: Vec<Attribute>,
41 pub ident: Ident,
42 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050043 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080044 pub eq_token: Option<Token![=]>,
45 pub default: Option<Type>,
46 }),
David Tolnayed906d12018-01-07 01:20:29 -080047
48 /// A lifetime definition: `'a: 'b + 'c + 'd`.
David Tolnay461d98e2018-01-07 11:07:19 -080049 ///
50 /// *This type is available if Syn is built with the `"derive"` or
51 /// `"full"` feature.*
David Tolnay517f3692018-01-01 20:17:23 -080052 pub Lifetime(LifetimeDef {
53 pub attrs: Vec<Attribute>,
54 pub lifetime: Lifetime,
55 pub colon_token: Option<Token![:]>,
56 pub bounds: Punctuated<Lifetime, Token![+]>,
57 }),
David Tolnayed906d12018-01-07 01:20:29 -080058
59 /// A const generic parameter: `const LENGTH: usize`.
David Tolnay461d98e2018-01-07 11:07:19 -080060 ///
61 /// *This type is available if Syn is built with the `"derive"` or
62 /// `"full"` feature.*
Nika Layzellf1fdc0b2017-12-04 19:58:32 -050063 pub Const(ConstParam {
64 pub attrs: Vec<Attribute>,
65 pub const_token: Token![const],
66 pub ident: Ident,
67 pub colon_token: Token![:],
68 pub ty: Type,
69 pub eq_token: Option<Token![=]>,
70 pub default: Option<Expr>,
71 }),
David Tolnayc2f1aba2017-11-12 20:29:22 -080072 }
73}
74
Sean Griffin8fcca802018-01-15 15:45:41 -070075impl Generics {
David Tolnayef5199b2018-01-17 10:56:03 -080076 /// Returns an
77 /// <code
78 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
79 /// href="struct.TypeParam.html"><code
80 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
81 /// style="padding-left:0;">&gt;</code>
82 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070083 pub fn type_params(&self) -> TypeParams {
84 TypeParams(self.params.iter())
85 }
86
David Tolnayef5199b2018-01-17 10:56:03 -080087 /// Returns an
88 /// <code
89 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
90 /// href="struct.TypeParam.html"><code
91 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
92 /// style="padding-left:0;">&gt;</code>
93 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070094 pub fn type_params_mut(&mut self) -> TypeParamsMut {
95 TypeParamsMut(self.params.iter_mut())
96 }
97
David Tolnayef5199b2018-01-17 10:56:03 -080098 /// Returns an
99 /// <code
100 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
101 /// href="struct.LifetimeDef.html"><code
102 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
103 /// style="padding-left:0;">&gt;</code>
104 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700105 pub fn lifetimes(&self) -> Lifetimes {
106 Lifetimes(self.params.iter())
107 }
108
David Tolnayef5199b2018-01-17 10:56:03 -0800109 /// Returns an
110 /// <code
111 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
112 /// href="struct.LifetimeDef.html"><code
113 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
114 /// style="padding-left:0;">&gt;</code>
115 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700116 pub fn lifetimes_mut(&mut self) -> LifetimesMut {
117 LifetimesMut(self.params.iter_mut())
118 }
119
David Tolnayef5199b2018-01-17 10:56:03 -0800120 /// Returns an
121 /// <code
122 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
123 /// href="struct.ConstParam.html"><code
124 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
125 /// style="padding-left:0;">&gt;</code>
126 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700127 pub fn const_params(&self) -> ConstParams {
128 ConstParams(self.params.iter())
129 }
130
David Tolnayef5199b2018-01-17 10:56:03 -0800131 /// Returns an
132 /// <code
133 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
134 /// href="struct.ConstParam.html"><code
135 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
136 /// style="padding-left:0;">&gt;</code>
137 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700138 pub fn const_params_mut(&mut self) -> ConstParamsMut {
139 ConstParamsMut(self.params.iter_mut())
140 }
David Tolnay7f9954d2018-04-01 16:52:15 +0200141
142 /// Initializes an empty `where`-clause if there is not one present already.
143 pub fn make_where_clause(&mut self) -> &mut WhereClause {
144 // This is Option::get_or_insert_with in Rust 1.20.
145 if self.where_clause.is_none() {
146 self.where_clause = Some(WhereClause {
David Tolnayd228b332018-06-27 23:56:05 -0700147 where_token: <Token![where]>::default(),
David Tolnay7f9954d2018-04-01 16:52:15 +0200148 predicates: Punctuated::new(),
149 });
150 }
151 match self.where_clause {
152 Some(ref mut where_clause) => where_clause,
153 None => unreachable!(),
154 }
155 }
Sean Griffin8fcca802018-01-15 15:45:41 -0700156}
157
David Tolnay8095c302018-03-31 19:34:17 +0200158pub struct TypeParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700159
160impl<'a> Iterator for TypeParams<'a> {
161 type Item = &'a TypeParam;
162
163 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700164 let next = match self.0.next() {
165 Some(item) => item,
166 None => return None,
167 };
168 if let GenericParam::Type(ref type_param) = *next {
169 Some(type_param)
170 } else {
171 self.next()
172 }
173 }
174}
175
David Tolnay8095c302018-03-31 19:34:17 +0200176pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700177
178impl<'a> Iterator for TypeParamsMut<'a> {
179 type Item = &'a mut TypeParam;
180
181 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700182 let next = match self.0.next() {
183 Some(item) => item,
184 None => return None,
185 };
186 if let GenericParam::Type(ref mut type_param) = *next {
187 Some(type_param)
188 } else {
189 self.next()
190 }
191 }
192}
193
David Tolnay8095c302018-03-31 19:34:17 +0200194pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700195
196impl<'a> Iterator for Lifetimes<'a> {
197 type Item = &'a LifetimeDef;
198
199 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700200 let next = match self.0.next() {
201 Some(item) => item,
202 None => return None,
203 };
204 if let GenericParam::Lifetime(ref lifetime) = *next {
205 Some(lifetime)
206 } else {
207 self.next()
208 }
209 }
210}
211
David Tolnay8095c302018-03-31 19:34:17 +0200212pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700213
214impl<'a> Iterator for LifetimesMut<'a> {
215 type Item = &'a mut LifetimeDef;
216
217 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700218 let next = match self.0.next() {
219 Some(item) => item,
220 None => return None,
221 };
222 if let GenericParam::Lifetime(ref mut lifetime) = *next {
223 Some(lifetime)
224 } else {
225 self.next()
226 }
227 }
228}
229
David Tolnay8095c302018-03-31 19:34:17 +0200230pub struct ConstParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700231
232impl<'a> Iterator for ConstParams<'a> {
233 type Item = &'a ConstParam;
234
235 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700236 let next = match self.0.next() {
237 Some(item) => item,
238 None => return None,
239 };
240 if let GenericParam::Const(ref const_param) = *next {
241 Some(const_param)
242 } else {
243 self.next()
244 }
245 }
246}
247
David Tolnay8095c302018-03-31 19:34:17 +0200248pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700249
250impl<'a> Iterator for ConstParamsMut<'a> {
251 type Item = &'a mut ConstParam;
252
253 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700254 let next = match self.0.next() {
255 Some(item) => item,
256 None => return None,
257 };
258 if let GenericParam::Const(ref mut const_param) = *next {
259 Some(const_param)
260 } else {
261 self.next()
262 }
263 }
264}
265
David Tolnay461d98e2018-01-07 11:07:19 -0800266/// Returned by `Generics::split_for_impl`.
267///
268/// *This type is available if Syn is built with the `"derive"` or `"full"`
269/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700270#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400271#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
272#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400273pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700274
David Tolnay461d98e2018-01-07 11:07:19 -0800275/// Returned by `Generics::split_for_impl`.
276///
277/// *This type is available if Syn is built with the `"derive"` or `"full"`
278/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700279#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400280#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
281#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800282pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700283
David Tolnay461d98e2018-01-07 11:07:19 -0800284/// Returned by `TypeGenerics::as_turbofish`.
285///
286/// *This type is available if Syn is built with the `"derive"` or `"full"`
287/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800288#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400289#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
290#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400291pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800292
David Tolnaye95cc9f2017-01-25 15:57:09 -0800293#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700294impl Generics {
295 /// Split a type's generics into the pieces required for impl'ing a trait
296 /// for that type.
297 ///
David Tolnay95989db2019-01-01 15:05:57 -0500298 /// ```edition2018
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700299 /// # use proc_macro2::{Span, Ident};
David Tolnayfd5b1172018-12-31 17:54:36 -0500300 /// # use quote::quote;
David Tolnay9b00f652018-09-01 10:31:02 -0700301 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700302 /// # fn main() {
David Tolnay9b00f652018-09-01 10:31:02 -0700303 /// # let generics: syn::Generics = Default::default();
304 /// # let name = Ident::new("MyType", Span::call_site());
305 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700306 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
307 /// quote! {
308 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
309 /// // ...
310 /// }
311 /// }
David Tolnay9b00f652018-09-01 10:31:02 -0700312 /// # ;
David Tolnayb153dbc2016-10-04 23:39:10 -0700313 /// # }
314 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800315 ///
316 /// *This method is available if Syn is built with the `"derive"` or
317 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500318 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800319 (
320 ImplGenerics(self),
321 TypeGenerics(self),
322 self.where_clause.as_ref(),
323 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700324 }
325}
326
David Tolnaye95cc9f2017-01-25 15:57:09 -0800327#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800328impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800329 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800330 ///
331 /// *This method is available if Syn is built with the `"derive"` or
332 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800333 pub fn as_turbofish(&self) -> Turbofish {
334 Turbofish(self.0)
335 }
336}
337
Alex Crichton62a0a592017-05-22 13:58:53 -0700338ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800339 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800340 ///
341 /// *This type is available if Syn is built with the `"derive"` or `"full"`
342 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700343 #[derive(Default)]
344 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800345 pub for_token: Token![for],
346 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500347 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800348 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700349 }
350}
351
David Tolnayf9505b52016-10-02 09:18:52 -0700352impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700353 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700354 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700355 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700356 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700357 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500358 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700359 }
360 }
361}
362
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800363impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700364 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800365 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700366 attrs: vec![],
367 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700368 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500369 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700370 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700371 default: None,
372 }
373 }
374}
375
David Tolnay40fb8ce2018-01-02 10:53:46 -0800376ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800377 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800378 ///
379 /// *This type is available if Syn is built with the `"derive"` or `"full"`
380 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800381 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800382 pub Trait(TraitBound),
383 pub Lifetime(Lifetime),
384 }
385}
386
387ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800388 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800389 ///
390 /// *This type is available if Syn is built with the `"derive"` or `"full"`
391 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800392 pub struct TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200393 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800394 pub modifier: TraitBoundModifier,
395 /// The `for<'a>` in `for<'a> Foo<&'a T>`
396 pub lifetimes: Option<BoundLifetimes>,
397 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
398 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700399 }
David Tolnay55337722016-09-11 12:58:56 -0700400}
401
Alex Crichton62a0a592017-05-22 13:58:53 -0700402ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800403 /// A modifier on a trait bound, currently only used for the `?` in
404 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800405 ///
406 /// *This type is available if Syn is built with the `"derive"` or `"full"`
407 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700408 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700409 pub enum TraitBoundModifier {
410 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800411 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700412 }
David Tolnay55337722016-09-11 12:58:56 -0700413}
414
Alex Crichton62a0a592017-05-22 13:58:53 -0700415ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800416 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
417 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800418 ///
419 /// *This type is available if Syn is built with the `"derive"` or `"full"`
420 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700421 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500422 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500423 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700424 }
David Tolnayb79ee962016-09-04 09:39:20 -0700425}
426
Alex Crichton62a0a592017-05-22 13:58:53 -0700427ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800428 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800429 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800430 /// *This type is available if Syn is built with the `"derive"` or `"full"`
431 /// feature.*
432 ///
David Tolnay614a0142018-01-07 10:25:43 -0800433 /// # Syntax tree enum
434 ///
435 /// This type is a [syntax tree enum].
436 ///
437 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
David Tolnayb8dec882019-07-20 09:46:14 -0700438 //
439 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
440 // blocked on https://github.com/rust-lang/rust/issues/62833
Alex Crichton62a0a592017-05-22 13:58:53 -0700441 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800442 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800443 ///
444 /// *This type is available if Syn is built with the `"derive"` or
445 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800446 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700447 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800448 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700449 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800450 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800451 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700452 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500453 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700454 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700455
David Tolnayed906d12018-01-07 01:20:29 -0800456 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800457 ///
458 /// *This type is available if Syn is built with the `"derive"` or
459 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800460 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700461 pub lifetime: Lifetime,
David Tolnay1b8e2852018-08-26 08:25:18 -0400462 pub colon_token: Token![:],
David Tolnayf2cfd722017-12-31 18:02:51 -0500463 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700465
David Tolnayed906d12018-01-07 01:20:29 -0800466 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800467 ///
468 /// *This type is available if Syn is built with the `"derive"` or
469 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800470 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800471 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800472 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800473 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700474 }),
475 }
David Tolnayf8e08832017-01-23 00:04:32 -0800476}
477
David Tolnay86eca752016-09-04 11:26:41 -0700478#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700479pub mod parsing {
480 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700481
David Tolnay1b8e2852018-08-26 08:25:18 -0400482 use parse::{Parse, ParseStream, Result};
Alex Crichton954046c2017-05-30 21:49:42 -0700483
David Tolnay1b8e2852018-08-26 08:25:18 -0400484 impl Parse for Generics {
485 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay1b8e2852018-08-26 08:25:18 -0400486 if !input.peek(Token![<]) {
David Tolnay3c29f6e2018-10-27 22:47:48 -0700487 return Ok(Generics::default());
Michael Layzell416724e2017-05-24 21:12:34 -0400488 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800489
David Tolnay1b8e2852018-08-26 08:25:18 -0400490 let lt_token: Token![<] = input.parse()?;
Alex Crichton954046c2017-05-30 21:49:42 -0700491
David Tolnay3c29f6e2018-10-27 22:47:48 -0700492 let mut params = Punctuated::new();
David Tolnayd502e4b2019-05-25 00:20:27 -0700493 let mut allow_lifetime_param = true;
494 let mut allow_type_param = true;
David Tolnay1b8e2852018-08-26 08:25:18 -0400495 loop {
496 if input.peek(Token![>]) {
497 break;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800498 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400499
500 let attrs = input.call(Attribute::parse_outer)?;
501 let lookahead = input.lookahead1();
David Tolnayd502e4b2019-05-25 00:20:27 -0700502 if allow_lifetime_param && lookahead.peek(Lifetime) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400503 params.push_value(GenericParam::Lifetime(LifetimeDef {
504 attrs: attrs,
505 ..input.parse()?
506 }));
David Tolnayd502e4b2019-05-25 00:20:27 -0700507 } else if allow_type_param && lookahead.peek(Ident) {
508 allow_lifetime_param = false;
David Tolnay1b8e2852018-08-26 08:25:18 -0400509 params.push_value(GenericParam::Type(TypeParam {
510 attrs: attrs,
511 ..input.parse()?
512 }));
David Tolnayd502e4b2019-05-25 00:20:27 -0700513 } else if lookahead.peek(Token![const]) {
514 allow_lifetime_param = false;
515 allow_type_param = false;
516 params.push_value(GenericParam::Const(ConstParam {
517 attrs: attrs,
518 ..input.parse()?
519 }));
David Tolnay1b8e2852018-08-26 08:25:18 -0400520 } else {
521 return Err(lookahead.error());
David Tolnay40fb8ce2018-01-02 10:53:46 -0800522 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400523
524 if input.peek(Token![>]) {
525 break;
526 }
527 let punct = input.parse()?;
528 params.push_punct(punct);
529 }
530
531 let gt_token: Token![>] = input.parse()?;
532
533 Ok(Generics {
534 lt_token: Some(lt_token),
535 params: params,
536 gt_token: Some(gt_token),
537 where_clause: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800538 })
David Tolnay40fb8ce2018-01-02 10:53:46 -0800539 }
540 }
541
David Tolnay1b8e2852018-08-26 08:25:18 -0400542 impl Parse for GenericParam {
543 fn parse(input: ParseStream) -> Result<Self> {
544 let attrs = input.call(Attribute::parse_outer)?;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800545
David Tolnay1b8e2852018-08-26 08:25:18 -0400546 let lookahead = input.lookahead1();
547 if lookahead.peek(Ident) {
548 Ok(GenericParam::Type(TypeParam {
David Tolnay78ee5202017-12-04 22:17:54 -0800549 attrs: attrs,
David Tolnay1b8e2852018-08-26 08:25:18 -0400550 ..input.parse()?
551 }))
552 } else if lookahead.peek(Lifetime) {
553 Ok(GenericParam::Lifetime(LifetimeDef {
554 attrs: attrs,
555 ..input.parse()?
556 }))
557 } else if lookahead.peek(Token![const]) {
558 Ok(GenericParam::Const(ConstParam {
559 attrs: attrs,
560 ..input.parse()?
561 }))
562 } else {
563 Err(lookahead.error())
564 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800565 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500566 }
567
David Tolnay1b8e2852018-08-26 08:25:18 -0400568 impl Parse for LifetimeDef {
569 fn parse(input: ParseStream) -> Result<Self> {
570 let has_colon;
571 Ok(LifetimeDef {
572 attrs: input.call(Attribute::parse_outer)?,
573 lifetime: input.parse()?,
574 colon_token: {
575 if input.peek(Token![:]) {
576 has_colon = true;
577 Some(input.parse()?)
578 } else {
579 has_colon = false;
580 None
581 }
582 },
583 bounds: {
584 let mut bounds = Punctuated::new();
585 if has_colon {
586 loop {
587 if input.peek(Token![,]) || input.peek(Token![>]) {
588 break;
589 }
590 let value = input.parse()?;
591 bounds.push_value(value);
592 if !input.peek(Token![+]) {
593 break;
594 }
595 let punct = input.parse()?;
596 bounds.push_punct(punct);
597 }
598 }
599 bounds
600 },
David Tolnayac997dd2017-12-27 23:18:22 -0500601 })
Alex Crichton954046c2017-05-30 21:49:42 -0700602 }
603 }
604
David Tolnay1b8e2852018-08-26 08:25:18 -0400605 impl Parse for BoundLifetimes {
606 fn parse(input: ParseStream) -> Result<Self> {
607 Ok(BoundLifetimes {
608 for_token: input.parse()?,
609 lt_token: input.parse()?,
David Tolnayf5ebc192018-08-30 18:23:46 -0700610 lifetimes: {
611 let mut lifetimes = Punctuated::new();
612 while !input.peek(Token![>]) {
613 lifetimes.push_value(input.parse()?);
614 if input.peek(Token![>]) {
615 break;
616 }
617 lifetimes.push_punct(input.parse()?);
618 }
619 lifetimes
620 },
David Tolnay1b8e2852018-08-26 08:25:18 -0400621 gt_token: input.parse()?,
622 })
623 }
624 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800625
David Tolnay1b8e2852018-08-26 08:25:18 -0400626 impl Parse for Option<BoundLifetimes> {
627 fn parse(input: ParseStream) -> Result<Self> {
628 if input.peek(Token![for]) {
629 input.parse().map(Some)
630 } else {
631 Ok(None)
632 }
633 }
634 }
635
636 impl Parse for TypeParam {
637 fn parse(input: ParseStream) -> Result<Self> {
638 let has_colon;
639 let has_default;
640 Ok(TypeParam {
641 attrs: input.call(Attribute::parse_outer)?,
642 ident: input.parse()?,
643 colon_token: {
644 if input.peek(Token![:]) {
645 has_colon = true;
646 Some(input.parse()?)
647 } else {
648 has_colon = false;
649 None
650 }
651 },
652 bounds: {
653 let mut bounds = Punctuated::new();
654 if has_colon {
655 loop {
David Tolnaye614f282018-10-27 22:50:12 -0700656 if input.peek(Token![,])
657 || input.peek(Token![>])
658 || input.peek(Token![=])
659 {
David Tolnay1b8e2852018-08-26 08:25:18 -0400660 break;
661 }
662 let value = input.parse()?;
663 bounds.push_value(value);
664 if !input.peek(Token![+]) {
665 break;
666 }
667 let punct = input.parse()?;
668 bounds.push_punct(punct);
669 }
670 }
671 bounds
672 },
673 eq_token: {
674 if input.peek(Token![=]) {
675 has_default = true;
676 Some(input.parse()?)
677 } else {
678 has_default = false;
679 None
680 }
681 },
682 default: {
683 if has_default {
David Tolnaya7d69fc2018-08-26 13:30:24 -0400684 Some(input.parse()?)
David Tolnay1b8e2852018-08-26 08:25:18 -0400685 } else {
686 None
687 }
688 },
689 })
690 }
691 }
692
693 impl Parse for TypeParamBound {
694 fn parse(input: ParseStream) -> Result<Self> {
695 if input.peek(Lifetime) {
696 return input.parse().map(TypeParamBound::Lifetime);
697 }
698
699 if input.peek(token::Paren) {
700 let content;
701 let paren_token = parenthesized!(content in input);
702 let mut bound: TraitBound = content.parse()?;
703 bound.paren_token = Some(paren_token);
704 return Ok(TypeParamBound::Trait(bound));
705 }
706
707 input.parse().map(TypeParamBound::Trait)
708 }
709 }
710
711 impl Parse for TraitBound {
712 fn parse(input: ParseStream) -> Result<Self> {
713 let modifier: TraitBoundModifier = input.parse()?;
714 let lifetimes: Option<BoundLifetimes> = input.parse()?;
715
716 let mut path: Path = input.parse()?;
717 if path.segments.last().unwrap().value().arguments.is_empty()
718 && input.peek(token::Paren)
719 {
720 let parenthesized = PathArguments::Parenthesized(input.parse()?);
721 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
722 }
723
724 Ok(TraitBound {
725 paren_token: None,
726 modifier: modifier,
727 lifetimes: lifetimes,
728 path: path,
729 })
730 }
731 }
732
733 impl Parse for TraitBoundModifier {
734 fn parse(input: ParseStream) -> Result<Self> {
735 if input.peek(Token![?]) {
736 input.parse().map(TraitBoundModifier::Maybe)
737 } else {
738 Ok(TraitBoundModifier::None)
739 }
740 }
741 }
742
743 impl Parse for ConstParam {
744 fn parse(input: ParseStream) -> Result<Self> {
745 let mut default = None;
746 Ok(ConstParam {
747 attrs: input.call(Attribute::parse_outer)?,
748 const_token: input.parse()?,
749 ident: input.parse()?,
750 colon_token: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400751 ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400752 eq_token: {
753 if input.peek(Token![=]) {
754 let eq_token = input.parse()?;
David Tolnay9389c382018-08-27 09:13:37 -0700755 default = Some(input.parse::<Expr>()?);
David Tolnay1b8e2852018-08-26 08:25:18 -0400756 Some(eq_token)
757 } else {
758 None
759 }
760 },
761 default: default,
762 })
763 }
764 }
765
766 impl Parse for WhereClause {
767 fn parse(input: ParseStream) -> Result<Self> {
768 Ok(WhereClause {
769 where_token: input.parse()?,
770 predicates: {
771 let mut predicates = Punctuated::new();
772 loop {
David Tolnay38012de2018-09-02 13:32:47 -0700773 if input.is_empty()
774 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400775 || input.peek(Token![,])
776 || input.peek(Token![;])
777 || input.peek(Token![:]) && !input.peek(Token![::])
778 || input.peek(Token![=])
779 {
780 break;
781 }
782 let value = input.parse()?;
783 predicates.push_value(value);
784 if !input.peek(Token![,]) {
785 break;
786 }
787 let punct = input.parse()?;
788 predicates.push_punct(punct);
789 }
790 predicates
791 },
792 })
793 }
794 }
795
796 impl Parse for Option<WhereClause> {
797 fn parse(input: ParseStream) -> Result<Self> {
798 if input.peek(Token![where]) {
799 input.parse().map(Some)
800 } else {
801 Ok(None)
802 }
803 }
804 }
805
806 impl Parse for WherePredicate {
807 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay66cb0c42018-08-31 09:01:30 -0700808 if input.peek(Lifetime) && input.peek2(Token![:]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400809 Ok(WherePredicate::Lifetime(PredicateLifetime {
810 lifetime: input.parse()?,
811 colon_token: input.parse()?,
812 bounds: {
813 let mut bounds = Punctuated::new();
814 loop {
David Tolnay1e072a72019-07-23 19:21:27 -0700815 if input.is_empty()
816 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400817 || 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 {
David Tolnay1e072a72019-07-23 19:21:27 -0700843 if input.is_empty()
844 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400845 || input.peek(Token![,])
846 || input.peek(Token![;])
847 || input.peek(Token![:]) && !input.peek(Token![::])
848 || input.peek(Token![=])
849 {
850 break;
851 }
852 let value = input.parse()?;
853 bounds.push_value(value);
854 if !input.peek(Token![+]) {
855 break;
856 }
857 let punct = input.parse()?;
858 bounds.push_punct(punct);
859 }
860 bounds
861 },
862 }))
863 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800864 }
Alex Crichton954046c2017-05-30 21:49:42 -0700865 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700866}
David Tolnay87d0b442016-09-04 11:52:12 -0700867
868#[cfg(feature = "printing")]
869mod printing {
870 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700871
Alex Crichtona74a1c82018-05-16 10:20:44 -0700872 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700873 use quote::{ToTokens, TokenStreamExt};
David Tolnay87d0b442016-09-04 11:52:12 -0700874
David Tolnay64023912018-08-31 09:51:12 -0700875 use attr::FilterAttrs;
876 use print::TokensOrDefault;
877
David Tolnay8ef93042016-09-04 14:08:40 -0700878 impl ToTokens for Generics {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700879 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800880 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400881 return;
882 }
883
Alex Crichton259ee532017-07-14 06:51:02 -0700884 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800885
886 // Print lifetimes before types and consts, regardless of their
887 // order in self.params.
888 //
889 // TODO: ordering rules for const parameters vs type parameters have
890 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
891 let mut trailing_or_empty = true;
892 for param in self.params.pairs() {
893 if let GenericParam::Lifetime(_) = **param.value() {
894 param.to_tokens(tokens);
895 trailing_or_empty = param.punct().is_some();
896 }
897 }
898 for param in self.params.pairs() {
899 match **param.value() {
900 GenericParam::Type(_) | GenericParam::Const(_) => {
901 if !trailing_or_empty {
902 <Token![,]>::default().to_tokens(tokens);
903 trailing_or_empty = true;
904 }
905 param.to_tokens(tokens);
906 }
907 GenericParam::Lifetime(_) => {}
908 }
909 }
910
Alex Crichton259ee532017-07-14 06:51:02 -0700911 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700912 }
913 }
914
David Tolnaye7678922016-10-13 20:44:03 -0700915 impl<'a> ToTokens for ImplGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700916 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800917 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400918 return;
919 }
920
Alex Crichton259ee532017-07-14 06:51:02 -0700921 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800922
923 // Print lifetimes before types and consts, regardless of their
924 // order in self.params.
925 //
926 // TODO: ordering rules for const parameters vs type parameters have
927 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
928 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800929 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800930 if let GenericParam::Lifetime(_) = **param.value() {
931 param.to_tokens(tokens);
932 trailing_or_empty = param.punct().is_some();
933 }
934 }
935 for param in self.0.params.pairs() {
936 if let GenericParam::Lifetime(_) = **param.value() {
937 continue;
938 }
939 if !trailing_or_empty {
940 <Token![,]>::default().to_tokens(tokens);
941 trailing_or_empty = true;
942 }
David Tolnay56080682018-01-06 14:01:52 -0800943 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800944 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800945 GenericParam::Type(ref param) => {
946 // Leave off the type parameter defaults
947 tokens.append_all(param.attrs.outer());
948 param.ident.to_tokens(tokens);
949 if !param.bounds.is_empty() {
950 TokensOrDefault(&param.colon_token).to_tokens(tokens);
951 param.bounds.to_tokens(tokens);
952 }
953 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500954 GenericParam::Const(ref param) => {
955 // Leave off the const parameter defaults
956 tokens.append_all(param.attrs.outer());
957 param.const_token.to_tokens(tokens);
958 param.ident.to_tokens(tokens);
959 param.colon_token.to_tokens(tokens);
960 param.ty.to_tokens(tokens);
961 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400962 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500963 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700964 }
David Tolnay225aca62018-01-11 20:51:46 -0800965
Alex Crichton259ee532017-07-14 06:51:02 -0700966 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700967 }
968 }
969
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800970 impl<'a> ToTokens for TypeGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700971 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800972 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400973 return;
974 }
975
Alex Crichton259ee532017-07-14 06:51:02 -0700976 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800977
978 // Print lifetimes before types and consts, regardless of their
979 // order in self.params.
980 //
981 // TODO: ordering rules for const parameters vs type parameters have
982 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
983 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800984 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800985 if let GenericParam::Lifetime(ref def) = **param.value() {
986 // Leave off the lifetime bounds and attributes
987 def.lifetime.to_tokens(tokens);
988 param.punct().to_tokens(tokens);
989 trailing_or_empty = param.punct().is_some();
990 }
991 }
992 for param in self.0.params.pairs() {
993 if let GenericParam::Lifetime(_) = **param.value() {
994 continue;
995 }
996 if !trailing_or_empty {
997 <Token![,]>::default().to_tokens(tokens);
998 trailing_or_empty = true;
999 }
David Tolnay56080682018-01-06 14:01:52 -08001000 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -08001001 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -08001002 GenericParam::Type(ref param) => {
1003 // Leave off the type parameter defaults
1004 param.ident.to_tokens(tokens);
1005 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001006 GenericParam::Const(ref param) => {
1007 // Leave off the const parameter defaults
1008 param.ident.to_tokens(tokens);
1009 }
David Tolnayc2f1aba2017-11-12 20:29:22 -08001010 }
David Tolnayf2cfd722017-12-31 18:02:51 -05001011 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001012 }
David Tolnay225aca62018-01-11 20:51:46 -08001013
Alex Crichton259ee532017-07-14 06:51:02 -07001014 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -07001015 }
1016 }
1017
David Tolnayc879a502017-01-25 15:51:32 -08001018 impl<'a> ToTokens for Turbofish<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001019 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -08001020 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08001021 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001022 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -08001023 }
1024 }
1025 }
1026
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001027 impl ToTokens for BoundLifetimes {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001028 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001029 self.for_token.to_tokens(tokens);
1030 self.lt_token.to_tokens(tokens);
1031 self.lifetimes.to_tokens(tokens);
1032 self.gt_token.to_tokens(tokens);
1033 }
1034 }
1035
David Tolnay87d0b442016-09-04 11:52:12 -07001036 impl ToTokens for LifetimeDef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001037 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001038 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -07001039 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001040 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001041 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001042 self.bounds.to_tokens(tokens);
1043 }
David Tolnay87d0b442016-09-04 11:52:12 -07001044 }
1045 }
1046
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001047 impl ToTokens for TypeParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001048 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001049 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -07001050 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001051 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001052 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001053 self.bounds.to_tokens(tokens);
1054 }
1055 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07001056 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001057 self.default.to_tokens(tokens);
1058 }
David Tolnay8ef93042016-09-04 14:08:40 -07001059 }
1060 }
1061
David Tolnay40fb8ce2018-01-02 10:53:46 -08001062 impl ToTokens for TraitBound {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001063 fn to_tokens(&self, tokens: &mut TokenStream) {
1064 let to_tokens = |tokens: &mut TokenStream| {
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001065 self.modifier.to_tokens(tokens);
1066 self.lifetimes.to_tokens(tokens);
1067 self.path.to_tokens(tokens);
1068 };
1069 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +02001070 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001071 None => to_tokens(tokens),
1072 }
David Tolnay55337722016-09-11 12:58:56 -07001073 }
1074 }
1075
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001076 impl ToTokens for TraitBoundModifier {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001077 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001078 match *self {
1079 TraitBoundModifier::None => {}
1080 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
1081 }
1082 }
1083 }
1084
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001085 impl ToTokens for ConstParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001086 fn to_tokens(&self, tokens: &mut TokenStream) {
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001087 tokens.append_all(self.attrs.outer());
1088 self.const_token.to_tokens(tokens);
1089 self.ident.to_tokens(tokens);
1090 self.colon_token.to_tokens(tokens);
1091 self.ty.to_tokens(tokens);
1092 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -08001093 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001094 self.default.to_tokens(tokens);
1095 }
1096 }
1097 }
1098
David Tolnay55337722016-09-11 12:58:56 -07001099 impl ToTokens for WhereClause {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001100 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2a0b02f2018-03-09 00:50:45 -08001101 if !self.predicates.is_empty() {
1102 self.where_token.to_tokens(tokens);
1103 self.predicates.to_tokens(tokens);
1104 }
David Tolnay87d0b442016-09-04 11:52:12 -07001105 }
1106 }
David Tolnay8ef93042016-09-04 14:08:40 -07001107
David Tolnayd4add852018-01-01 20:13:24 -08001108 impl ToTokens for PredicateType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001109 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay40fb8ce2018-01-02 10:53:46 -08001110 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001111 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001112 self.colon_token.to_tokens(tokens);
1113 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001114 }
1115 }
1116
David Tolnayd4add852018-01-01 20:13:24 -08001117 impl ToTokens for PredicateLifetime {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001118 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay8ef93042016-09-04 14:08:40 -07001119 self.lifetime.to_tokens(tokens);
David Tolnay1b8e2852018-08-26 08:25:18 -04001120 self.colon_token.to_tokens(tokens);
1121 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001122 }
1123 }
David Tolnayf8e08832017-01-23 00:04:32 -08001124
David Tolnayd4add852018-01-01 20:13:24 -08001125 impl ToTokens for PredicateEq {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001126 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8e08832017-01-23 00:04:32 -08001127 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001128 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001129 self.rhs_ty.to_tokens(tokens);
1130 }
1131 }
David Tolnay87d0b442016-09-04 11:52:12 -07001132}