blob: 10fdb48a9f5eaceba98c1f50642b6bbb5465f636 [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 Tolnayc2f1aba2017-11-12 20:29:22 -080031 pub enum GenericParam {
David Tolnayed906d12018-01-07 01:20:29 -080032 /// A generic type parameter: `T: Into<String>`.
David Tolnay461d98e2018-01-07 11:07:19 -080033 ///
34 /// *This type is available if Syn is built with the `"derive"` or
35 /// `"full"` feature.*
David Tolnayc2f1aba2017-11-12 20:29:22 -080036 pub Type(TypeParam {
37 pub attrs: Vec<Attribute>,
38 pub ident: Ident,
39 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050040 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080041 pub eq_token: Option<Token![=]>,
42 pub default: Option<Type>,
43 }),
David Tolnayed906d12018-01-07 01:20:29 -080044
45 /// A lifetime definition: `'a: 'b + 'c + 'd`.
David Tolnay461d98e2018-01-07 11:07:19 -080046 ///
47 /// *This type is available if Syn is built with the `"derive"` or
48 /// `"full"` feature.*
David Tolnay517f3692018-01-01 20:17:23 -080049 pub Lifetime(LifetimeDef {
50 pub attrs: Vec<Attribute>,
51 pub lifetime: Lifetime,
52 pub colon_token: Option<Token![:]>,
53 pub bounds: Punctuated<Lifetime, Token![+]>,
54 }),
David Tolnayed906d12018-01-07 01:20:29 -080055
56 /// A const generic parameter: `const LENGTH: usize`.
David Tolnay461d98e2018-01-07 11:07:19 -080057 ///
58 /// *This type is available if Syn is built with the `"derive"` or
59 /// `"full"` feature.*
Nika Layzellf1fdc0b2017-12-04 19:58:32 -050060 pub Const(ConstParam {
61 pub attrs: Vec<Attribute>,
62 pub const_token: Token![const],
63 pub ident: Ident,
64 pub colon_token: Token![:],
65 pub ty: Type,
66 pub eq_token: Option<Token![=]>,
67 pub default: Option<Expr>,
68 }),
David Tolnayc2f1aba2017-11-12 20:29:22 -080069 }
70}
71
Sean Griffin8fcca802018-01-15 15:45:41 -070072impl Generics {
David Tolnayef5199b2018-01-17 10:56:03 -080073 /// Returns an
74 /// <code
75 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
76 /// href="struct.TypeParam.html"><code
77 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
78 /// style="padding-left:0;">&gt;</code>
79 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070080 pub fn type_params(&self) -> TypeParams {
81 TypeParams(self.params.iter())
82 }
83
David Tolnayef5199b2018-01-17 10:56:03 -080084 /// Returns an
85 /// <code
86 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
87 /// href="struct.TypeParam.html"><code
88 /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code
89 /// style="padding-left:0;">&gt;</code>
90 /// over the type parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -070091 pub fn type_params_mut(&mut self) -> TypeParamsMut {
92 TypeParamsMut(self.params.iter_mut())
93 }
94
David Tolnayef5199b2018-01-17 10:56:03 -080095 /// Returns an
96 /// <code
97 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
98 /// href="struct.LifetimeDef.html"><code
99 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
100 /// style="padding-left:0;">&gt;</code>
101 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700102 pub fn lifetimes(&self) -> Lifetimes {
103 Lifetimes(self.params.iter())
104 }
105
David Tolnayef5199b2018-01-17 10:56:03 -0800106 /// Returns an
107 /// <code
108 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
109 /// href="struct.LifetimeDef.html"><code
110 /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
111 /// style="padding-left:0;">&gt;</code>
112 /// over the lifetime parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700113 pub fn lifetimes_mut(&mut self) -> LifetimesMut {
114 LifetimesMut(self.params.iter_mut())
115 }
116
David Tolnayef5199b2018-01-17 10:56:03 -0800117 /// Returns an
118 /// <code
119 /// style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
120 /// href="struct.ConstParam.html"><code
121 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
122 /// style="padding-left:0;">&gt;</code>
123 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700124 pub fn const_params(&self) -> ConstParams {
125 ConstParams(self.params.iter())
126 }
127
David Tolnayef5199b2018-01-17 10:56:03 -0800128 /// Returns an
129 /// <code
130 /// style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
131 /// href="struct.ConstParam.html"><code
132 /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code
133 /// style="padding-left:0;">&gt;</code>
134 /// over the constant parameters in `self.params`.
Sean Griffin8fcca802018-01-15 15:45:41 -0700135 pub fn const_params_mut(&mut self) -> ConstParamsMut {
136 ConstParamsMut(self.params.iter_mut())
137 }
David Tolnay7f9954d2018-04-01 16:52:15 +0200138
139 /// Initializes an empty `where`-clause if there is not one present already.
140 pub fn make_where_clause(&mut self) -> &mut WhereClause {
141 // This is Option::get_or_insert_with in Rust 1.20.
142 if self.where_clause.is_none() {
143 self.where_clause = Some(WhereClause {
David Tolnayd228b332018-06-27 23:56:05 -0700144 where_token: <Token![where]>::default(),
David Tolnay7f9954d2018-04-01 16:52:15 +0200145 predicates: Punctuated::new(),
146 });
147 }
148 match self.where_clause {
149 Some(ref mut where_clause) => where_clause,
150 None => unreachable!(),
151 }
152 }
Sean Griffin8fcca802018-01-15 15:45:41 -0700153}
154
David Tolnay8095c302018-03-31 19:34:17 +0200155pub struct TypeParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700156
157impl<'a> Iterator for TypeParams<'a> {
158 type Item = &'a TypeParam;
159
160 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700161 let next = match self.0.next() {
162 Some(item) => item,
163 None => return None,
164 };
165 if let GenericParam::Type(ref type_param) = *next {
166 Some(type_param)
167 } else {
168 self.next()
169 }
170 }
171}
172
David Tolnay8095c302018-03-31 19:34:17 +0200173pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700174
175impl<'a> Iterator for TypeParamsMut<'a> {
176 type Item = &'a mut TypeParam;
177
178 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700179 let next = match self.0.next() {
180 Some(item) => item,
181 None => return None,
182 };
183 if let GenericParam::Type(ref mut type_param) = *next {
184 Some(type_param)
185 } else {
186 self.next()
187 }
188 }
189}
190
David Tolnay8095c302018-03-31 19:34:17 +0200191pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700192
193impl<'a> Iterator for Lifetimes<'a> {
194 type Item = &'a LifetimeDef;
195
196 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700197 let next = match self.0.next() {
198 Some(item) => item,
199 None => return None,
200 };
201 if let GenericParam::Lifetime(ref lifetime) = *next {
202 Some(lifetime)
203 } else {
204 self.next()
205 }
206 }
207}
208
David Tolnay8095c302018-03-31 19:34:17 +0200209pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700210
211impl<'a> Iterator for LifetimesMut<'a> {
212 type Item = &'a mut LifetimeDef;
213
214 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700215 let next = match self.0.next() {
216 Some(item) => item,
217 None => return None,
218 };
219 if let GenericParam::Lifetime(ref mut lifetime) = *next {
220 Some(lifetime)
221 } else {
222 self.next()
223 }
224 }
225}
226
David Tolnay8095c302018-03-31 19:34:17 +0200227pub struct ConstParams<'a>(Iter<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700228
229impl<'a> Iterator for ConstParams<'a> {
230 type Item = &'a ConstParam;
231
232 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700233 let next = match self.0.next() {
234 Some(item) => item,
235 None => return None,
236 };
237 if let GenericParam::Const(ref const_param) = *next {
238 Some(const_param)
239 } else {
240 self.next()
241 }
242 }
243}
244
David Tolnay8095c302018-03-31 19:34:17 +0200245pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
Sean Griffin8fcca802018-01-15 15:45:41 -0700246
247impl<'a> Iterator for ConstParamsMut<'a> {
248 type Item = &'a mut ConstParam;
249
250 fn next(&mut self) -> Option<Self::Item> {
Sean Griffin8fcca802018-01-15 15:45:41 -0700251 let next = match self.0.next() {
252 Some(item) => item,
253 None => return None,
254 };
255 if let GenericParam::Const(ref mut const_param) = *next {
256 Some(const_param)
257 } else {
258 self.next()
259 }
260 }
261}
262
David Tolnay461d98e2018-01-07 11:07:19 -0800263/// Returned by `Generics::split_for_impl`.
264///
265/// *This type is available if Syn is built with the `"derive"` or `"full"`
266/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700267#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400268#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
269#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400270pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700271
David Tolnay461d98e2018-01-07 11:07:19 -0800272/// Returned by `Generics::split_for_impl`.
273///
274/// *This type is available if Syn is built with the `"derive"` or `"full"`
275/// feature and the `"printing"` feature.*
David Tolnaye7678922016-10-13 20:44:03 -0700276#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400277#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
278#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800279pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -0700280
David Tolnay461d98e2018-01-07 11:07:19 -0800281/// Returned by `TypeGenerics::as_turbofish`.
282///
283/// *This type is available if Syn is built with the `"derive"` or `"full"`
284/// feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800285#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -0400286#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
287#[cfg_attr(feature = "clone-impls", derive(Clone))]
Nika Layzell6b38b132017-10-24 23:09:39 -0400288pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -0800289
David Tolnaye95cc9f2017-01-25 15:57:09 -0800290#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -0700291impl Generics {
292 /// Split a type's generics into the pieces required for impl'ing a trait
293 /// for that type.
294 ///
David Tolnay95989db2019-01-01 15:05:57 -0500295 /// ```edition2018
Alex Crichtonf0fea9a2018-05-17 11:19:34 -0700296 /// # use proc_macro2::{Span, Ident};
David Tolnayfd5b1172018-12-31 17:54:36 -0500297 /// # use quote::quote;
David Tolnay9b00f652018-09-01 10:31:02 -0700298 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700299 /// # fn main() {
David Tolnay9b00f652018-09-01 10:31:02 -0700300 /// # let generics: syn::Generics = Default::default();
301 /// # let name = Ident::new("MyType", Span::call_site());
302 /// #
David Tolnayb153dbc2016-10-04 23:39:10 -0700303 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
304 /// quote! {
305 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
306 /// // ...
307 /// }
308 /// }
David Tolnay9b00f652018-09-01 10:31:02 -0700309 /// # ;
David Tolnayb153dbc2016-10-04 23:39:10 -0700310 /// # }
311 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This method is available if Syn is built with the `"derive"` or
314 /// `"full"` feature and the `"printing"` feature.*
David Tolnayac997dd2017-12-27 23:18:22 -0500315 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -0800316 (
317 ImplGenerics(self),
318 TypeGenerics(self),
319 self.where_clause.as_ref(),
320 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700321 }
322}
323
David Tolnaye95cc9f2017-01-25 15:57:09 -0800324#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800325impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800326 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This method is available if Syn is built with the `"derive"` or
329 /// `"full"` feature and the `"printing"` feature.*
David Tolnayc879a502017-01-25 15:51:32 -0800330 pub fn as_turbofish(&self) -> Turbofish {
331 Turbofish(self.0)
332 }
333}
334
Alex Crichton62a0a592017-05-22 13:58:53 -0700335ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800336 /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800337 ///
338 /// *This type is available if Syn is built with the `"derive"` or `"full"`
339 /// feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700340 #[derive(Default)]
341 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800342 pub for_token: Token![for],
343 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500344 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800345 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700346 }
347}
348
David Tolnayf9505b52016-10-02 09:18:52 -0700349impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700350 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700351 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700352 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700353 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700354 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500355 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700356 }
357 }
358}
359
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800360impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700361 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800362 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700363 attrs: vec![],
364 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700365 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500366 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700367 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700368 default: None,
369 }
370 }
371}
372
David Tolnay40fb8ce2018-01-02 10:53:46 -0800373ast_enum_of_structs! {
David Tolnayed906d12018-01-07 01:20:29 -0800374 /// A trait or lifetime used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800375 ///
376 /// *This type is available if Syn is built with the `"derive"` or `"full"`
377 /// feature.*
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800378 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800379 pub Trait(TraitBound),
380 pub Lifetime(Lifetime),
381 }
382}
383
384ast_struct! {
David Tolnayed906d12018-01-07 01:20:29 -0800385 /// A trait used as a bound on a type parameter.
David Tolnay461d98e2018-01-07 11:07:19 -0800386 ///
387 /// *This type is available if Syn is built with the `"derive"` or `"full"`
388 /// feature.*
David Tolnay40fb8ce2018-01-02 10:53:46 -0800389 pub struct TraitBound {
David Tolnayc1f5d5d2018-03-31 22:17:56 +0200390 pub paren_token: Option<token::Paren>,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800391 pub modifier: TraitBoundModifier,
392 /// The `for<'a>` in `for<'a> Foo<&'a T>`
393 pub lifetimes: Option<BoundLifetimes>,
394 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
395 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 }
David Tolnay55337722016-09-11 12:58:56 -0700397}
398
Alex Crichton62a0a592017-05-22 13:58:53 -0700399ast_enum! {
David Tolnayed906d12018-01-07 01:20:29 -0800400 /// A modifier on a trait bound, currently only used for the `?` in
401 /// `?Sized`.
David Tolnay461d98e2018-01-07 11:07:19 -0800402 ///
403 /// *This type is available if Syn is built with the `"derive"` or `"full"`
404 /// feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700405 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700406 pub enum TraitBoundModifier {
407 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800408 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700409 }
David Tolnay55337722016-09-11 12:58:56 -0700410}
411
Alex Crichton62a0a592017-05-22 13:58:53 -0700412ast_struct! {
David Tolnay05658502018-01-07 09:56:37 -0800413 /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
414 /// 'static`.
David Tolnay461d98e2018-01-07 11:07:19 -0800415 ///
416 /// *This type is available if Syn is built with the `"derive"` or `"full"`
417 /// feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700418 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500419 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500420 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700421 }
David Tolnayb79ee962016-09-04 09:39:20 -0700422}
423
Alex Crichton62a0a592017-05-22 13:58:53 -0700424ast_enum_of_structs! {
David Tolnay05658502018-01-07 09:56:37 -0800425 /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
David Tolnay614a0142018-01-07 10:25:43 -0800426 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800427 /// *This type is available if Syn is built with the `"derive"` or `"full"`
428 /// feature.*
429 ///
David Tolnay614a0142018-01-07 10:25:43 -0800430 /// # Syntax tree enum
431 ///
432 /// This type is a [syntax tree enum].
433 ///
434 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700435 pub enum WherePredicate {
David Tolnayed906d12018-01-07 01:20:29 -0800436 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
David Tolnay461d98e2018-01-07 11:07:19 -0800437 ///
438 /// *This type is available if Syn is built with the `"derive"` or
439 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800440 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700441 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800442 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700443 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800444 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800445 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500447 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700449
David Tolnayed906d12018-01-07 01:20:29 -0800450 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
David Tolnay461d98e2018-01-07 11:07:19 -0800451 ///
452 /// *This type is available if Syn is built with the `"derive"` or
453 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800454 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700455 pub lifetime: Lifetime,
David Tolnay1b8e2852018-08-26 08:25:18 -0400456 pub colon_token: Token![:],
David Tolnayf2cfd722017-12-31 18:02:51 -0500457 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700458 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700459
David Tolnayed906d12018-01-07 01:20:29 -0800460 /// An equality predicate in a `where` clause (unsupported).
David Tolnay461d98e2018-01-07 11:07:19 -0800461 ///
462 /// *This type is available if Syn is built with the `"derive"` or
463 /// `"full"` feature.*
David Tolnayd4add852018-01-01 20:13:24 -0800464 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800465 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800466 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800467 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 }),
469 }
David Tolnayf8e08832017-01-23 00:04:32 -0800470}
471
David Tolnay86eca752016-09-04 11:26:41 -0700472#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700473pub mod parsing {
474 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700475
David Tolnay1b8e2852018-08-26 08:25:18 -0400476 use parse::{Parse, ParseStream, Result};
Alex Crichton954046c2017-05-30 21:49:42 -0700477
David Tolnay1b8e2852018-08-26 08:25:18 -0400478 impl Parse for Generics {
479 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay1b8e2852018-08-26 08:25:18 -0400480 if !input.peek(Token![<]) {
David Tolnay3c29f6e2018-10-27 22:47:48 -0700481 return Ok(Generics::default());
Michael Layzell416724e2017-05-24 21:12:34 -0400482 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800483
David Tolnay1b8e2852018-08-26 08:25:18 -0400484 let lt_token: Token![<] = input.parse()?;
Alex Crichton954046c2017-05-30 21:49:42 -0700485
David Tolnay3c29f6e2018-10-27 22:47:48 -0700486 let mut params = Punctuated::new();
David Tolnayd502e4b2019-05-25 00:20:27 -0700487 let mut allow_lifetime_param = true;
488 let mut allow_type_param = true;
David Tolnay1b8e2852018-08-26 08:25:18 -0400489 loop {
490 if input.peek(Token![>]) {
491 break;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800492 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400493
494 let attrs = input.call(Attribute::parse_outer)?;
495 let lookahead = input.lookahead1();
David Tolnayd502e4b2019-05-25 00:20:27 -0700496 if allow_lifetime_param && lookahead.peek(Lifetime) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400497 params.push_value(GenericParam::Lifetime(LifetimeDef {
498 attrs: attrs,
499 ..input.parse()?
500 }));
David Tolnayd502e4b2019-05-25 00:20:27 -0700501 } else if allow_type_param && lookahead.peek(Ident) {
502 allow_lifetime_param = false;
David Tolnay1b8e2852018-08-26 08:25:18 -0400503 params.push_value(GenericParam::Type(TypeParam {
504 attrs: attrs,
505 ..input.parse()?
506 }));
David Tolnayd502e4b2019-05-25 00:20:27 -0700507 } else if lookahead.peek(Token![const]) {
508 allow_lifetime_param = false;
509 allow_type_param = false;
510 params.push_value(GenericParam::Const(ConstParam {
511 attrs: attrs,
512 ..input.parse()?
513 }));
David Tolnay1b8e2852018-08-26 08:25:18 -0400514 } else {
515 return Err(lookahead.error());
David Tolnay40fb8ce2018-01-02 10:53:46 -0800516 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400517
518 if input.peek(Token![>]) {
519 break;
520 }
521 let punct = input.parse()?;
522 params.push_punct(punct);
523 }
524
525 let gt_token: Token![>] = input.parse()?;
526
527 Ok(Generics {
528 lt_token: Some(lt_token),
529 params: params,
530 gt_token: Some(gt_token),
531 where_clause: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800532 })
David Tolnay40fb8ce2018-01-02 10:53:46 -0800533 }
534 }
535
David Tolnay1b8e2852018-08-26 08:25:18 -0400536 impl Parse for GenericParam {
537 fn parse(input: ParseStream) -> Result<Self> {
538 let attrs = input.call(Attribute::parse_outer)?;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800539
David Tolnay1b8e2852018-08-26 08:25:18 -0400540 let lookahead = input.lookahead1();
541 if lookahead.peek(Ident) {
542 Ok(GenericParam::Type(TypeParam {
David Tolnay78ee5202017-12-04 22:17:54 -0800543 attrs: attrs,
David Tolnay1b8e2852018-08-26 08:25:18 -0400544 ..input.parse()?
545 }))
546 } else if lookahead.peek(Lifetime) {
547 Ok(GenericParam::Lifetime(LifetimeDef {
548 attrs: attrs,
549 ..input.parse()?
550 }))
551 } else if lookahead.peek(Token![const]) {
552 Ok(GenericParam::Const(ConstParam {
553 attrs: attrs,
554 ..input.parse()?
555 }))
556 } else {
557 Err(lookahead.error())
558 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800559 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500560 }
561
David Tolnay1b8e2852018-08-26 08:25:18 -0400562 impl Parse for LifetimeDef {
563 fn parse(input: ParseStream) -> Result<Self> {
564 let has_colon;
565 Ok(LifetimeDef {
566 attrs: input.call(Attribute::parse_outer)?,
567 lifetime: input.parse()?,
568 colon_token: {
569 if input.peek(Token![:]) {
570 has_colon = true;
571 Some(input.parse()?)
572 } else {
573 has_colon = false;
574 None
575 }
576 },
577 bounds: {
578 let mut bounds = Punctuated::new();
579 if has_colon {
580 loop {
581 if input.peek(Token![,]) || input.peek(Token![>]) {
582 break;
583 }
584 let value = input.parse()?;
585 bounds.push_value(value);
586 if !input.peek(Token![+]) {
587 break;
588 }
589 let punct = input.parse()?;
590 bounds.push_punct(punct);
591 }
592 }
593 bounds
594 },
David Tolnayac997dd2017-12-27 23:18:22 -0500595 })
Alex Crichton954046c2017-05-30 21:49:42 -0700596 }
597 }
598
David Tolnay1b8e2852018-08-26 08:25:18 -0400599 impl Parse for BoundLifetimes {
600 fn parse(input: ParseStream) -> Result<Self> {
601 Ok(BoundLifetimes {
602 for_token: input.parse()?,
603 lt_token: input.parse()?,
David Tolnayf5ebc192018-08-30 18:23:46 -0700604 lifetimes: {
605 let mut lifetimes = Punctuated::new();
606 while !input.peek(Token![>]) {
607 lifetimes.push_value(input.parse()?);
608 if input.peek(Token![>]) {
609 break;
610 }
611 lifetimes.push_punct(input.parse()?);
612 }
613 lifetimes
614 },
David Tolnay1b8e2852018-08-26 08:25:18 -0400615 gt_token: input.parse()?,
616 })
617 }
618 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800619
David Tolnay1b8e2852018-08-26 08:25:18 -0400620 impl Parse for Option<BoundLifetimes> {
621 fn parse(input: ParseStream) -> Result<Self> {
622 if input.peek(Token![for]) {
623 input.parse().map(Some)
624 } else {
625 Ok(None)
626 }
627 }
628 }
629
630 impl Parse for TypeParam {
631 fn parse(input: ParseStream) -> Result<Self> {
632 let has_colon;
633 let has_default;
634 Ok(TypeParam {
635 attrs: input.call(Attribute::parse_outer)?,
636 ident: input.parse()?,
637 colon_token: {
638 if input.peek(Token![:]) {
639 has_colon = true;
640 Some(input.parse()?)
641 } else {
642 has_colon = false;
643 None
644 }
645 },
646 bounds: {
647 let mut bounds = Punctuated::new();
648 if has_colon {
649 loop {
David Tolnaye614f282018-10-27 22:50:12 -0700650 if input.peek(Token![,])
651 || input.peek(Token![>])
652 || input.peek(Token![=])
653 {
David Tolnay1b8e2852018-08-26 08:25:18 -0400654 break;
655 }
656 let value = input.parse()?;
657 bounds.push_value(value);
658 if !input.peek(Token![+]) {
659 break;
660 }
661 let punct = input.parse()?;
662 bounds.push_punct(punct);
663 }
664 }
665 bounds
666 },
667 eq_token: {
668 if input.peek(Token![=]) {
669 has_default = true;
670 Some(input.parse()?)
671 } else {
672 has_default = false;
673 None
674 }
675 },
676 default: {
677 if has_default {
David Tolnaya7d69fc2018-08-26 13:30:24 -0400678 Some(input.parse()?)
David Tolnay1b8e2852018-08-26 08:25:18 -0400679 } else {
680 None
681 }
682 },
683 })
684 }
685 }
686
687 impl Parse for TypeParamBound {
688 fn parse(input: ParseStream) -> Result<Self> {
689 if input.peek(Lifetime) {
690 return input.parse().map(TypeParamBound::Lifetime);
691 }
692
693 if input.peek(token::Paren) {
694 let content;
695 let paren_token = parenthesized!(content in input);
696 let mut bound: TraitBound = content.parse()?;
697 bound.paren_token = Some(paren_token);
698 return Ok(TypeParamBound::Trait(bound));
699 }
700
701 input.parse().map(TypeParamBound::Trait)
702 }
703 }
704
705 impl Parse for TraitBound {
706 fn parse(input: ParseStream) -> Result<Self> {
707 let modifier: TraitBoundModifier = input.parse()?;
708 let lifetimes: Option<BoundLifetimes> = input.parse()?;
709
710 let mut path: Path = input.parse()?;
711 if path.segments.last().unwrap().value().arguments.is_empty()
712 && input.peek(token::Paren)
713 {
714 let parenthesized = PathArguments::Parenthesized(input.parse()?);
715 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
716 }
717
718 Ok(TraitBound {
719 paren_token: None,
720 modifier: modifier,
721 lifetimes: lifetimes,
722 path: path,
723 })
724 }
725 }
726
727 impl Parse for TraitBoundModifier {
728 fn parse(input: ParseStream) -> Result<Self> {
729 if input.peek(Token![?]) {
730 input.parse().map(TraitBoundModifier::Maybe)
731 } else {
732 Ok(TraitBoundModifier::None)
733 }
734 }
735 }
736
737 impl Parse for ConstParam {
738 fn parse(input: ParseStream) -> Result<Self> {
739 let mut default = None;
740 Ok(ConstParam {
741 attrs: input.call(Attribute::parse_outer)?,
742 const_token: input.parse()?,
743 ident: input.parse()?,
744 colon_token: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400745 ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400746 eq_token: {
747 if input.peek(Token![=]) {
748 let eq_token = input.parse()?;
David Tolnay9389c382018-08-27 09:13:37 -0700749 default = Some(input.parse::<Expr>()?);
David Tolnay1b8e2852018-08-26 08:25:18 -0400750 Some(eq_token)
751 } else {
752 None
753 }
754 },
755 default: default,
756 })
757 }
758 }
759
760 impl Parse for WhereClause {
761 fn parse(input: ParseStream) -> Result<Self> {
762 Ok(WhereClause {
763 where_token: input.parse()?,
764 predicates: {
765 let mut predicates = Punctuated::new();
766 loop {
David Tolnay38012de2018-09-02 13:32:47 -0700767 if input.is_empty()
768 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400769 || input.peek(Token![,])
770 || input.peek(Token![;])
771 || input.peek(Token![:]) && !input.peek(Token![::])
772 || input.peek(Token![=])
773 {
774 break;
775 }
776 let value = input.parse()?;
777 predicates.push_value(value);
778 if !input.peek(Token![,]) {
779 break;
780 }
781 let punct = input.parse()?;
782 predicates.push_punct(punct);
783 }
784 predicates
785 },
786 })
787 }
788 }
789
790 impl Parse for Option<WhereClause> {
791 fn parse(input: ParseStream) -> Result<Self> {
792 if input.peek(Token![where]) {
793 input.parse().map(Some)
794 } else {
795 Ok(None)
796 }
797 }
798 }
799
800 impl Parse for WherePredicate {
801 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay66cb0c42018-08-31 09:01:30 -0700802 if input.peek(Lifetime) && input.peek2(Token![:]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400803 Ok(WherePredicate::Lifetime(PredicateLifetime {
804 lifetime: input.parse()?,
805 colon_token: input.parse()?,
806 bounds: {
807 let mut bounds = Punctuated::new();
808 loop {
809 if input.peek(token::Brace)
810 || input.peek(Token![,])
811 || input.peek(Token![;])
812 || input.peek(Token![:])
813 || input.peek(Token![=])
814 {
815 break;
816 }
817 let value = input.parse()?;
818 bounds.push_value(value);
819 if !input.peek(Token![+]) {
820 break;
821 }
822 let punct = input.parse()?;
823 bounds.push_punct(punct);
824 }
825 bounds
826 },
827 }))
828 } else {
829 Ok(WherePredicate::Type(PredicateType {
830 lifetimes: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400831 bounded_ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400832 colon_token: input.parse()?,
833 bounds: {
834 let mut bounds = Punctuated::new();
835 loop {
836 if input.peek(token::Brace)
837 || input.peek(Token![,])
838 || input.peek(Token![;])
839 || input.peek(Token![:]) && !input.peek(Token![::])
840 || input.peek(Token![=])
841 {
842 break;
843 }
844 let value = input.parse()?;
845 bounds.push_value(value);
846 if !input.peek(Token![+]) {
847 break;
848 }
849 let punct = input.parse()?;
850 bounds.push_punct(punct);
851 }
852 bounds
853 },
854 }))
855 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800856 }
Alex Crichton954046c2017-05-30 21:49:42 -0700857 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700858}
David Tolnay87d0b442016-09-04 11:52:12 -0700859
860#[cfg(feature = "printing")]
861mod printing {
862 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700863
Alex Crichtona74a1c82018-05-16 10:20:44 -0700864 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700865 use quote::{ToTokens, TokenStreamExt};
David Tolnay87d0b442016-09-04 11:52:12 -0700866
David Tolnay64023912018-08-31 09:51:12 -0700867 use attr::FilterAttrs;
868 use print::TokensOrDefault;
869
David Tolnay8ef93042016-09-04 14:08:40 -0700870 impl ToTokens for Generics {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700871 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800872 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400873 return;
874 }
875
Alex Crichton259ee532017-07-14 06:51:02 -0700876 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800877
878 // Print lifetimes before types and consts, regardless of their
879 // order in self.params.
880 //
881 // TODO: ordering rules for const parameters vs type parameters have
882 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
883 let mut trailing_or_empty = true;
884 for param in self.params.pairs() {
885 if let GenericParam::Lifetime(_) = **param.value() {
886 param.to_tokens(tokens);
887 trailing_or_empty = param.punct().is_some();
888 }
889 }
890 for param in self.params.pairs() {
891 match **param.value() {
892 GenericParam::Type(_) | GenericParam::Const(_) => {
893 if !trailing_or_empty {
894 <Token![,]>::default().to_tokens(tokens);
895 trailing_or_empty = true;
896 }
897 param.to_tokens(tokens);
898 }
899 GenericParam::Lifetime(_) => {}
900 }
901 }
902
Alex Crichton259ee532017-07-14 06:51:02 -0700903 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700904 }
905 }
906
David Tolnaye7678922016-10-13 20:44:03 -0700907 impl<'a> ToTokens for ImplGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700908 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800909 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400910 return;
911 }
912
Alex Crichton259ee532017-07-14 06:51:02 -0700913 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800914
915 // Print lifetimes before types and consts, regardless of their
916 // order in self.params.
917 //
918 // TODO: ordering rules for const parameters vs type parameters have
919 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
920 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800921 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800922 if let GenericParam::Lifetime(_) = **param.value() {
923 param.to_tokens(tokens);
924 trailing_or_empty = param.punct().is_some();
925 }
926 }
927 for param in self.0.params.pairs() {
928 if let GenericParam::Lifetime(_) = **param.value() {
929 continue;
930 }
931 if !trailing_or_empty {
932 <Token![,]>::default().to_tokens(tokens);
933 trailing_or_empty = true;
934 }
David Tolnay56080682018-01-06 14:01:52 -0800935 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800936 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800937 GenericParam::Type(ref param) => {
938 // Leave off the type parameter defaults
939 tokens.append_all(param.attrs.outer());
940 param.ident.to_tokens(tokens);
941 if !param.bounds.is_empty() {
942 TokensOrDefault(&param.colon_token).to_tokens(tokens);
943 param.bounds.to_tokens(tokens);
944 }
945 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500946 GenericParam::Const(ref param) => {
947 // Leave off the const parameter defaults
948 tokens.append_all(param.attrs.outer());
949 param.const_token.to_tokens(tokens);
950 param.ident.to_tokens(tokens);
951 param.colon_token.to_tokens(tokens);
952 param.ty.to_tokens(tokens);
953 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400954 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500955 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700956 }
David Tolnay225aca62018-01-11 20:51:46 -0800957
Alex Crichton259ee532017-07-14 06:51:02 -0700958 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700959 }
960 }
961
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800962 impl<'a> ToTokens for TypeGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700963 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800964 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400965 return;
966 }
967
Alex Crichton259ee532017-07-14 06:51:02 -0700968 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800969
970 // Print lifetimes before types and consts, regardless of their
971 // order in self.params.
972 //
973 // TODO: ordering rules for const parameters vs type parameters have
974 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
975 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800976 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800977 if let GenericParam::Lifetime(ref def) = **param.value() {
978 // Leave off the lifetime bounds and attributes
979 def.lifetime.to_tokens(tokens);
980 param.punct().to_tokens(tokens);
981 trailing_or_empty = param.punct().is_some();
982 }
983 }
984 for param in self.0.params.pairs() {
985 if let GenericParam::Lifetime(_) = **param.value() {
986 continue;
987 }
988 if !trailing_or_empty {
989 <Token![,]>::default().to_tokens(tokens);
990 trailing_or_empty = true;
991 }
David Tolnay56080682018-01-06 14:01:52 -0800992 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800993 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800994 GenericParam::Type(ref param) => {
995 // Leave off the type parameter defaults
996 param.ident.to_tokens(tokens);
997 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500998 GenericParam::Const(ref param) => {
999 // Leave off the const parameter defaults
1000 param.ident.to_tokens(tokens);
1001 }
David Tolnayc2f1aba2017-11-12 20:29:22 -08001002 }
David Tolnayf2cfd722017-12-31 18:02:51 -05001003 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001004 }
David Tolnay225aca62018-01-11 20:51:46 -08001005
Alex Crichton259ee532017-07-14 06:51:02 -07001006 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -07001007 }
1008 }
1009
David Tolnayc879a502017-01-25 15:51:32 -08001010 impl<'a> ToTokens for Turbofish<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001011 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -08001012 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08001013 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001014 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -08001015 }
1016 }
1017 }
1018
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001019 impl ToTokens for BoundLifetimes {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001020 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001021 self.for_token.to_tokens(tokens);
1022 self.lt_token.to_tokens(tokens);
1023 self.lifetimes.to_tokens(tokens);
1024 self.gt_token.to_tokens(tokens);
1025 }
1026 }
1027
David Tolnay87d0b442016-09-04 11:52:12 -07001028 impl ToTokens for LifetimeDef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001029 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001030 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -07001031 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001032 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001033 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001034 self.bounds.to_tokens(tokens);
1035 }
David Tolnay87d0b442016-09-04 11:52:12 -07001036 }
1037 }
1038
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001039 impl ToTokens for TypeParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001040 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001041 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -07001042 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001043 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001044 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001045 self.bounds.to_tokens(tokens);
1046 }
1047 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07001048 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001049 self.default.to_tokens(tokens);
1050 }
David Tolnay8ef93042016-09-04 14:08:40 -07001051 }
1052 }
1053
David Tolnay40fb8ce2018-01-02 10:53:46 -08001054 impl ToTokens for TraitBound {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001055 fn to_tokens(&self, tokens: &mut TokenStream) {
1056 let to_tokens = |tokens: &mut TokenStream| {
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001057 self.modifier.to_tokens(tokens);
1058 self.lifetimes.to_tokens(tokens);
1059 self.path.to_tokens(tokens);
1060 };
1061 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +02001062 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001063 None => to_tokens(tokens),
1064 }
David Tolnay55337722016-09-11 12:58:56 -07001065 }
1066 }
1067
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001068 impl ToTokens for TraitBoundModifier {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001069 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001070 match *self {
1071 TraitBoundModifier::None => {}
1072 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
1073 }
1074 }
1075 }
1076
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001077 impl ToTokens for ConstParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001078 fn to_tokens(&self, tokens: &mut TokenStream) {
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001079 tokens.append_all(self.attrs.outer());
1080 self.const_token.to_tokens(tokens);
1081 self.ident.to_tokens(tokens);
1082 self.colon_token.to_tokens(tokens);
1083 self.ty.to_tokens(tokens);
1084 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -08001085 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001086 self.default.to_tokens(tokens);
1087 }
1088 }
1089 }
1090
David Tolnay55337722016-09-11 12:58:56 -07001091 impl ToTokens for WhereClause {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001092 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2a0b02f2018-03-09 00:50:45 -08001093 if !self.predicates.is_empty() {
1094 self.where_token.to_tokens(tokens);
1095 self.predicates.to_tokens(tokens);
1096 }
David Tolnay87d0b442016-09-04 11:52:12 -07001097 }
1098 }
David Tolnay8ef93042016-09-04 14:08:40 -07001099
David Tolnayd4add852018-01-01 20:13:24 -08001100 impl ToTokens for PredicateType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001101 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay40fb8ce2018-01-02 10:53:46 -08001102 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001103 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001104 self.colon_token.to_tokens(tokens);
1105 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001106 }
1107 }
1108
David Tolnayd4add852018-01-01 20:13:24 -08001109 impl ToTokens for PredicateLifetime {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001110 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay8ef93042016-09-04 14:08:40 -07001111 self.lifetime.to_tokens(tokens);
David Tolnay1b8e2852018-08-26 08:25:18 -04001112 self.colon_token.to_tokens(tokens);
1113 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001114 }
1115 }
David Tolnayf8e08832017-01-23 00:04:32 -08001116
David Tolnayd4add852018-01-01 20:13:24 -08001117 impl ToTokens for PredicateEq {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001118 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8e08832017-01-23 00:04:32 -08001119 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001120 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001121 self.rhs_ty.to_tokens(tokens);
1122 }
1123 }
David Tolnay87d0b442016-09-04 11:52:12 -07001124}