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