1 | use super::*; |
2 | use crate::punctuated::{Iter, IterMut, Punctuated}; |
3 | #[cfg (all(feature = "printing" , feature = "extra-traits" ))] |
4 | use std::fmt::{self, Debug}; |
5 | #[cfg (all(feature = "printing" , feature = "extra-traits" ))] |
6 | use std::hash::{Hash, Hasher}; |
7 | |
8 | ast_struct! { |
9 | /// Lifetimes and type parameters attached to a declaration of a function, |
10 | /// enum, trait, etc. |
11 | /// |
12 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
13 | /// feature.* |
14 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
15 | pub struct Generics { |
16 | pub lt_token: Option<Token![<]>, |
17 | pub params: Punctuated<GenericParam, Token![,]>, |
18 | pub gt_token: Option<Token![>]>, |
19 | pub where_clause: Option<WhereClause>, |
20 | } |
21 | } |
22 | |
23 | ast_enum_of_structs! { |
24 | /// A generic type parameter, lifetime, or const generic: `T: Into<String>`, |
25 | /// `'a: 'b`, `const LEN: usize`. |
26 | /// |
27 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
28 | /// feature.* |
29 | /// |
30 | /// # Syntax tree enum |
31 | /// |
32 | /// This type is a [syntax tree enum]. |
33 | /// |
34 | /// [syntax tree enum]: Expr#syntax-tree-enums |
35 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
36 | pub enum GenericParam { |
37 | /// A generic type parameter: `T: Into<String>`. |
38 | Type(TypeParam), |
39 | |
40 | /// A lifetime definition: `'a: 'b + 'c + 'd`. |
41 | Lifetime(LifetimeDef), |
42 | |
43 | /// A const generic parameter: `const LENGTH: usize`. |
44 | Const(ConstParam), |
45 | } |
46 | } |
47 | |
48 | ast_struct! { |
49 | /// A generic type parameter: `T: Into<String>`. |
50 | /// |
51 | /// *This type is available only if Syn is built with the `"derive"` or |
52 | /// `"full"` feature.* |
53 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
54 | pub struct TypeParam { |
55 | pub attrs: Vec<Attribute>, |
56 | pub ident: Ident, |
57 | pub colon_token: Option<Token![:]>, |
58 | pub bounds: Punctuated<TypeParamBound, Token![+]>, |
59 | pub eq_token: Option<Token![=]>, |
60 | pub default: Option<Type>, |
61 | } |
62 | } |
63 | |
64 | ast_struct! { |
65 | /// A lifetime definition: `'a: 'b + 'c + 'd`. |
66 | /// |
67 | /// *This type is available only if Syn is built with the `"derive"` or |
68 | /// `"full"` feature.* |
69 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
70 | pub struct LifetimeDef { |
71 | pub attrs: Vec<Attribute>, |
72 | pub lifetime: Lifetime, |
73 | pub colon_token: Option<Token![:]>, |
74 | pub bounds: Punctuated<Lifetime, Token![+]>, |
75 | } |
76 | } |
77 | |
78 | ast_struct! { |
79 | /// A const generic parameter: `const LENGTH: usize`. |
80 | /// |
81 | /// *This type is available only if Syn is built with the `"derive"` or |
82 | /// `"full"` feature.* |
83 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
84 | pub struct ConstParam { |
85 | pub attrs: Vec<Attribute>, |
86 | pub const_token: Token![const], |
87 | pub ident: Ident, |
88 | pub colon_token: Token![:], |
89 | pub ty: Type, |
90 | pub eq_token: Option<Token![=]>, |
91 | pub default: Option<Expr>, |
92 | } |
93 | } |
94 | |
95 | impl Default for Generics { |
96 | fn default() -> Self { |
97 | Generics { |
98 | lt_token: None, |
99 | params: Punctuated::new(), |
100 | gt_token: None, |
101 | where_clause: None, |
102 | } |
103 | } |
104 | } |
105 | |
106 | impl Generics { |
107 | /// Returns an |
108 | /// <code |
109 | /// style="padding-right:0;">Iterator<Item = &</code><a |
110 | /// href="struct.TypeParam.html"><code |
111 | /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code |
112 | /// style="padding-left:0;">></code> |
113 | /// over the type parameters in `self.params`. |
114 | pub fn type_params(&self) -> TypeParams { |
115 | TypeParams(self.params.iter()) |
116 | } |
117 | |
118 | /// Returns an |
119 | /// <code |
120 | /// style="padding-right:0;">Iterator<Item = &mut </code><a |
121 | /// href="struct.TypeParam.html"><code |
122 | /// style="padding-left:0;padding-right:0;">TypeParam</code></a><code |
123 | /// style="padding-left:0;">></code> |
124 | /// over the type parameters in `self.params`. |
125 | pub fn type_params_mut(&mut self) -> TypeParamsMut { |
126 | TypeParamsMut(self.params.iter_mut()) |
127 | } |
128 | |
129 | /// Returns an |
130 | /// <code |
131 | /// style="padding-right:0;">Iterator<Item = &</code><a |
132 | /// href="struct.LifetimeDef.html"><code |
133 | /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code |
134 | /// style="padding-left:0;">></code> |
135 | /// over the lifetime parameters in `self.params`. |
136 | pub fn lifetimes(&self) -> Lifetimes { |
137 | Lifetimes(self.params.iter()) |
138 | } |
139 | |
140 | /// Returns an |
141 | /// <code |
142 | /// style="padding-right:0;">Iterator<Item = &mut </code><a |
143 | /// href="struct.LifetimeDef.html"><code |
144 | /// style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code |
145 | /// style="padding-left:0;">></code> |
146 | /// over the lifetime parameters in `self.params`. |
147 | pub fn lifetimes_mut(&mut self) -> LifetimesMut { |
148 | LifetimesMut(self.params.iter_mut()) |
149 | } |
150 | |
151 | /// Returns an |
152 | /// <code |
153 | /// style="padding-right:0;">Iterator<Item = &</code><a |
154 | /// href="struct.ConstParam.html"><code |
155 | /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code |
156 | /// style="padding-left:0;">></code> |
157 | /// over the constant parameters in `self.params`. |
158 | pub fn const_params(&self) -> ConstParams { |
159 | ConstParams(self.params.iter()) |
160 | } |
161 | |
162 | /// Returns an |
163 | /// <code |
164 | /// style="padding-right:0;">Iterator<Item = &mut </code><a |
165 | /// href="struct.ConstParam.html"><code |
166 | /// style="padding-left:0;padding-right:0;">ConstParam</code></a><code |
167 | /// style="padding-left:0;">></code> |
168 | /// over the constant parameters in `self.params`. |
169 | pub fn const_params_mut(&mut self) -> ConstParamsMut { |
170 | ConstParamsMut(self.params.iter_mut()) |
171 | } |
172 | |
173 | /// Initializes an empty `where`-clause if there is not one present already. |
174 | pub fn make_where_clause(&mut self) -> &mut WhereClause { |
175 | self.where_clause.get_or_insert_with(|| WhereClause { |
176 | where_token: <Token![where]>::default(), |
177 | predicates: Punctuated::new(), |
178 | }) |
179 | } |
180 | } |
181 | |
182 | pub struct TypeParams<'a>(Iter<'a, GenericParam>); |
183 | |
184 | impl<'a> Iterator for TypeParams<'a> { |
185 | type Item = &'a TypeParam; |
186 | |
187 | fn next(&mut self) -> Option<Self::Item> { |
188 | let next = match self.0.next() { |
189 | Some(item) => item, |
190 | None => return None, |
191 | }; |
192 | if let GenericParam::Type(type_param) = next { |
193 | Some(type_param) |
194 | } else { |
195 | self.next() |
196 | } |
197 | } |
198 | } |
199 | |
200 | pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>); |
201 | |
202 | impl<'a> Iterator for TypeParamsMut<'a> { |
203 | type Item = &'a mut TypeParam; |
204 | |
205 | fn next(&mut self) -> Option<Self::Item> { |
206 | let next = match self.0.next() { |
207 | Some(item) => item, |
208 | None => return None, |
209 | }; |
210 | if let GenericParam::Type(type_param) = next { |
211 | Some(type_param) |
212 | } else { |
213 | self.next() |
214 | } |
215 | } |
216 | } |
217 | |
218 | pub struct Lifetimes<'a>(Iter<'a, GenericParam>); |
219 | |
220 | impl<'a> Iterator for Lifetimes<'a> { |
221 | type Item = &'a LifetimeDef; |
222 | |
223 | fn next(&mut self) -> Option<Self::Item> { |
224 | let next = match self.0.next() { |
225 | Some(item) => item, |
226 | None => return None, |
227 | }; |
228 | if let GenericParam::Lifetime(lifetime) = next { |
229 | Some(lifetime) |
230 | } else { |
231 | self.next() |
232 | } |
233 | } |
234 | } |
235 | |
236 | pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>); |
237 | |
238 | impl<'a> Iterator for LifetimesMut<'a> { |
239 | type Item = &'a mut LifetimeDef; |
240 | |
241 | fn next(&mut self) -> Option<Self::Item> { |
242 | let next = match self.0.next() { |
243 | Some(item) => item, |
244 | None => return None, |
245 | }; |
246 | if let GenericParam::Lifetime(lifetime) = next { |
247 | Some(lifetime) |
248 | } else { |
249 | self.next() |
250 | } |
251 | } |
252 | } |
253 | |
254 | pub struct ConstParams<'a>(Iter<'a, GenericParam>); |
255 | |
256 | impl<'a> Iterator for ConstParams<'a> { |
257 | type Item = &'a ConstParam; |
258 | |
259 | fn next(&mut self) -> Option<Self::Item> { |
260 | let next = match self.0.next() { |
261 | Some(item) => item, |
262 | None => return None, |
263 | }; |
264 | if let GenericParam::Const(const_param) = next { |
265 | Some(const_param) |
266 | } else { |
267 | self.next() |
268 | } |
269 | } |
270 | } |
271 | |
272 | pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>); |
273 | |
274 | impl<'a> Iterator for ConstParamsMut<'a> { |
275 | type Item = &'a mut ConstParam; |
276 | |
277 | fn next(&mut self) -> Option<Self::Item> { |
278 | let next = match self.0.next() { |
279 | Some(item) => item, |
280 | None => return None, |
281 | }; |
282 | if let GenericParam::Const(const_param) = next { |
283 | Some(const_param) |
284 | } else { |
285 | self.next() |
286 | } |
287 | } |
288 | } |
289 | |
290 | /// Returned by `Generics::split_for_impl`. |
291 | /// |
292 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
293 | /// feature and the `"printing"` feature.* |
294 | #[cfg (feature = "printing" )] |
295 | #[cfg_attr ( |
296 | doc_cfg, |
297 | doc(cfg(all(any(feature = "full" , feature = "derive" ), feature = "printing" ))) |
298 | )] |
299 | pub struct ImplGenerics<'a>(&'a Generics); |
300 | |
301 | /// Returned by `Generics::split_for_impl`. |
302 | /// |
303 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
304 | /// feature and the `"printing"` feature.* |
305 | #[cfg (feature = "printing" )] |
306 | #[cfg_attr ( |
307 | doc_cfg, |
308 | doc(cfg(all(any(feature = "full" , feature = "derive" ), feature = "printing" ))) |
309 | )] |
310 | pub struct TypeGenerics<'a>(&'a Generics); |
311 | |
312 | /// Returned by `TypeGenerics::as_turbofish`. |
313 | /// |
314 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
315 | /// feature and the `"printing"` feature.* |
316 | #[cfg (feature = "printing" )] |
317 | #[cfg_attr ( |
318 | doc_cfg, |
319 | doc(cfg(all(any(feature = "full" , feature = "derive" ), feature = "printing" ))) |
320 | )] |
321 | pub struct Turbofish<'a>(&'a Generics); |
322 | |
323 | #[cfg (feature = "printing" )] |
324 | impl Generics { |
325 | /// Split a type's generics into the pieces required for impl'ing a trait |
326 | /// for that type. |
327 | /// |
328 | /// ``` |
329 | /// # use proc_macro2::{Span, Ident}; |
330 | /// # use quote::quote; |
331 | /// # |
332 | /// # let generics: syn::Generics = Default::default(); |
333 | /// # let name = Ident::new("MyType" , Span::call_site()); |
334 | /// # |
335 | /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); |
336 | /// quote! { |
337 | /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { |
338 | /// // ... |
339 | /// } |
340 | /// } |
341 | /// # ; |
342 | /// ``` |
343 | /// |
344 | /// *This method is available only if Syn is built with the `"derive"` or |
345 | /// `"full"` feature and the `"printing"` feature.* |
346 | #[cfg_attr ( |
347 | doc_cfg, |
348 | doc(cfg(all(any(feature = "full" , feature = "derive" ), feature = "printing" ))) |
349 | )] |
350 | pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { |
351 | ( |
352 | ImplGenerics(self), |
353 | TypeGenerics(self), |
354 | self.where_clause.as_ref(), |
355 | ) |
356 | } |
357 | } |
358 | |
359 | #[cfg (feature = "printing" )] |
360 | macro_rules! generics_wrapper_impls { |
361 | ($ty:ident) => { |
362 | #[cfg(feature = "clone-impls" )] |
363 | #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls" )))] |
364 | impl<'a> Clone for $ty<'a> { |
365 | fn clone(&self) -> Self { |
366 | $ty(self.0) |
367 | } |
368 | } |
369 | |
370 | #[cfg(feature = "extra-traits" )] |
371 | #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits" )))] |
372 | impl<'a> Debug for $ty<'a> { |
373 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
374 | formatter |
375 | .debug_tuple(stringify!($ty)) |
376 | .field(self.0) |
377 | .finish() |
378 | } |
379 | } |
380 | |
381 | #[cfg(feature = "extra-traits" )] |
382 | #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits" )))] |
383 | impl<'a> Eq for $ty<'a> {} |
384 | |
385 | #[cfg(feature = "extra-traits" )] |
386 | #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits" )))] |
387 | impl<'a> PartialEq for $ty<'a> { |
388 | fn eq(&self, other: &Self) -> bool { |
389 | self.0 == other.0 |
390 | } |
391 | } |
392 | |
393 | #[cfg(feature = "extra-traits" )] |
394 | #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits" )))] |
395 | impl<'a> Hash for $ty<'a> { |
396 | fn hash<H: Hasher>(&self, state: &mut H) { |
397 | self.0.hash(state); |
398 | } |
399 | } |
400 | }; |
401 | } |
402 | |
403 | #[cfg (feature = "printing" )] |
404 | generics_wrapper_impls!(ImplGenerics); |
405 | #[cfg (feature = "printing" )] |
406 | generics_wrapper_impls!(TypeGenerics); |
407 | #[cfg (feature = "printing" )] |
408 | generics_wrapper_impls!(Turbofish); |
409 | |
410 | #[cfg (feature = "printing" )] |
411 | impl<'a> TypeGenerics<'a> { |
412 | /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`. |
413 | /// |
414 | /// *This method is available only if Syn is built with the `"derive"` or |
415 | /// `"full"` feature and the `"printing"` feature.* |
416 | pub fn as_turbofish(&self) -> Turbofish { |
417 | Turbofish(self.0) |
418 | } |
419 | } |
420 | |
421 | ast_struct! { |
422 | /// A set of bound lifetimes: `for<'a, 'b, 'c>`. |
423 | /// |
424 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
425 | /// feature.* |
426 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
427 | pub struct BoundLifetimes { |
428 | pub for_token: Token![for], |
429 | pub lt_token: Token![<], |
430 | pub lifetimes: Punctuated<LifetimeDef, Token![,]>, |
431 | pub gt_token: Token![>], |
432 | } |
433 | } |
434 | |
435 | impl Default for BoundLifetimes { |
436 | fn default() -> Self { |
437 | BoundLifetimes { |
438 | for_token: Default::default(), |
439 | lt_token: Default::default(), |
440 | lifetimes: Punctuated::new(), |
441 | gt_token: Default::default(), |
442 | } |
443 | } |
444 | } |
445 | |
446 | impl LifetimeDef { |
447 | pub fn new(lifetime: Lifetime) -> Self { |
448 | LifetimeDef { |
449 | attrs: Vec::new(), |
450 | lifetime, |
451 | colon_token: None, |
452 | bounds: Punctuated::new(), |
453 | } |
454 | } |
455 | } |
456 | |
457 | impl From<Ident> for TypeParam { |
458 | fn from(ident: Ident) -> Self { |
459 | TypeParam { |
460 | attrs: vec![], |
461 | ident, |
462 | colon_token: None, |
463 | bounds: Punctuated::new(), |
464 | eq_token: None, |
465 | default: None, |
466 | } |
467 | } |
468 | } |
469 | |
470 | ast_enum_of_structs! { |
471 | /// A trait or lifetime used as a bound on a type parameter. |
472 | /// |
473 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
474 | /// feature.* |
475 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
476 | pub enum TypeParamBound { |
477 | Trait(TraitBound), |
478 | Lifetime(Lifetime), |
479 | } |
480 | } |
481 | |
482 | ast_struct! { |
483 | /// A trait used as a bound on a type parameter. |
484 | /// |
485 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
486 | /// feature.* |
487 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
488 | pub struct TraitBound { |
489 | pub paren_token: Option<token::Paren>, |
490 | pub modifier: TraitBoundModifier, |
491 | /// The `for<'a>` in `for<'a> Foo<&'a T>` |
492 | pub lifetimes: Option<BoundLifetimes>, |
493 | /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>` |
494 | pub path: Path, |
495 | } |
496 | } |
497 | |
498 | ast_enum! { |
499 | /// A modifier on a trait bound, currently only used for the `?` in |
500 | /// `?Sized`. |
501 | /// |
502 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
503 | /// feature.* |
504 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
505 | pub enum TraitBoundModifier { |
506 | None, |
507 | Maybe(Token![?]), |
508 | } |
509 | } |
510 | |
511 | ast_struct! { |
512 | /// A `where` clause in a definition: `where T: Deserialize<'de>, D: |
513 | /// 'static`. |
514 | /// |
515 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
516 | /// feature.* |
517 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
518 | pub struct WhereClause { |
519 | pub where_token: Token![where], |
520 | pub predicates: Punctuated<WherePredicate, Token![,]>, |
521 | } |
522 | } |
523 | |
524 | ast_enum_of_structs! { |
525 | /// A single predicate in a `where` clause: `T: Deserialize<'de>`. |
526 | /// |
527 | /// *This type is available only if Syn is built with the `"derive"` or `"full"` |
528 | /// feature.* |
529 | /// |
530 | /// # Syntax tree enum |
531 | /// |
532 | /// This type is a [syntax tree enum]. |
533 | /// |
534 | /// [syntax tree enum]: Expr#syntax-tree-enums |
535 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
536 | pub enum WherePredicate { |
537 | /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. |
538 | Type(PredicateType), |
539 | |
540 | /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. |
541 | Lifetime(PredicateLifetime), |
542 | |
543 | /// An equality predicate in a `where` clause (unsupported). |
544 | Eq(PredicateEq), |
545 | } |
546 | } |
547 | |
548 | ast_struct! { |
549 | /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. |
550 | /// |
551 | /// *This type is available only if Syn is built with the `"derive"` or |
552 | /// `"full"` feature.* |
553 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
554 | pub struct PredicateType { |
555 | /// Any lifetimes from a `for` binding |
556 | pub lifetimes: Option<BoundLifetimes>, |
557 | /// The type being bounded |
558 | pub bounded_ty: Type, |
559 | pub colon_token: Token![:], |
560 | /// Trait and lifetime bounds (`Clone+Send+'static`) |
561 | pub bounds: Punctuated<TypeParamBound, Token![+]>, |
562 | } |
563 | } |
564 | |
565 | ast_struct! { |
566 | /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. |
567 | /// |
568 | /// *This type is available only if Syn is built with the `"derive"` or |
569 | /// `"full"` feature.* |
570 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
571 | pub struct PredicateLifetime { |
572 | pub lifetime: Lifetime, |
573 | pub colon_token: Token![:], |
574 | pub bounds: Punctuated<Lifetime, Token![+]>, |
575 | } |
576 | } |
577 | |
578 | ast_struct! { |
579 | /// An equality predicate in a `where` clause (unsupported). |
580 | /// |
581 | /// *This type is available only if Syn is built with the `"derive"` or |
582 | /// `"full"` feature.* |
583 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
584 | pub struct PredicateEq { |
585 | pub lhs_ty: Type, |
586 | pub eq_token: Token![=], |
587 | pub rhs_ty: Type, |
588 | } |
589 | } |
590 | |
591 | #[cfg (feature = "parsing" )] |
592 | pub mod parsing { |
593 | use super::*; |
594 | use crate::ext::IdentExt; |
595 | use crate::parse::{Parse, ParseStream, Result}; |
596 | |
597 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
598 | impl Parse for Generics { |
599 | fn parse(input: ParseStream) -> Result<Self> { |
600 | if !input.peek(Token![<]) { |
601 | return Ok(Generics::default()); |
602 | } |
603 | |
604 | let lt_token: Token![<] = input.parse()?; |
605 | |
606 | let mut params = Punctuated::new(); |
607 | loop { |
608 | if input.peek(Token![>]) { |
609 | break; |
610 | } |
611 | |
612 | let attrs = input.call(Attribute::parse_outer)?; |
613 | let lookahead = input.lookahead1(); |
614 | if lookahead.peek(Lifetime) { |
615 | params.push_value(GenericParam::Lifetime(LifetimeDef { |
616 | attrs, |
617 | ..input.parse()? |
618 | })); |
619 | } else if lookahead.peek(Ident) { |
620 | params.push_value(GenericParam::Type(TypeParam { |
621 | attrs, |
622 | ..input.parse()? |
623 | })); |
624 | } else if lookahead.peek(Token![const]) { |
625 | params.push_value(GenericParam::Const(ConstParam { |
626 | attrs, |
627 | ..input.parse()? |
628 | })); |
629 | } else if input.peek(Token![_]) { |
630 | params.push_value(GenericParam::Type(TypeParam { |
631 | attrs, |
632 | ident: input.call(Ident::parse_any)?, |
633 | colon_token: None, |
634 | bounds: Punctuated::new(), |
635 | eq_token: None, |
636 | default: None, |
637 | })); |
638 | } else { |
639 | return Err(lookahead.error()); |
640 | } |
641 | |
642 | if input.peek(Token![>]) { |
643 | break; |
644 | } |
645 | let punct = input.parse()?; |
646 | params.push_punct(punct); |
647 | } |
648 | |
649 | let gt_token: Token![>] = input.parse()?; |
650 | |
651 | Ok(Generics { |
652 | lt_token: Some(lt_token), |
653 | params, |
654 | gt_token: Some(gt_token), |
655 | where_clause: None, |
656 | }) |
657 | } |
658 | } |
659 | |
660 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
661 | impl Parse for GenericParam { |
662 | fn parse(input: ParseStream) -> Result<Self> { |
663 | let attrs = input.call(Attribute::parse_outer)?; |
664 | |
665 | let lookahead = input.lookahead1(); |
666 | if lookahead.peek(Ident) { |
667 | Ok(GenericParam::Type(TypeParam { |
668 | attrs, |
669 | ..input.parse()? |
670 | })) |
671 | } else if lookahead.peek(Lifetime) { |
672 | Ok(GenericParam::Lifetime(LifetimeDef { |
673 | attrs, |
674 | ..input.parse()? |
675 | })) |
676 | } else if lookahead.peek(Token![const]) { |
677 | Ok(GenericParam::Const(ConstParam { |
678 | attrs, |
679 | ..input.parse()? |
680 | })) |
681 | } else { |
682 | Err(lookahead.error()) |
683 | } |
684 | } |
685 | } |
686 | |
687 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
688 | impl Parse for LifetimeDef { |
689 | fn parse(input: ParseStream) -> Result<Self> { |
690 | let has_colon; |
691 | Ok(LifetimeDef { |
692 | attrs: input.call(Attribute::parse_outer)?, |
693 | lifetime: input.parse()?, |
694 | colon_token: { |
695 | if input.peek(Token![:]) { |
696 | has_colon = true; |
697 | Some(input.parse()?) |
698 | } else { |
699 | has_colon = false; |
700 | None |
701 | } |
702 | }, |
703 | bounds: { |
704 | let mut bounds = Punctuated::new(); |
705 | if has_colon { |
706 | loop { |
707 | if input.peek(Token![,]) || input.peek(Token![>]) { |
708 | break; |
709 | } |
710 | let value = input.parse()?; |
711 | bounds.push_value(value); |
712 | if !input.peek(Token![+]) { |
713 | break; |
714 | } |
715 | let punct = input.parse()?; |
716 | bounds.push_punct(punct); |
717 | } |
718 | } |
719 | bounds |
720 | }, |
721 | }) |
722 | } |
723 | } |
724 | |
725 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
726 | impl Parse for BoundLifetimes { |
727 | fn parse(input: ParseStream) -> Result<Self> { |
728 | Ok(BoundLifetimes { |
729 | for_token: input.parse()?, |
730 | lt_token: input.parse()?, |
731 | lifetimes: { |
732 | let mut lifetimes = Punctuated::new(); |
733 | while !input.peek(Token![>]) { |
734 | lifetimes.push_value(input.parse()?); |
735 | if input.peek(Token![>]) { |
736 | break; |
737 | } |
738 | lifetimes.push_punct(input.parse()?); |
739 | } |
740 | lifetimes |
741 | }, |
742 | gt_token: input.parse()?, |
743 | }) |
744 | } |
745 | } |
746 | |
747 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
748 | impl Parse for Option<BoundLifetimes> { |
749 | fn parse(input: ParseStream) -> Result<Self> { |
750 | if input.peek(Token![for]) { |
751 | input.parse().map(Some) |
752 | } else { |
753 | Ok(None) |
754 | } |
755 | } |
756 | } |
757 | |
758 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
759 | impl Parse for TypeParam { |
760 | fn parse(input: ParseStream) -> Result<Self> { |
761 | let attrs = input.call(Attribute::parse_outer)?; |
762 | let ident: Ident = input.parse()?; |
763 | let colon_token: Option<Token![:]> = input.parse()?; |
764 | |
765 | let begin_bound = input.fork(); |
766 | let mut is_maybe_const = false; |
767 | let mut bounds = Punctuated::new(); |
768 | if colon_token.is_some() { |
769 | loop { |
770 | if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) { |
771 | break; |
772 | } |
773 | if input.peek(Token![~]) && input.peek2(Token![const]) { |
774 | input.parse::<Token![~]>()?; |
775 | input.parse::<Token![const]>()?; |
776 | is_maybe_const = true; |
777 | } |
778 | let value: TypeParamBound = input.parse()?; |
779 | bounds.push_value(value); |
780 | if !input.peek(Token![+]) { |
781 | break; |
782 | } |
783 | let punct: Token![+] = input.parse()?; |
784 | bounds.push_punct(punct); |
785 | } |
786 | } |
787 | |
788 | let mut eq_token: Option<Token![=]> = input.parse()?; |
789 | let mut default = if eq_token.is_some() { |
790 | Some(input.parse::<Type>()?) |
791 | } else { |
792 | None |
793 | }; |
794 | |
795 | if is_maybe_const { |
796 | bounds.clear(); |
797 | eq_token = None; |
798 | default = Some(Type::Verbatim(verbatim::between(begin_bound, input))); |
799 | } |
800 | |
801 | Ok(TypeParam { |
802 | attrs, |
803 | ident, |
804 | colon_token, |
805 | bounds, |
806 | eq_token, |
807 | default, |
808 | }) |
809 | } |
810 | } |
811 | |
812 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
813 | impl Parse for TypeParamBound { |
814 | fn parse(input: ParseStream) -> Result<Self> { |
815 | if input.peek(Lifetime) { |
816 | return input.parse().map(TypeParamBound::Lifetime); |
817 | } |
818 | |
819 | if input.peek(token::Paren) { |
820 | let content; |
821 | let paren_token = parenthesized!(content in input); |
822 | let mut bound: TraitBound = content.parse()?; |
823 | bound.paren_token = Some(paren_token); |
824 | return Ok(TypeParamBound::Trait(bound)); |
825 | } |
826 | |
827 | input.parse().map(TypeParamBound::Trait) |
828 | } |
829 | } |
830 | |
831 | impl TypeParamBound { |
832 | pub(crate) fn parse_multiple( |
833 | input: ParseStream, |
834 | allow_plus: bool, |
835 | ) -> Result<Punctuated<Self, Token![+]>> { |
836 | let mut bounds = Punctuated::new(); |
837 | loop { |
838 | bounds.push_value(input.parse()?); |
839 | if !(allow_plus && input.peek(Token![+])) { |
840 | break; |
841 | } |
842 | bounds.push_punct(input.parse()?); |
843 | if !(input.peek(Ident::peek_any) |
844 | || input.peek(Token![::]) |
845 | || input.peek(Token![?]) |
846 | || input.peek(Lifetime) |
847 | || input.peek(token::Paren)) |
848 | { |
849 | break; |
850 | } |
851 | } |
852 | Ok(bounds) |
853 | } |
854 | } |
855 | |
856 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
857 | impl Parse for TraitBound { |
858 | fn parse(input: ParseStream) -> Result<Self> { |
859 | #[cfg (feature = "full" )] |
860 | let tilde_const = if input.peek(Token![~]) && input.peek2(Token![const]) { |
861 | let tilde_token = input.parse::<Token![~]>()?; |
862 | let const_token = input.parse::<Token![const]>()?; |
863 | Some((tilde_token, const_token)) |
864 | } else { |
865 | None |
866 | }; |
867 | |
868 | let modifier: TraitBoundModifier = input.parse()?; |
869 | let lifetimes: Option<BoundLifetimes> = input.parse()?; |
870 | |
871 | let mut path: Path = input.parse()?; |
872 | if path.segments.last().unwrap().arguments.is_empty() |
873 | && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren)) |
874 | { |
875 | input.parse::<Option<Token![::]>>()?; |
876 | let args: ParenthesizedGenericArguments = input.parse()?; |
877 | let parenthesized = PathArguments::Parenthesized(args); |
878 | path.segments.last_mut().unwrap().arguments = parenthesized; |
879 | } |
880 | |
881 | #[cfg (feature = "full" )] |
882 | { |
883 | if let Some((tilde_token, const_token)) = tilde_const { |
884 | path.segments.insert( |
885 | 0, |
886 | PathSegment { |
887 | ident: Ident::new("const" , const_token.span), |
888 | arguments: PathArguments::None, |
889 | }, |
890 | ); |
891 | let (_const, punct) = path.segments.pairs_mut().next().unwrap().into_tuple(); |
892 | *punct.unwrap() = Token![::](tilde_token.span); |
893 | } |
894 | } |
895 | |
896 | Ok(TraitBound { |
897 | paren_token: None, |
898 | modifier, |
899 | lifetimes, |
900 | path, |
901 | }) |
902 | } |
903 | } |
904 | |
905 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
906 | impl Parse for TraitBoundModifier { |
907 | fn parse(input: ParseStream) -> Result<Self> { |
908 | if input.peek(Token![?]) { |
909 | input.parse().map(TraitBoundModifier::Maybe) |
910 | } else { |
911 | Ok(TraitBoundModifier::None) |
912 | } |
913 | } |
914 | } |
915 | |
916 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
917 | impl Parse for ConstParam { |
918 | fn parse(input: ParseStream) -> Result<Self> { |
919 | let mut default = None; |
920 | Ok(ConstParam { |
921 | attrs: input.call(Attribute::parse_outer)?, |
922 | const_token: input.parse()?, |
923 | ident: input.parse()?, |
924 | colon_token: input.parse()?, |
925 | ty: input.parse()?, |
926 | eq_token: { |
927 | if input.peek(Token![=]) { |
928 | let eq_token = input.parse()?; |
929 | default = Some(path::parsing::const_argument(input)?); |
930 | Some(eq_token) |
931 | } else { |
932 | None |
933 | } |
934 | }, |
935 | default, |
936 | }) |
937 | } |
938 | } |
939 | |
940 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
941 | impl Parse for WhereClause { |
942 | fn parse(input: ParseStream) -> Result<Self> { |
943 | Ok(WhereClause { |
944 | where_token: input.parse()?, |
945 | predicates: { |
946 | let mut predicates = Punctuated::new(); |
947 | loop { |
948 | if input.is_empty() |
949 | || input.peek(token::Brace) |
950 | || input.peek(Token![,]) |
951 | || input.peek(Token![;]) |
952 | || input.peek(Token![:]) && !input.peek(Token![::]) |
953 | || input.peek(Token![=]) |
954 | { |
955 | break; |
956 | } |
957 | let value = input.parse()?; |
958 | predicates.push_value(value); |
959 | if !input.peek(Token![,]) { |
960 | break; |
961 | } |
962 | let punct = input.parse()?; |
963 | predicates.push_punct(punct); |
964 | } |
965 | predicates |
966 | }, |
967 | }) |
968 | } |
969 | } |
970 | |
971 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
972 | impl Parse for Option<WhereClause> { |
973 | fn parse(input: ParseStream) -> Result<Self> { |
974 | if input.peek(Token![where]) { |
975 | input.parse().map(Some) |
976 | } else { |
977 | Ok(None) |
978 | } |
979 | } |
980 | } |
981 | |
982 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
983 | impl Parse for WherePredicate { |
984 | fn parse(input: ParseStream) -> Result<Self> { |
985 | if input.peek(Lifetime) && input.peek2(Token![:]) { |
986 | Ok(WherePredicate::Lifetime(PredicateLifetime { |
987 | lifetime: input.parse()?, |
988 | colon_token: input.parse()?, |
989 | bounds: { |
990 | let mut bounds = Punctuated::new(); |
991 | loop { |
992 | if input.is_empty() |
993 | || input.peek(token::Brace) |
994 | || input.peek(Token![,]) |
995 | || input.peek(Token![;]) |
996 | || input.peek(Token![:]) |
997 | || input.peek(Token![=]) |
998 | { |
999 | break; |
1000 | } |
1001 | let value = input.parse()?; |
1002 | bounds.push_value(value); |
1003 | if !input.peek(Token![+]) { |
1004 | break; |
1005 | } |
1006 | let punct = input.parse()?; |
1007 | bounds.push_punct(punct); |
1008 | } |
1009 | bounds |
1010 | }, |
1011 | })) |
1012 | } else { |
1013 | Ok(WherePredicate::Type(PredicateType { |
1014 | lifetimes: input.parse()?, |
1015 | bounded_ty: input.parse()?, |
1016 | colon_token: input.parse()?, |
1017 | bounds: { |
1018 | let mut bounds = Punctuated::new(); |
1019 | loop { |
1020 | if input.is_empty() |
1021 | || input.peek(token::Brace) |
1022 | || input.peek(Token![,]) |
1023 | || input.peek(Token![;]) |
1024 | || input.peek(Token![:]) && !input.peek(Token![::]) |
1025 | || input.peek(Token![=]) |
1026 | { |
1027 | break; |
1028 | } |
1029 | let value = input.parse()?; |
1030 | bounds.push_value(value); |
1031 | if !input.peek(Token![+]) { |
1032 | break; |
1033 | } |
1034 | let punct = input.parse()?; |
1035 | bounds.push_punct(punct); |
1036 | } |
1037 | bounds |
1038 | }, |
1039 | })) |
1040 | } |
1041 | } |
1042 | } |
1043 | } |
1044 | |
1045 | #[cfg (feature = "printing" )] |
1046 | mod printing { |
1047 | use super::*; |
1048 | use crate::attr::FilterAttrs; |
1049 | use crate::print::TokensOrDefault; |
1050 | #[cfg (feature = "full" )] |
1051 | use crate::punctuated::Pair; |
1052 | use proc_macro2::TokenStream; |
1053 | #[cfg (feature = "full" )] |
1054 | use proc_macro2::TokenTree; |
1055 | use quote::{ToTokens, TokenStreamExt}; |
1056 | |
1057 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1058 | impl ToTokens for Generics { |
1059 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1060 | if self.params.is_empty() { |
1061 | return; |
1062 | } |
1063 | |
1064 | TokensOrDefault(&self.lt_token).to_tokens(tokens); |
1065 | |
1066 | // Print lifetimes before types and consts, regardless of their |
1067 | // order in self.params. |
1068 | // |
1069 | // TODO: ordering rules for const parameters vs type parameters have |
1070 | // not been settled yet. https://github.com/rust-lang/rust/issues/44580 |
1071 | let mut trailing_or_empty = true; |
1072 | for param in self.params.pairs() { |
1073 | if let GenericParam::Lifetime(_) = **param.value() { |
1074 | param.to_tokens(tokens); |
1075 | trailing_or_empty = param.punct().is_some(); |
1076 | } |
1077 | } |
1078 | for param in self.params.pairs() { |
1079 | match **param.value() { |
1080 | GenericParam::Type(_) | GenericParam::Const(_) => { |
1081 | if !trailing_or_empty { |
1082 | <Token![,]>::default().to_tokens(tokens); |
1083 | trailing_or_empty = true; |
1084 | } |
1085 | param.to_tokens(tokens); |
1086 | } |
1087 | GenericParam::Lifetime(_) => {} |
1088 | } |
1089 | } |
1090 | |
1091 | TokensOrDefault(&self.gt_token).to_tokens(tokens); |
1092 | } |
1093 | } |
1094 | |
1095 | impl<'a> ToTokens for ImplGenerics<'a> { |
1096 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1097 | if self.0.params.is_empty() { |
1098 | return; |
1099 | } |
1100 | |
1101 | TokensOrDefault(&self.0.lt_token).to_tokens(tokens); |
1102 | |
1103 | // Print lifetimes before types and consts, regardless of their |
1104 | // order in self.params. |
1105 | // |
1106 | // TODO: ordering rules for const parameters vs type parameters have |
1107 | // not been settled yet. https://github.com/rust-lang/rust/issues/44580 |
1108 | let mut trailing_or_empty = true; |
1109 | for param in self.0.params.pairs() { |
1110 | if let GenericParam::Lifetime(_) = **param.value() { |
1111 | param.to_tokens(tokens); |
1112 | trailing_or_empty = param.punct().is_some(); |
1113 | } |
1114 | } |
1115 | for param in self.0.params.pairs() { |
1116 | if let GenericParam::Lifetime(_) = **param.value() { |
1117 | continue; |
1118 | } |
1119 | if !trailing_or_empty { |
1120 | <Token![,]>::default().to_tokens(tokens); |
1121 | trailing_or_empty = true; |
1122 | } |
1123 | match *param.value() { |
1124 | GenericParam::Lifetime(_) => unreachable!(), |
1125 | GenericParam::Type(param) => { |
1126 | // Leave off the type parameter defaults |
1127 | tokens.append_all(param.attrs.outer()); |
1128 | param.ident.to_tokens(tokens); |
1129 | if !param.bounds.is_empty() { |
1130 | TokensOrDefault(¶m.colon_token).to_tokens(tokens); |
1131 | param.bounds.to_tokens(tokens); |
1132 | } |
1133 | } |
1134 | GenericParam::Const(param) => { |
1135 | // Leave off the const parameter defaults |
1136 | tokens.append_all(param.attrs.outer()); |
1137 | param.const_token.to_tokens(tokens); |
1138 | param.ident.to_tokens(tokens); |
1139 | param.colon_token.to_tokens(tokens); |
1140 | param.ty.to_tokens(tokens); |
1141 | } |
1142 | } |
1143 | param.punct().to_tokens(tokens); |
1144 | } |
1145 | |
1146 | TokensOrDefault(&self.0.gt_token).to_tokens(tokens); |
1147 | } |
1148 | } |
1149 | |
1150 | impl<'a> ToTokens for TypeGenerics<'a> { |
1151 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1152 | if self.0.params.is_empty() { |
1153 | return; |
1154 | } |
1155 | |
1156 | TokensOrDefault(&self.0.lt_token).to_tokens(tokens); |
1157 | |
1158 | // Print lifetimes before types and consts, regardless of their |
1159 | // order in self.params. |
1160 | // |
1161 | // TODO: ordering rules for const parameters vs type parameters have |
1162 | // not been settled yet. https://github.com/rust-lang/rust/issues/44580 |
1163 | let mut trailing_or_empty = true; |
1164 | for param in self.0.params.pairs() { |
1165 | if let GenericParam::Lifetime(def) = *param.value() { |
1166 | // Leave off the lifetime bounds and attributes |
1167 | def.lifetime.to_tokens(tokens); |
1168 | param.punct().to_tokens(tokens); |
1169 | trailing_or_empty = param.punct().is_some(); |
1170 | } |
1171 | } |
1172 | for param in self.0.params.pairs() { |
1173 | if let GenericParam::Lifetime(_) = **param.value() { |
1174 | continue; |
1175 | } |
1176 | if !trailing_or_empty { |
1177 | <Token![,]>::default().to_tokens(tokens); |
1178 | trailing_or_empty = true; |
1179 | } |
1180 | match *param.value() { |
1181 | GenericParam::Lifetime(_) => unreachable!(), |
1182 | GenericParam::Type(param) => { |
1183 | // Leave off the type parameter defaults |
1184 | param.ident.to_tokens(tokens); |
1185 | } |
1186 | GenericParam::Const(param) => { |
1187 | // Leave off the const parameter defaults |
1188 | param.ident.to_tokens(tokens); |
1189 | } |
1190 | } |
1191 | param.punct().to_tokens(tokens); |
1192 | } |
1193 | |
1194 | TokensOrDefault(&self.0.gt_token).to_tokens(tokens); |
1195 | } |
1196 | } |
1197 | |
1198 | impl<'a> ToTokens for Turbofish<'a> { |
1199 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1200 | if !self.0.params.is_empty() { |
1201 | <Token![::]>::default().to_tokens(tokens); |
1202 | TypeGenerics(self.0).to_tokens(tokens); |
1203 | } |
1204 | } |
1205 | } |
1206 | |
1207 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1208 | impl ToTokens for BoundLifetimes { |
1209 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1210 | self.for_token.to_tokens(tokens); |
1211 | self.lt_token.to_tokens(tokens); |
1212 | self.lifetimes.to_tokens(tokens); |
1213 | self.gt_token.to_tokens(tokens); |
1214 | } |
1215 | } |
1216 | |
1217 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1218 | impl ToTokens for LifetimeDef { |
1219 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1220 | tokens.append_all(self.attrs.outer()); |
1221 | self.lifetime.to_tokens(tokens); |
1222 | if !self.bounds.is_empty() { |
1223 | TokensOrDefault(&self.colon_token).to_tokens(tokens); |
1224 | self.bounds.to_tokens(tokens); |
1225 | } |
1226 | } |
1227 | } |
1228 | |
1229 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1230 | impl ToTokens for TypeParam { |
1231 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1232 | tokens.append_all(self.attrs.outer()); |
1233 | self.ident.to_tokens(tokens); |
1234 | if !self.bounds.is_empty() { |
1235 | TokensOrDefault(&self.colon_token).to_tokens(tokens); |
1236 | self.bounds.to_tokens(tokens); |
1237 | } |
1238 | if let Some(default) = &self.default { |
1239 | #[cfg (feature = "full" )] |
1240 | { |
1241 | if self.eq_token.is_none() { |
1242 | if let Type::Verbatim(default) = default { |
1243 | let mut iter = default.clone().into_iter().peekable(); |
1244 | while let Some(token) = iter.next() { |
1245 | if let TokenTree::Punct(q) = token { |
1246 | if q.as_char() == '~' { |
1247 | if let Some(TokenTree::Ident(c)) = iter.peek() { |
1248 | if c == "const" { |
1249 | if self.bounds.is_empty() { |
1250 | TokensOrDefault(&self.colon_token) |
1251 | .to_tokens(tokens); |
1252 | } |
1253 | return default.to_tokens(tokens); |
1254 | } |
1255 | } |
1256 | } |
1257 | } |
1258 | } |
1259 | } |
1260 | } |
1261 | } |
1262 | TokensOrDefault(&self.eq_token).to_tokens(tokens); |
1263 | default.to_tokens(tokens); |
1264 | } |
1265 | } |
1266 | } |
1267 | |
1268 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1269 | impl ToTokens for TraitBound { |
1270 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1271 | let to_tokens = |tokens: &mut TokenStream| { |
1272 | #[cfg (feature = "full" )] |
1273 | let skip = match self.path.segments.pairs().next() { |
1274 | Some(Pair::Punctuated(t, p)) if t.ident == "const" => { |
1275 | Token![~](p.spans[0]).to_tokens(tokens); |
1276 | t.to_tokens(tokens); |
1277 | 1 |
1278 | } |
1279 | _ => 0, |
1280 | }; |
1281 | self.modifier.to_tokens(tokens); |
1282 | self.lifetimes.to_tokens(tokens); |
1283 | #[cfg (feature = "full" )] |
1284 | { |
1285 | self.path.leading_colon.to_tokens(tokens); |
1286 | tokens.append_all(self.path.segments.pairs().skip(skip)); |
1287 | } |
1288 | #[cfg (not(feature = "full" ))] |
1289 | { |
1290 | self.path.to_tokens(tokens); |
1291 | } |
1292 | }; |
1293 | match &self.paren_token { |
1294 | Some(paren) => paren.surround(tokens, to_tokens), |
1295 | None => to_tokens(tokens), |
1296 | } |
1297 | } |
1298 | } |
1299 | |
1300 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1301 | impl ToTokens for TraitBoundModifier { |
1302 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1303 | match self { |
1304 | TraitBoundModifier::None => {} |
1305 | TraitBoundModifier::Maybe(t) => t.to_tokens(tokens), |
1306 | } |
1307 | } |
1308 | } |
1309 | |
1310 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1311 | impl ToTokens for ConstParam { |
1312 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1313 | tokens.append_all(self.attrs.outer()); |
1314 | self.const_token.to_tokens(tokens); |
1315 | self.ident.to_tokens(tokens); |
1316 | self.colon_token.to_tokens(tokens); |
1317 | self.ty.to_tokens(tokens); |
1318 | if let Some(default) = &self.default { |
1319 | TokensOrDefault(&self.eq_token).to_tokens(tokens); |
1320 | default.to_tokens(tokens); |
1321 | } |
1322 | } |
1323 | } |
1324 | |
1325 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1326 | impl ToTokens for WhereClause { |
1327 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1328 | if !self.predicates.is_empty() { |
1329 | self.where_token.to_tokens(tokens); |
1330 | self.predicates.to_tokens(tokens); |
1331 | } |
1332 | } |
1333 | } |
1334 | |
1335 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1336 | impl ToTokens for PredicateType { |
1337 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1338 | self.lifetimes.to_tokens(tokens); |
1339 | self.bounded_ty.to_tokens(tokens); |
1340 | self.colon_token.to_tokens(tokens); |
1341 | self.bounds.to_tokens(tokens); |
1342 | } |
1343 | } |
1344 | |
1345 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1346 | impl ToTokens for PredicateLifetime { |
1347 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1348 | self.lifetime.to_tokens(tokens); |
1349 | self.colon_token.to_tokens(tokens); |
1350 | self.bounds.to_tokens(tokens); |
1351 | } |
1352 | } |
1353 | |
1354 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1355 | impl ToTokens for PredicateEq { |
1356 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1357 | self.lhs_ty.to_tokens(tokens); |
1358 | self.eq_token.to_tokens(tokens); |
1359 | self.rhs_ty.to_tokens(tokens); |
1360 | } |
1361 | } |
1362 | } |
1363 | |