blob: 08dba3902e8fc9629b09d7d3021b8ffb144ee79d [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002use delimited::Delimited;
David Tolnayb79ee962016-09-04 09:39:20 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
5 /// Represents lifetimes and type parameters attached to a declaration
6 /// of a function, enum, trait, etc.
7 #[derive(Default)]
8 pub struct Generics {
David Tolnayf8db7ba2017-11-11 22:52:16 -08009 pub lt_token: Option<Token![<]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080010 pub params: Delimited<GenericParam, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080011 pub gt_token: Option<Token![>]>,
Alex Crichton62a0a592017-05-22 13:58:53 -070012 pub where_clause: WhereClause,
13 }
David Tolnayb79ee962016-09-04 09:39:20 -070014}
15
David Tolnayc2f1aba2017-11-12 20:29:22 -080016ast_enum_of_structs! {
17 pub enum GenericParam {
18 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
19 pub Lifetime(LifetimeDef {
20 pub attrs: Vec<Attribute>,
21 pub lifetime: Lifetime,
22 pub colon_token: Option<Token![:]>,
23 pub bounds: Delimited<Lifetime, Token![+]>,
24 }),
25 /// A generic type parameter, e.g. `T: Into<String>`.
26 pub Type(TypeParam {
27 pub attrs: Vec<Attribute>,
28 pub ident: Ident,
29 pub colon_token: Option<Token![:]>,
30 pub bounds: Delimited<TypeParamBound, Token![+]>,
31 pub eq_token: Option<Token![=]>,
32 pub default: Option<Type>,
33 }),
34 }
35}
36
David Tolnaye7678922016-10-13 20:44:03 -070037#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040038#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
39#[cfg_attr(feature = "clone-impls", derive(Clone))]
40/// Returned by `Generics::split_for_impl`.
41pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070042
43#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040044#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
45#[cfg_attr(feature = "clone-impls", derive(Clone))]
46/// Returned by `Generics::split_for_impl`.
David Tolnayfd6bf5c2017-11-12 09:41:14 -080047pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070048
David Tolnayc879a502017-01-25 15:51:32 -080049#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040050#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
51#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080052/// Returned by `TypeGenerics::as_turbofish`.
Nika Layzell6b38b132017-10-24 23:09:39 -040053pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -080054
David Tolnaye95cc9f2017-01-25 15:57:09 -080055#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -070056impl Generics {
57 /// Split a type's generics into the pieces required for impl'ing a trait
58 /// for that type.
59 ///
60 /// ```
61 /// # extern crate syn;
62 /// # #[macro_use]
63 /// # extern crate quote;
64 /// # fn main() {
65 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -070066 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -070067 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
68 /// quote! {
69 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
70 /// // ...
71 /// }
72 /// }
73 /// # ;
74 /// # }
75 /// ```
David Tolnayfd6bf5c2017-11-12 09:41:14 -080076 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, &WhereClause) {
77 (ImplGenerics(self), TypeGenerics(self), &self.where_clause)
David Tolnayb153dbc2016-10-04 23:39:10 -070078 }
79}
80
David Tolnaye95cc9f2017-01-25 15:57:09 -080081#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080082impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -080083 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
84 pub fn as_turbofish(&self) -> Turbofish {
85 Turbofish(self.0)
86 }
87}
88
Alex Crichton62a0a592017-05-22 13:58:53 -070089ast_struct! {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070090 /// A set of bound lifetimes, e.g. `for<'a, 'b, 'c>`
91 #[derive(Default)]
92 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -080093 pub for_token: Token![for],
94 pub lt_token: Token![<],
95 pub lifetimes: Delimited<LifetimeDef, Token![,]>,
96 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -070097 }
98}
99
David Tolnayf9505b52016-10-02 09:18:52 -0700100impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700101 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700102 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700103 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700104 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700105 colon_token: None,
106 bounds: Delimited::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700107 }
108 }
109}
110
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800111impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700112 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800113 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700114 attrs: vec![],
115 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700116 colon_token: None,
117 bounds: Delimited::new(),
118 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700119 default: None,
120 }
121 }
122}
123
Alex Crichton62a0a592017-05-22 13:58:53 -0700124ast_enum! {
125 /// The AST represents all type param bounds as types.
126 /// `typeck::collect::compute_bounds` matches these against
127 /// the "special" built-in traits (see `middle::lang_items`) and
128 /// detects Copy, Send and Sync.
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800129 pub enum TypeParamBound {
Alex Crichton62a0a592017-05-22 13:58:53 -0700130 Trait(PolyTraitRef, TraitBoundModifier),
131 Region(Lifetime),
132 }
David Tolnay55337722016-09-11 12:58:56 -0700133}
134
Alex Crichton62a0a592017-05-22 13:58:53 -0700135ast_enum! {
136 /// A modifier on a bound, currently this is only used for `?Sized`, where the
137 /// modifier is `Maybe`. Negative bounds should also be handled here.
Alex Crichton2e0229c2017-05-23 09:34:50 -0700138 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub enum TraitBoundModifier {
140 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800141 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700142 }
David Tolnay55337722016-09-11 12:58:56 -0700143}
144
Alex Crichton62a0a592017-05-22 13:58:53 -0700145ast_struct! {
146 /// A `where` clause in a definition
147 #[derive(Default)]
148 pub struct WhereClause {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800149 pub where_token: Option<Token![where]>,
150 pub predicates: Delimited<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700151 }
David Tolnayb79ee962016-09-04 09:39:20 -0700152}
153
David Tolnayb153dbc2016-10-04 23:39:10 -0700154impl WhereClause {
155 pub fn none() -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700156 WhereClause::default()
David Tolnayb153dbc2016-10-04 23:39:10 -0700157 }
158}
159
Alex Crichton62a0a592017-05-22 13:58:53 -0700160ast_enum_of_structs! {
161 /// A single predicate in a `where` clause
162 pub enum WherePredicate {
163 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
164 pub BoundPredicate(WhereBoundPredicate {
165 /// Any lifetimes from a `for` binding
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700166 pub bound_lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700167 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800168 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800169 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700170 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800171 pub bounds: Delimited<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700173
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 /// A lifetime predicate, e.g. `'a: 'b+'c`
175 pub RegionPredicate(WhereRegionPredicate {
176 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800177 pub colon_token: Option<Token![:]>,
178 pub bounds: Delimited<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700179 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700180
Alex Crichton62a0a592017-05-22 13:58:53 -0700181 /// An equality predicate (unsupported)
182 pub EqPredicate(WhereEqPredicate {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800183 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800184 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800185 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700186 }),
187 }
David Tolnayf8e08832017-01-23 00:04:32 -0800188}
189
David Tolnay86eca752016-09-04 11:26:41 -0700190#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700191pub mod parsing {
192 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700193
David Tolnay63e3dee2017-06-03 20:13:17 -0700194 use synom::Synom;
David Tolnayc2f1aba2017-11-12 20:29:22 -0800195 use synom::delimited::Element;
Alex Crichton954046c2017-05-30 21:49:42 -0700196
197 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400198 named!(parse -> Self, map!(
199 alt!(
200 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800201 lt: punct!(<) >>
David Tolnayc2f1aba2017-11-12 20:29:22 -0800202 lifetimes: call!(Delimited::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400203 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800204 lifetimes.empty_or_trailing(),
205 call!(Delimited::<TypeParam, Token![,]>::parse_terminated)
Michael Layzell92639a52017-06-01 00:07:44 -0400206 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800207 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400208 (lifetimes, ty_params, Some(lt), Some(gt))
209 )
210 |
211 epsilon!() => { |_| (Delimited::new(), None, None, None) }
212 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700213 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400214 lt_token: lt,
David Tolnayc2f1aba2017-11-12 20:29:22 -0800215 params: lifetimes.into_iter()
216 .map(Element::into_tuple)
217 .map(|(lifetime, comma)| (GenericParam::Lifetime(lifetime), comma))
218 .chain(ty_params.unwrap_or_default()
219 .into_iter()
220 .map(Element::into_tuple)
221 .map(|(ty_param, comma)| (GenericParam::Type(ty_param), comma)))
222 .collect::<Vec<_>>()
223 .into(),
224 gt_token: gt,
225 where_clause: WhereClause::default(),
Michael Layzell416724e2017-05-24 21:12:34 -0400226 }
Michael Layzell92639a52017-06-01 00:07:44 -0400227 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700228 }
229
Alex Crichton954046c2017-05-30 21:49:42 -0700230 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400231 named!(parse -> Self, do_parse!(
232 attrs: many0!(call!(Attribute::parse_outer)) >>
233 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800234 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400235 bounds: cond!(
236 colon.is_some(),
237 call!(Delimited::parse_separated_nonempty)
238 ) >>
239 (LifetimeDef {
240 attrs: attrs,
241 lifetime: life,
242 bounds: bounds.unwrap_or_default(),
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 colon_token: colon.map(|_| <Token![:]>::default()),
Michael Layzell92639a52017-06-01 00:07:44 -0400244 })
245 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700246 }
247
248 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400249 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800250 for_: keyword!(for) >>
251 lt: punct!(<) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400252 lifetimes: call!(Delimited::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800253 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400254 (BoundLifetimes {
255 for_token: for_,
256 lt_token: lt,
257 gt_token: gt,
258 lifetimes: lifetimes,
259 })
260 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700261 }
David Tolnay55337722016-09-11 12:58:56 -0700262
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800263 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400264 named!(parse -> Self, do_parse!(
265 attrs: many0!(call!(Attribute::parse_outer)) >>
266 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800267 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400268 bounds: cond!(
269 colon.is_some(),
270 call!(Delimited::parse_separated_nonempty)
271 ) >>
272 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800273 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800274 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400275 (eq, ty)
276 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800277 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400278 attrs: attrs,
279 ident: id,
280 bounds: bounds.unwrap_or_default(),
281 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800282 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400283 default: default.map(|d| d.1),
284 })
285 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700286 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700287
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800288 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400289 named!(parse -> Self, alt!(
290 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800291 question: punct!(?) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400292 poly: syn!(PolyTraitRef) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800293 (TypeParamBound::Trait(poly, TraitBoundModifier::Maybe(question)))
Michael Layzell92639a52017-06-01 00:07:44 -0400294 )
295 |
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800296 syn!(Lifetime) => { TypeParamBound::Region }
Michael Layzell92639a52017-06-01 00:07:44 -0400297 |
298 syn!(PolyTraitRef) => {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800299 |poly| TypeParamBound::Trait(poly, TraitBoundModifier::None)
Alex Crichton954046c2017-05-30 21:49:42 -0700300 }
Michael Layzell92639a52017-06-01 00:07:44 -0400301 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700302
303 fn description() -> Option<&'static str> {
304 Some("type parameter buond")
305 }
306 }
307
308 impl Synom for WhereClause {
Michael Layzell92639a52017-06-01 00:07:44 -0400309 named!(parse -> Self, alt!(
310 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800311 where_: keyword!(where) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400312 predicates: call!(Delimited::parse_terminated) >>
313 (WhereClause {
314 predicates: predicates,
315 where_token: Some(where_),
316 })
317 )
318 |
319 epsilon!() => { |_| WhereClause::default() }
320 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700321
322 fn description() -> Option<&'static str> {
323 Some("where clause")
324 }
325 }
326
327 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400328 named!(parse -> Self, alt!(
329 do_parse!(
330 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800331 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400332 bounds: cond!(
333 colon.is_some(),
334 call!(Delimited::parse_separated)
335 ) >>
336 (WherePredicate::RegionPredicate(WhereRegionPredicate {
337 lifetime: ident,
338 bounds: bounds.unwrap_or_default(),
339 colon_token: colon,
340 }))
341 )
342 |
343 do_parse!(
344 bound_lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800345 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800346 colon: punct!(:) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400347 bounds: call!(Delimited::parse_separated_nonempty) >>
348 (WherePredicate::BoundPredicate(WhereBoundPredicate {
349 bound_lifetimes: bound_lifetimes,
350 bounded_ty: bounded_ty,
351 bounds: bounds,
352 colon_token: colon,
353 }))
354 )
355 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700356 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700357}
David Tolnay87d0b442016-09-04 11:52:12 -0700358
359#[cfg(feature = "printing")]
360mod printing {
361 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700362 use attr::FilterAttrs;
David Tolnay87d0b442016-09-04 11:52:12 -0700363 use quote::{Tokens, ToTokens};
364
Michael Layzell3936ceb2017-07-08 00:28:36 -0400365 /// Returns true if the generics object has no lifetimes or ty_params.
366 fn empty_normal_generics(generics: &Generics) -> bool {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800367 generics.params.is_empty()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400368 }
369
David Tolnay8ef93042016-09-04 14:08:40 -0700370 impl ToTokens for Generics {
371 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400372 if empty_normal_generics(self) {
373 return;
374 }
375
Alex Crichton259ee532017-07-14 06:51:02 -0700376 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800377 self.params.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700378 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700379 }
380 }
381
David Tolnaye7678922016-10-13 20:44:03 -0700382 impl<'a> ToTokens for ImplGenerics<'a> {
383 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400384 if empty_normal_generics(&self.0) {
385 return;
386 }
387
Alex Crichton259ee532017-07-14 06:51:02 -0700388 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800389 for param in self.0.params.iter() {
390 match **param.item() {
391 GenericParam::Lifetime(ref param) => {
392 param.to_tokens(tokens);
393 }
394 GenericParam::Type(ref param) => {
395 // Leave off the type parameter defaults
396 tokens.append_all(param.attrs.outer());
397 param.ident.to_tokens(tokens);
398 if !param.bounds.is_empty() {
399 TokensOrDefault(&param.colon_token).to_tokens(tokens);
400 param.bounds.to_tokens(tokens);
401 }
402 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400403 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700404 param.delimiter().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700405 }
Alex Crichton259ee532017-07-14 06:51:02 -0700406 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700407 }
408 }
409
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800410 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700411 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400412 if empty_normal_generics(&self.0) {
413 return;
414 }
415
Alex Crichton259ee532017-07-14 06:51:02 -0700416 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800417 for param in self.0.params.iter() {
418 match **param.item() {
419 GenericParam::Lifetime(ref param) => {
420 // Leave off the lifetime bounds and attributes
421 param.lifetime.to_tokens(tokens);
422 }
423 GenericParam::Type(ref param) => {
424 // Leave off the type parameter defaults
425 param.ident.to_tokens(tokens);
426 }
427 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700428 param.delimiter().to_tokens(tokens);
429 }
Alex Crichton259ee532017-07-14 06:51:02 -0700430 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700431 }
432 }
433
David Tolnayc879a502017-01-25 15:51:32 -0800434 impl<'a> ToTokens for Turbofish<'a> {
435 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400436 if !empty_normal_generics(&self.0) {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800437 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800438 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800439 }
440 }
441 }
442
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700443 impl ToTokens for BoundLifetimes {
444 fn to_tokens(&self, tokens: &mut Tokens) {
445 self.for_token.to_tokens(tokens);
446 self.lt_token.to_tokens(tokens);
447 self.lifetimes.to_tokens(tokens);
448 self.gt_token.to_tokens(tokens);
449 }
450 }
451
David Tolnay87d0b442016-09-04 11:52:12 -0700452 impl ToTokens for LifetimeDef {
453 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700454 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700455 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400456 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700457 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400458 self.bounds.to_tokens(tokens);
459 }
David Tolnay87d0b442016-09-04 11:52:12 -0700460 }
461 }
462
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800463 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700464 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700465 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700466 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400467 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700468 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400469 self.bounds.to_tokens(tokens);
470 }
471 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700472 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400473 self.default.to_tokens(tokens);
474 }
David Tolnay8ef93042016-09-04 14:08:40 -0700475 }
476 }
477
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800478 impl ToTokens for TypeParamBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700479 fn to_tokens(&self, tokens: &mut Tokens) {
480 match *self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800481 TypeParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
482 TypeParamBound::Trait(ref trait_ref, ref modifier) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700483 modifier.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700484 trait_ref.to_tokens(tokens);
485 }
486 }
487 }
488 }
489
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700490 impl ToTokens for TraitBoundModifier {
491 fn to_tokens(&self, tokens: &mut Tokens) {
492 match *self {
493 TraitBoundModifier::None => {}
494 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
495 }
496 }
497 }
498
David Tolnay55337722016-09-11 12:58:56 -0700499 impl ToTokens for WhereClause {
500 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400501 if !self.predicates.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700502 TokensOrDefault(&self.where_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400503 self.predicates.to_tokens(tokens);
504 }
David Tolnay87d0b442016-09-04 11:52:12 -0700505 }
506 }
David Tolnay8ef93042016-09-04 14:08:40 -0700507
David Tolnay8ef93042016-09-04 14:08:40 -0700508 impl ToTokens for WhereBoundPredicate {
509 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700510 self.bound_lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700511 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700512 self.colon_token.to_tokens(tokens);
513 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700514 }
515 }
516
517 impl ToTokens for WhereRegionPredicate {
518 fn to_tokens(&self, tokens: &mut Tokens) {
519 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400520 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700521 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400522 self.bounds.to_tokens(tokens);
523 }
David Tolnay8ef93042016-09-04 14:08:40 -0700524 }
525 }
David Tolnayf8e08832017-01-23 00:04:32 -0800526
527 impl ToTokens for WhereEqPredicate {
528 fn to_tokens(&self, tokens: &mut Tokens) {
529 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700530 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800531 self.rhs_ty.to_tokens(tokens);
532 }
533 }
David Tolnay87d0b442016-09-04 11:52:12 -0700534}