blob: 59c7c4523b4e6a7d7508282510e775fc8aed82f2 [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 Tolnay1b8e2852018-08-26 08:25:18 -0400487 let mut has_type_param = false;
488 loop {
489 if input.peek(Token![>]) {
490 break;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800491 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400492
493 let attrs = input.call(Attribute::parse_outer)?;
494 let lookahead = input.lookahead1();
495 if !has_type_param && lookahead.peek(Lifetime) {
496 params.push_value(GenericParam::Lifetime(LifetimeDef {
497 attrs: attrs,
498 ..input.parse()?
499 }));
500 } else if lookahead.peek(Ident) {
501 has_type_param = true;
502 params.push_value(GenericParam::Type(TypeParam {
503 attrs: attrs,
504 ..input.parse()?
505 }));
506 } else {
507 return Err(lookahead.error());
David Tolnay40fb8ce2018-01-02 10:53:46 -0800508 }
David Tolnay1b8e2852018-08-26 08:25:18 -0400509
510 if input.peek(Token![>]) {
511 break;
512 }
513 let punct = input.parse()?;
514 params.push_punct(punct);
515 }
516
517 let gt_token: Token![>] = input.parse()?;
518
519 Ok(Generics {
520 lt_token: Some(lt_token),
521 params: params,
522 gt_token: Some(gt_token),
523 where_clause: None,
David Tolnay40fb8ce2018-01-02 10:53:46 -0800524 })
David Tolnay40fb8ce2018-01-02 10:53:46 -0800525 }
526 }
527
David Tolnay1b8e2852018-08-26 08:25:18 -0400528 impl Parse for GenericParam {
529 fn parse(input: ParseStream) -> Result<Self> {
530 let attrs = input.call(Attribute::parse_outer)?;
David Tolnay40fb8ce2018-01-02 10:53:46 -0800531
David Tolnay1b8e2852018-08-26 08:25:18 -0400532 let lookahead = input.lookahead1();
533 if lookahead.peek(Ident) {
534 Ok(GenericParam::Type(TypeParam {
David Tolnay78ee5202017-12-04 22:17:54 -0800535 attrs: attrs,
David Tolnay1b8e2852018-08-26 08:25:18 -0400536 ..input.parse()?
537 }))
538 } else if lookahead.peek(Lifetime) {
539 Ok(GenericParam::Lifetime(LifetimeDef {
540 attrs: attrs,
541 ..input.parse()?
542 }))
543 } else if lookahead.peek(Token![const]) {
544 Ok(GenericParam::Const(ConstParam {
545 attrs: attrs,
546 ..input.parse()?
547 }))
548 } else {
549 Err(lookahead.error())
550 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800551 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500552 }
553
David Tolnay1b8e2852018-08-26 08:25:18 -0400554 impl Parse for LifetimeDef {
555 fn parse(input: ParseStream) -> Result<Self> {
556 let has_colon;
557 Ok(LifetimeDef {
558 attrs: input.call(Attribute::parse_outer)?,
559 lifetime: input.parse()?,
560 colon_token: {
561 if input.peek(Token![:]) {
562 has_colon = true;
563 Some(input.parse()?)
564 } else {
565 has_colon = false;
566 None
567 }
568 },
569 bounds: {
570 let mut bounds = Punctuated::new();
571 if has_colon {
572 loop {
573 if input.peek(Token![,]) || input.peek(Token![>]) {
574 break;
575 }
576 let value = input.parse()?;
577 bounds.push_value(value);
578 if !input.peek(Token![+]) {
579 break;
580 }
581 let punct = input.parse()?;
582 bounds.push_punct(punct);
583 }
584 }
585 bounds
586 },
David Tolnayac997dd2017-12-27 23:18:22 -0500587 })
Alex Crichton954046c2017-05-30 21:49:42 -0700588 }
589 }
590
David Tolnay1b8e2852018-08-26 08:25:18 -0400591 impl Parse for BoundLifetimes {
592 fn parse(input: ParseStream) -> Result<Self> {
593 Ok(BoundLifetimes {
594 for_token: input.parse()?,
595 lt_token: input.parse()?,
David Tolnayf5ebc192018-08-30 18:23:46 -0700596 lifetimes: {
597 let mut lifetimes = Punctuated::new();
598 while !input.peek(Token![>]) {
599 lifetimes.push_value(input.parse()?);
600 if input.peek(Token![>]) {
601 break;
602 }
603 lifetimes.push_punct(input.parse()?);
604 }
605 lifetimes
606 },
David Tolnay1b8e2852018-08-26 08:25:18 -0400607 gt_token: input.parse()?,
608 })
609 }
610 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800611
David Tolnay1b8e2852018-08-26 08:25:18 -0400612 impl Parse for Option<BoundLifetimes> {
613 fn parse(input: ParseStream) -> Result<Self> {
614 if input.peek(Token![for]) {
615 input.parse().map(Some)
616 } else {
617 Ok(None)
618 }
619 }
620 }
621
622 impl Parse for TypeParam {
623 fn parse(input: ParseStream) -> Result<Self> {
624 let has_colon;
625 let has_default;
626 Ok(TypeParam {
627 attrs: input.call(Attribute::parse_outer)?,
628 ident: input.parse()?,
629 colon_token: {
630 if input.peek(Token![:]) {
631 has_colon = true;
632 Some(input.parse()?)
633 } else {
634 has_colon = false;
635 None
636 }
637 },
638 bounds: {
639 let mut bounds = Punctuated::new();
640 if has_colon {
641 loop {
David Tolnaye614f282018-10-27 22:50:12 -0700642 if input.peek(Token![,])
643 || input.peek(Token![>])
644 || input.peek(Token![=])
645 {
David Tolnay1b8e2852018-08-26 08:25:18 -0400646 break;
647 }
648 let value = input.parse()?;
649 bounds.push_value(value);
650 if !input.peek(Token![+]) {
651 break;
652 }
653 let punct = input.parse()?;
654 bounds.push_punct(punct);
655 }
656 }
657 bounds
658 },
659 eq_token: {
660 if input.peek(Token![=]) {
661 has_default = true;
662 Some(input.parse()?)
663 } else {
664 has_default = false;
665 None
666 }
667 },
668 default: {
669 if has_default {
David Tolnaya7d69fc2018-08-26 13:30:24 -0400670 Some(input.parse()?)
David Tolnay1b8e2852018-08-26 08:25:18 -0400671 } else {
672 None
673 }
674 },
675 })
676 }
677 }
678
679 impl Parse for TypeParamBound {
680 fn parse(input: ParseStream) -> Result<Self> {
681 if input.peek(Lifetime) {
682 return input.parse().map(TypeParamBound::Lifetime);
683 }
684
685 if input.peek(token::Paren) {
686 let content;
687 let paren_token = parenthesized!(content in input);
688 let mut bound: TraitBound = content.parse()?;
689 bound.paren_token = Some(paren_token);
690 return Ok(TypeParamBound::Trait(bound));
691 }
692
693 input.parse().map(TypeParamBound::Trait)
694 }
695 }
696
697 impl Parse for TraitBound {
698 fn parse(input: ParseStream) -> Result<Self> {
699 let modifier: TraitBoundModifier = input.parse()?;
700 let lifetimes: Option<BoundLifetimes> = input.parse()?;
701
702 let mut path: Path = input.parse()?;
703 if path.segments.last().unwrap().value().arguments.is_empty()
704 && input.peek(token::Paren)
705 {
706 let parenthesized = PathArguments::Parenthesized(input.parse()?);
707 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
708 }
709
710 Ok(TraitBound {
711 paren_token: None,
712 modifier: modifier,
713 lifetimes: lifetimes,
714 path: path,
715 })
716 }
717 }
718
719 impl Parse for TraitBoundModifier {
720 fn parse(input: ParseStream) -> Result<Self> {
721 if input.peek(Token![?]) {
722 input.parse().map(TraitBoundModifier::Maybe)
723 } else {
724 Ok(TraitBoundModifier::None)
725 }
726 }
727 }
728
729 impl Parse for ConstParam {
730 fn parse(input: ParseStream) -> Result<Self> {
731 let mut default = None;
732 Ok(ConstParam {
733 attrs: input.call(Attribute::parse_outer)?,
734 const_token: input.parse()?,
735 ident: input.parse()?,
736 colon_token: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400737 ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400738 eq_token: {
739 if input.peek(Token![=]) {
740 let eq_token = input.parse()?;
David Tolnay9389c382018-08-27 09:13:37 -0700741 default = Some(input.parse::<Expr>()?);
David Tolnay1b8e2852018-08-26 08:25:18 -0400742 Some(eq_token)
743 } else {
744 None
745 }
746 },
747 default: default,
748 })
749 }
750 }
751
752 impl Parse for WhereClause {
753 fn parse(input: ParseStream) -> Result<Self> {
754 Ok(WhereClause {
755 where_token: input.parse()?,
756 predicates: {
757 let mut predicates = Punctuated::new();
758 loop {
David Tolnay38012de2018-09-02 13:32:47 -0700759 if input.is_empty()
760 || input.peek(token::Brace)
David Tolnay1b8e2852018-08-26 08:25:18 -0400761 || input.peek(Token![,])
762 || input.peek(Token![;])
763 || input.peek(Token![:]) && !input.peek(Token![::])
764 || input.peek(Token![=])
765 {
766 break;
767 }
768 let value = input.parse()?;
769 predicates.push_value(value);
770 if !input.peek(Token![,]) {
771 break;
772 }
773 let punct = input.parse()?;
774 predicates.push_punct(punct);
775 }
776 predicates
777 },
778 })
779 }
780 }
781
782 impl Parse for Option<WhereClause> {
783 fn parse(input: ParseStream) -> Result<Self> {
784 if input.peek(Token![where]) {
785 input.parse().map(Some)
786 } else {
787 Ok(None)
788 }
789 }
790 }
791
792 impl Parse for WherePredicate {
793 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay66cb0c42018-08-31 09:01:30 -0700794 if input.peek(Lifetime) && input.peek2(Token![:]) {
David Tolnay1b8e2852018-08-26 08:25:18 -0400795 Ok(WherePredicate::Lifetime(PredicateLifetime {
796 lifetime: input.parse()?,
797 colon_token: input.parse()?,
798 bounds: {
799 let mut bounds = Punctuated::new();
800 loop {
801 if input.peek(token::Brace)
802 || input.peek(Token![,])
803 || input.peek(Token![;])
804 || input.peek(Token![:])
805 || input.peek(Token![=])
806 {
807 break;
808 }
809 let value = input.parse()?;
810 bounds.push_value(value);
811 if !input.peek(Token![+]) {
812 break;
813 }
814 let punct = input.parse()?;
815 bounds.push_punct(punct);
816 }
817 bounds
818 },
819 }))
820 } else {
821 Ok(WherePredicate::Type(PredicateType {
822 lifetimes: input.parse()?,
David Tolnaya7d69fc2018-08-26 13:30:24 -0400823 bounded_ty: input.parse()?,
David Tolnay1b8e2852018-08-26 08:25:18 -0400824 colon_token: input.parse()?,
825 bounds: {
826 let mut bounds = Punctuated::new();
827 loop {
828 if input.peek(token::Brace)
829 || input.peek(Token![,])
830 || input.peek(Token![;])
831 || input.peek(Token![:]) && !input.peek(Token![::])
832 || input.peek(Token![=])
833 {
834 break;
835 }
836 let value = input.parse()?;
837 bounds.push_value(value);
838 if !input.peek(Token![+]) {
839 break;
840 }
841 let punct = input.parse()?;
842 bounds.push_punct(punct);
843 }
844 bounds
845 },
846 }))
847 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800848 }
Alex Crichton954046c2017-05-30 21:49:42 -0700849 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700850}
David Tolnay87d0b442016-09-04 11:52:12 -0700851
852#[cfg(feature = "printing")]
853mod printing {
854 use super::*;
David Tolnay64023912018-08-31 09:51:12 -0700855
Alex Crichtona74a1c82018-05-16 10:20:44 -0700856 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700857 use quote::{ToTokens, TokenStreamExt};
David Tolnay87d0b442016-09-04 11:52:12 -0700858
David Tolnay64023912018-08-31 09:51:12 -0700859 use attr::FilterAttrs;
860 use print::TokensOrDefault;
861
David Tolnay8ef93042016-09-04 14:08:40 -0700862 impl ToTokens for Generics {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700863 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800864 if self.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400865 return;
866 }
867
Alex Crichton259ee532017-07-14 06:51:02 -0700868 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnay298570b2018-01-11 16:38:36 -0800869
870 // Print lifetimes before types and consts, regardless of their
871 // order in self.params.
872 //
873 // TODO: ordering rules for const parameters vs type parameters have
874 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
875 let mut trailing_or_empty = true;
876 for param in self.params.pairs() {
877 if let GenericParam::Lifetime(_) = **param.value() {
878 param.to_tokens(tokens);
879 trailing_or_empty = param.punct().is_some();
880 }
881 }
882 for param in self.params.pairs() {
883 match **param.value() {
884 GenericParam::Type(_) | GenericParam::Const(_) => {
885 if !trailing_or_empty {
886 <Token![,]>::default().to_tokens(tokens);
887 trailing_or_empty = true;
888 }
889 param.to_tokens(tokens);
890 }
891 GenericParam::Lifetime(_) => {}
892 }
893 }
894
Alex Crichton259ee532017-07-14 06:51:02 -0700895 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700896 }
897 }
898
David Tolnaye7678922016-10-13 20:44:03 -0700899 impl<'a> ToTokens for ImplGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700900 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800901 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400902 return;
903 }
904
Alex Crichton259ee532017-07-14 06:51:02 -0700905 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800906
907 // Print lifetimes before types and consts, regardless of their
908 // order in self.params.
909 //
910 // TODO: ordering rules for const parameters vs type parameters have
911 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
912 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800913 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800914 if let GenericParam::Lifetime(_) = **param.value() {
915 param.to_tokens(tokens);
916 trailing_or_empty = param.punct().is_some();
917 }
918 }
919 for param in self.0.params.pairs() {
920 if let GenericParam::Lifetime(_) = **param.value() {
921 continue;
922 }
923 if !trailing_or_empty {
924 <Token![,]>::default().to_tokens(tokens);
925 trailing_or_empty = true;
926 }
David Tolnay56080682018-01-06 14:01:52 -0800927 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800928 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800929 GenericParam::Type(ref param) => {
930 // Leave off the type parameter defaults
931 tokens.append_all(param.attrs.outer());
932 param.ident.to_tokens(tokens);
933 if !param.bounds.is_empty() {
934 TokensOrDefault(&param.colon_token).to_tokens(tokens);
935 param.bounds.to_tokens(tokens);
936 }
937 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500938 GenericParam::Const(ref param) => {
939 // Leave off the const parameter defaults
940 tokens.append_all(param.attrs.outer());
941 param.const_token.to_tokens(tokens);
942 param.ident.to_tokens(tokens);
943 param.colon_token.to_tokens(tokens);
944 param.ty.to_tokens(tokens);
945 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400946 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500947 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700948 }
David Tolnay225aca62018-01-11 20:51:46 -0800949
Alex Crichton259ee532017-07-14 06:51:02 -0700950 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700951 }
952 }
953
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800954 impl<'a> ToTokens for TypeGenerics<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700955 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -0800956 if self.0.params.is_empty() {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400957 return;
958 }
959
Alex Crichton259ee532017-07-14 06:51:02 -0700960 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay225aca62018-01-11 20:51:46 -0800961
962 // Print lifetimes before types and consts, regardless of their
963 // order in self.params.
964 //
965 // TODO: ordering rules for const parameters vs type parameters have
966 // not been settled yet. https://github.com/rust-lang/rust/issues/44580
967 let mut trailing_or_empty = true;
David Tolnay56080682018-01-06 14:01:52 -0800968 for param in self.0.params.pairs() {
David Tolnay225aca62018-01-11 20:51:46 -0800969 if let GenericParam::Lifetime(ref def) = **param.value() {
970 // Leave off the lifetime bounds and attributes
971 def.lifetime.to_tokens(tokens);
972 param.punct().to_tokens(tokens);
973 trailing_or_empty = param.punct().is_some();
974 }
975 }
976 for param in self.0.params.pairs() {
977 if let GenericParam::Lifetime(_) = **param.value() {
978 continue;
979 }
980 if !trailing_or_empty {
981 <Token![,]>::default().to_tokens(tokens);
982 trailing_or_empty = true;
983 }
David Tolnay56080682018-01-06 14:01:52 -0800984 match **param.value() {
David Tolnay225aca62018-01-11 20:51:46 -0800985 GenericParam::Lifetime(_) => unreachable!(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800986 GenericParam::Type(ref param) => {
987 // Leave off the type parameter defaults
988 param.ident.to_tokens(tokens);
989 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500990 GenericParam::Const(ref param) => {
991 // Leave off the const parameter defaults
992 param.ident.to_tokens(tokens);
993 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800994 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500995 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700996 }
David Tolnay225aca62018-01-11 20:51:46 -0800997
Alex Crichton259ee532017-07-14 06:51:02 -0700998 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700999 }
1000 }
1001
David Tolnayc879a502017-01-25 15:51:32 -08001002 impl<'a> ToTokens for Turbofish<'a> {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001003 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay7c6e0f42018-01-11 20:52:52 -08001004 if !self.0.params.is_empty() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08001005 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001006 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -08001007 }
1008 }
1009 }
1010
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001011 impl ToTokens for BoundLifetimes {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001012 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001013 self.for_token.to_tokens(tokens);
1014 self.lt_token.to_tokens(tokens);
1015 self.lifetimes.to_tokens(tokens);
1016 self.gt_token.to_tokens(tokens);
1017 }
1018 }
1019
David Tolnay87d0b442016-09-04 11:52:12 -07001020 impl ToTokens for LifetimeDef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001021 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001022 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -07001023 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001024 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001025 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001026 self.bounds.to_tokens(tokens);
1027 }
David Tolnay87d0b442016-09-04 11:52:12 -07001028 }
1029 }
1030
David Tolnayfd6bf5c2017-11-12 09:41:14 -08001031 impl ToTokens for TypeParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001032 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaye7678922016-10-13 20:44:03 -07001033 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -07001034 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001035 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07001036 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001037 self.bounds.to_tokens(tokens);
1038 }
1039 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07001040 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04001041 self.default.to_tokens(tokens);
1042 }
David Tolnay8ef93042016-09-04 14:08:40 -07001043 }
1044 }
1045
David Tolnay40fb8ce2018-01-02 10:53:46 -08001046 impl ToTokens for TraitBound {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001047 fn to_tokens(&self, tokens: &mut TokenStream) {
1048 let to_tokens = |tokens: &mut TokenStream| {
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001049 self.modifier.to_tokens(tokens);
1050 self.lifetimes.to_tokens(tokens);
1051 self.path.to_tokens(tokens);
1052 };
1053 match self.paren_token {
David Tolnay997c6cb2018-03-31 22:49:52 +02001054 Some(ref paren) => paren.surround(tokens, to_tokens),
David Tolnayc1f5d5d2018-03-31 22:17:56 +02001055 None => to_tokens(tokens),
1056 }
David Tolnay55337722016-09-11 12:58:56 -07001057 }
1058 }
1059
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001060 impl ToTokens for TraitBoundModifier {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001061 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001062 match *self {
1063 TraitBoundModifier::None => {}
1064 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
1065 }
1066 }
1067 }
1068
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001069 impl ToTokens for ConstParam {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001070 fn to_tokens(&self, tokens: &mut TokenStream) {
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001071 tokens.append_all(self.attrs.outer());
1072 self.const_token.to_tokens(tokens);
1073 self.ident.to_tokens(tokens);
1074 self.colon_token.to_tokens(tokens);
1075 self.ty.to_tokens(tokens);
1076 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -08001077 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -05001078 self.default.to_tokens(tokens);
1079 }
1080 }
1081 }
1082
David Tolnay55337722016-09-11 12:58:56 -07001083 impl ToTokens for WhereClause {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001084 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2a0b02f2018-03-09 00:50:45 -08001085 if !self.predicates.is_empty() {
1086 self.where_token.to_tokens(tokens);
1087 self.predicates.to_tokens(tokens);
1088 }
David Tolnay87d0b442016-09-04 11:52:12 -07001089 }
1090 }
David Tolnay8ef93042016-09-04 14:08:40 -07001091
David Tolnayd4add852018-01-01 20:13:24 -08001092 impl ToTokens for PredicateType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001093 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay40fb8ce2018-01-02 10:53:46 -08001094 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001095 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001096 self.colon_token.to_tokens(tokens);
1097 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001098 }
1099 }
1100
David Tolnayd4add852018-01-01 20:13:24 -08001101 impl ToTokens for PredicateLifetime {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001102 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay8ef93042016-09-04 14:08:40 -07001103 self.lifetime.to_tokens(tokens);
David Tolnay1b8e2852018-08-26 08:25:18 -04001104 self.colon_token.to_tokens(tokens);
1105 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -07001106 }
1107 }
David Tolnayf8e08832017-01-23 00:04:32 -08001108
David Tolnayd4add852018-01-01 20:13:24 -08001109 impl ToTokens for PredicateEq {
Alex Crichtona74a1c82018-05-16 10:20:44 -07001110 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayf8e08832017-01-23 00:04:32 -08001111 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001112 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -08001113 self.rhs_ty.to_tokens(tokens);
1114 }
1115 }
David Tolnay87d0b442016-09-04 11:52:12 -07001116}