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