1use crate::attr::Attribute;
2#[cfg(feature = "parsing")]
3use crate::error::Result;
4use crate::expr::Expr;
5use crate::ident::Ident;
6use crate::lifetime::Lifetime;
7use crate::path::Path;
8use crate::punctuated::{Iter, IterMut, Punctuated};
9use crate::token;
10use crate::ty::Type;
11use alloc::vec::Vec;
12#[cfg(all(feature = "printing", feature = "extra-traits"))]
13use core::fmt::{self, Debug};
14#[cfg(all(feature = "printing", feature = "extra-traits"))]
15use core::hash::{Hash, Hasher};
16use proc_macro2::TokenStream;
17
18#[doc =
r" Lifetimes and type parameters attached to a declaration of a function,"]
#[doc = r" enum, trait, etc."]
#[doc = r""]
#[doc = r" This struct represents two distinct optional syntactic elements,"]
#[doc = r" [generic parameters] and [where clause]. In some locations of the"]
#[doc = r" grammar, there may be other tokens in between these two things."]
#[doc = r""]
#[doc =
r" [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters"]
#[doc =
r" [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses"]
pub struct Generics {
pub lt_token: Option<crate::token::Lt>,
pub params: Punctuated<GenericParam, crate::token::Comma>,
pub gt_token: Option<crate::token::Gt>,
pub where_clause: Option<WhereClause>,
}ast_struct! {
19 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
29 pub struct Generics {
30 pub lt_token: Option<Token![<]>,
31 pub params: Punctuated<GenericParam, Token![,]>,
32 pub gt_token: Option<Token![>]>,
33 pub where_clause: Option<WhereClause>,
34 }
35}
36
37#[doc =
r" A generic type parameter, lifetime, or const generic: `T: Into<String>`,"]
#[doc = r" `'a: 'b`, `const LEN: usize`."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
pub enum GenericParam {
#[doc = r" A lifetime parameter: `'a: 'b + 'c + 'd`."]
Lifetime(LifetimeParam),
#[doc = r" A generic type parameter: `T: Into<String>`."]
Type(TypeParam),
#[doc = r" A const generic parameter: `const LENGTH: usize`."]
Const(ConstParam),
}
impl ::quote::ToTokens for GenericParam {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
GenericParam::Lifetime(_e) => _e.to_tokens(tokens),
GenericParam::Type(_e) => _e.to_tokens(tokens),
GenericParam::Const(_e) => _e.to_tokens(tokens),
}
}
}ast_enum_of_structs! {
38 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
47 pub enum GenericParam {
48 Lifetime(LifetimeParam),
50
51 Type(TypeParam),
53
54 Const(ConstParam),
56 }
57}
58
59#[doc = r" A lifetime definition: `'a: 'b + 'c + 'd`."]
pub struct LifetimeParam {
pub attrs: Vec<Attribute>,
pub lifetime: Lifetime,
pub colon_token: Option<crate::token::Colon>,
pub bounds: Punctuated<Lifetime, crate::token::Plus>,
}ast_struct! {
60 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
62 pub struct LifetimeParam {
63 pub attrs: Vec<Attribute>,
64 pub lifetime: Lifetime,
65 pub colon_token: Option<Token![:]>,
66 pub bounds: Punctuated<Lifetime, Token![+]>,
67 }
68}
69
70#[doc = r" A generic type parameter: `T: Into<String>`."]
pub struct TypeParam {
pub attrs: Vec<Attribute>,
pub ident: Ident,
pub colon_token: Option<crate::token::Colon>,
pub bounds: Punctuated<TypeParamBound, crate::token::Plus>,
pub default: Option<(crate::token::Eq, Type)>,
}ast_struct! {
71 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
73 pub struct TypeParam {
74 pub attrs: Vec<Attribute>,
75 pub ident: Ident,
76 pub colon_token: Option<Token![:]>,
77 pub bounds: Punctuated<TypeParamBound, Token![+]>,
78 pub default: Option<(Token![=], Type)>,
79 }
80}
81
82#[doc = r" A const generic parameter: `const LENGTH: usize`."]
pub struct ConstParam {
pub attrs: Vec<Attribute>,
pub const_token: crate::token::Const,
pub ident: Ident,
pub colon_token: crate::token::Colon,
pub ty: Type,
pub default: Option<(crate::token::Eq, Expr)>,
}ast_struct! {
83 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
85 pub struct ConstParam {
86 pub attrs: Vec<Attribute>,
87 pub const_token: Token![const],
88 pub ident: Ident,
89 pub colon_token: Token![:],
90 pub ty: Type,
91 pub default: Option<(Token![=], Expr)>,
92 }
93}
94
95impl 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
106impl Generics {
107 #[doc = r" Iterator over the lifetime parameters in `self.params`."]
pub fn lifetimes(&self) -> Lifetimes { Lifetimes(self.params.iter()) }return_impl_trait! {
108 pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
110 Lifetimes(self.params.iter())
111 }
112 }
113
114 #[doc = r" Iterator over the lifetime parameters in `self.params`."]
pub fn lifetimes_mut(&mut self) -> LifetimesMut {
LifetimesMut(self.params.iter_mut())
}return_impl_trait! {
115 pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] {
117 LifetimesMut(self.params.iter_mut())
118 }
119 }
120
121 #[doc = r" Iterator over the type parameters in `self.params`."]
pub fn type_params(&self) -> TypeParams { TypeParams(self.params.iter()) }return_impl_trait! {
122 pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
124 TypeParams(self.params.iter())
125 }
126 }
127
128 #[doc = r" Iterator over the type parameters in `self.params`."]
pub fn type_params_mut(&mut self) -> TypeParamsMut {
TypeParamsMut(self.params.iter_mut())
}return_impl_trait! {
129 pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] {
131 TypeParamsMut(self.params.iter_mut())
132 }
133 }
134
135 #[doc = r" Iterator over the constant parameters in `self.params`."]
pub fn const_params(&self) -> ConstParams { ConstParams(self.params.iter()) }return_impl_trait! {
136 pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
138 ConstParams(self.params.iter())
139 }
140 }
141
142 #[doc = r" Iterator over the constant parameters in `self.params`."]
pub fn const_params_mut(&mut self) -> ConstParamsMut {
ConstParamsMut(self.params.iter_mut())
}return_impl_trait! {
143 pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
145 ConstParamsMut(self.params.iter_mut())
146 }
147 }
148
149 pub fn make_where_clause(&mut self) -> &mut WhereClause {
151 self.where_clause.get_or_insert_with(|| WhereClause {
152 where_token: <crate::token::WhereToken![where]>::default(),
153 predicates: Punctuated::new(),
154 })
155 }
156
157 #[cfg(feature = "printing")]
176 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
177 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
178 (
179 ImplGenerics(self),
180 TypeGenerics(self),
181 self.where_clause.as_ref(),
182 )
183 }
184}
185
186pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
187
188impl<'a> Iterator for Lifetimes<'a> {
189 type Item = &'a LifetimeParam;
190
191 fn next(&mut self) -> Option<Self::Item> {
192 if let GenericParam::Lifetime(lifetime) = self.0.next()? {
193 Some(lifetime)
194 } else {
195 self.next()
196 }
197 }
198}
199
200pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
201
202impl<'a> Iterator for LifetimesMut<'a> {
203 type Item = &'a mut LifetimeParam;
204
205 fn next(&mut self) -> Option<Self::Item> {
206 if let GenericParam::Lifetime(lifetime) = self.0.next()? {
207 Some(lifetime)
208 } else {
209 self.next()
210 }
211 }
212}
213
214pub struct TypeParams<'a>(Iter<'a, GenericParam>);
215
216impl<'a> Iterator for TypeParams<'a> {
217 type Item = &'a TypeParam;
218
219 fn next(&mut self) -> Option<Self::Item> {
220 if let GenericParam::Type(type_param) = self.0.next()? {
221 Some(type_param)
222 } else {
223 self.next()
224 }
225 }
226}
227
228pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
229
230impl<'a> Iterator for TypeParamsMut<'a> {
231 type Item = &'a mut TypeParam;
232
233 fn next(&mut self) -> Option<Self::Item> {
234 if let GenericParam::Type(type_param) = self.0.next()? {
235 Some(type_param)
236 } else {
237 self.next()
238 }
239 }
240}
241
242pub struct ConstParams<'a>(Iter<'a, GenericParam>);
243
244impl<'a> Iterator for ConstParams<'a> {
245 type Item = &'a ConstParam;
246
247 fn next(&mut self) -> Option<Self::Item> {
248 if let GenericParam::Const(const_param) = self.0.next()? {
249 Some(const_param)
250 } else {
251 self.next()
252 }
253 }
254}
255
256pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
257
258impl<'a> Iterator for ConstParamsMut<'a> {
259 type Item = &'a mut ConstParam;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 if let GenericParam::Const(const_param) = self.0.next()? {
263 Some(const_param)
264 } else {
265 self.next()
266 }
267 }
268}
269
270#[cfg(feature = "printing")]
272#[cfg_attr(
273 docsrs,
274 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
275)]
276pub struct ImplGenerics<'a>(&'a Generics);
277
278#[cfg(feature = "printing")]
280#[cfg_attr(
281 docsrs,
282 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
283)]
284pub struct TypeGenerics<'a>(&'a Generics);
285
286#[cfg(feature = "printing")]
288#[cfg_attr(
289 docsrs,
290 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
291)]
292pub struct Turbofish<'a>(&'a Generics);
293
294#[cfg(feature = "printing")]
295macro_rules! generics_wrapper_impls {
296 ($ty:ident) => {
297 #[cfg(feature = "clone-impls")]
298 #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
299 impl<'a> Clone for $ty<'a> {
300 fn clone(&self) -> Self {
301 $ty(self.0)
302 }
303 }
304
305 #[cfg(feature = "extra-traits")]
306 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
307 impl<'a> Debug for $ty<'a> {
308 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
309 formatter
310 .debug_tuple(stringify!($ty))
311 .field(self.0)
312 .finish()
313 }
314 }
315
316 #[cfg(feature = "extra-traits")]
317 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
318 impl<'a> Eq for $ty<'a> {}
319
320 #[cfg(feature = "extra-traits")]
321 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
322 impl<'a> PartialEq for $ty<'a> {
323 fn eq(&self, other: &Self) -> bool {
324 self.0 == other.0
325 }
326 }
327
328 #[cfg(feature = "extra-traits")]
329 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
330 impl<'a> Hash for $ty<'a> {
331 fn hash<H: Hasher>(&self, state: &mut H) {
332 self.0.hash(state);
333 }
334 }
335 };
336}
337
338#[cfg(feature = "printing")]
339impl<'a> Clone for ImplGenerics<'a> {
fn clone(&self) -> Self { ImplGenerics(self.0) }
}
impl<'a> Debug for ImplGenerics<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_tuple("ImplGenerics").field(self.0).finish()
}
}
impl<'a> Eq for ImplGenerics<'a> { }
impl<'a> PartialEq for ImplGenerics<'a> {
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for ImplGenerics<'a> {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(ImplGenerics);
340#[cfg(feature = "printing")]
341impl<'a> Clone for TypeGenerics<'a> {
fn clone(&self) -> Self { TypeGenerics(self.0) }
}
impl<'a> Debug for TypeGenerics<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_tuple("TypeGenerics").field(self.0).finish()
}
}
impl<'a> Eq for TypeGenerics<'a> { }
impl<'a> PartialEq for TypeGenerics<'a> {
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for TypeGenerics<'a> {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(TypeGenerics);
342#[cfg(feature = "printing")]
343impl<'a> Clone for Turbofish<'a> {
fn clone(&self) -> Self { Turbofish(self.0) }
}
impl<'a> Debug for Turbofish<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.debug_tuple("Turbofish").field(self.0).finish()
}
}
impl<'a> Eq for Turbofish<'a> { }
impl<'a> PartialEq for Turbofish<'a> {
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for Turbofish<'a> {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(Turbofish);
344
345#[cfg(feature = "printing")]
346impl<'a> TypeGenerics<'a> {
347 pub fn as_turbofish(&self) -> Turbofish<'a> {
349 Turbofish(self.0)
350 }
351}
352
353#[doc = r" A set of bound lifetimes: `for<'a, 'b, 'c>`."]
pub struct BoundLifetimes {
pub for_token: crate::token::For,
pub lt_token: crate::token::Lt,
pub lifetimes: Punctuated<GenericParam, crate::token::Comma>,
pub gt_token: crate::token::Gt,
}ast_struct! {
354 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
356 pub struct BoundLifetimes {
357 pub for_token: Token![for],
358 pub lt_token: Token![<],
359 pub lifetimes: Punctuated<GenericParam, Token![,]>,
360 pub gt_token: Token![>],
361 }
362}
363
364impl Default for BoundLifetimes {
365 fn default() -> Self {
366 BoundLifetimes {
367 for_token: Default::default(),
368 lt_token: Default::default(),
369 lifetimes: Punctuated::new(),
370 gt_token: Default::default(),
371 }
372 }
373}
374
375impl LifetimeParam {
376 pub fn new(lifetime: Lifetime) -> Self {
377 LifetimeParam {
378 attrs: Vec::new(),
379 lifetime,
380 colon_token: None,
381 bounds: Punctuated::new(),
382 }
383 }
384}
385
386impl From<Ident> for TypeParam {
387 fn from(ident: Ident) -> Self {
388 TypeParam {
389 attrs: Vec::new(),
390 ident,
391 colon_token: None,
392 bounds: Punctuated::new(),
393 default: None,
394 }
395 }
396}
397
398#[doc = r" A trait or lifetime used as a bound on a type parameter."]
#[non_exhaustive]
pub enum TypeParamBound {
Trait(TraitBound),
Lifetime(Lifetime),
PreciseCapture(PreciseCapture),
#[doc = r" Tokens in bound position not interpreted by Syn."]
#[doc = r""]
#[doc = r#" <div class="warning">"#]
#[doc = r""]
#[doc =
r" Important: see [Compatibility notes][crate#verbatim-variants]."]
#[doc = r""]
#[doc = r" </div>"]
Verbatim(TokenStream),
}
impl ::quote::ToTokens for TypeParamBound {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
TypeParamBound::Trait(_e) => _e.to_tokens(tokens),
TypeParamBound::Lifetime(_e) => _e.to_tokens(tokens),
TypeParamBound::PreciseCapture(_e) => _e.to_tokens(tokens),
TypeParamBound::Verbatim(_e) => _e.to_tokens(tokens),
}
}
}ast_enum_of_structs! {
399 #[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
407 Verbatim(TokenStream),
415 }
416}
417
418#[doc = r" A trait used as a bound on a type parameter."]
pub struct TraitBound {
pub paren_token: Option<token::Paren>,
#[doc = r" The `for<'a>` in `for<'a> Foo<&'a T>`"]
pub lifetimes: Option<BoundLifetimes>,
#[doc =
r" (Non-exhaustive) Additional optional information about a trait"]
#[doc = r" bound."]
pub modifiers: TraitBoundModifiers,
#[doc = r" The `?` in `?Sized`"]
pub maybe: Option<crate::token::Question>,
#[doc = r" The `Foo<&'a T>` in `for<'a> Foo<&'a T>`"]
pub path: Path,
}ast_struct! {
419 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
421 pub struct TraitBound {
422 pub paren_token: Option<token::Paren>,
423 pub lifetimes: Option<BoundLifetimes>,
425 pub modifiers: TraitBoundModifiers,
428 pub maybe: Option<Token![?]>,
430 pub path: Path,
432 }
433}
434
435#[doc = r" Additional optional information about a trait bound."]
#[doc = r""]
#[doc = r" This data structure may grow to accommodate future Rust language"]
#[doc = r" changes, including the following in-progress RFCs:"]
#[doc = r""]
#[doc = r#" - [RFC 3668] "Async closures" (`async Fn()`)"#]
#[doc =
r#" - [RFC 3762] "Make trait methods callable in const contexts" (`const Default`)"#]
#[doc = r""]
#[doc = r" [RFC 3668]: https://github.com/rust-lang/rust/issues/62290"]
#[doc = r" [RFC 3762]: https://github.com/rust-lang/rfcs/pull/3762"]
#[non_exhaustive]
pub struct TraitBoundModifiers {}ast_struct! {
436 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
447 #[non_exhaustive]
448 pub struct TraitBoundModifiers {}
449}
450
451impl Default for TraitBoundModifiers {
452 fn default() -> Self {
453 TraitBoundModifiers {}
454 }
455}
456
457impl TraitBoundModifiers {
458 #[cfg(feature = "parsing")]
459 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
460 pub fn require_empty(&self) -> Result<()> {
461 Ok(())
462 }
463}
464
465#[doc =
r" Precise capturing bound: the 'use<…>' in `impl Trait +"]
#[doc = r" use<'a, T>`."]
pub struct PreciseCapture {
pub use_token: crate::token::Use,
pub lt_token: crate::token::Lt,
pub params: Punctuated<CapturedParam, crate::token::Comma>,
pub gt_token: crate::token::Gt,
}ast_struct! {
466 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
469 pub struct PreciseCapture #full {
470 pub use_token: Token![use],
471 pub lt_token: Token![<],
472 pub params: Punctuated<CapturedParam, Token![,]>,
473 pub gt_token: Token![>],
474 }
475}
476
477#[cfg(feature = "full")]
478#[doc = r" Single parameter in a precise capturing bound."]
#[non_exhaustive]
pub enum CapturedParam {
#[doc =
r" A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl"]
#[doc = r" Trait + use<'a>`."]
Lifetime(Lifetime),
#[doc =
r" A type parameter or const generic parameter in precise capturing"]
#[doc =
r" bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->"]
#[doc = r" impl Trait + use<K>`."]
Ident(Ident),
}ast_enum! {
479 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
481 #[non_exhaustive]
482 pub enum CapturedParam {
483 Lifetime(Lifetime),
486 Ident(Ident),
490 }
491}
492
493#[doc = r" A `where` clause in a definition: `where T: Deserialize<'de>, D:"]
#[doc = r" 'static`."]
pub struct WhereClause {
pub where_token: crate::token::Where,
pub predicates: Punctuated<WherePredicate, crate::token::Comma>,
}ast_struct! {
494 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
497 pub struct WhereClause {
498 pub where_token: Token![where],
499 pub predicates: Punctuated<WherePredicate, Token![,]>,
500 }
501}
502
503#[doc = r" A single predicate in a `where` clause: `T: Deserialize<'de>`."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
#[non_exhaustive]
pub enum WherePredicate {
#[doc = r" A lifetime predicate in a `where` clause: `'a: 'b + 'c`."]
Lifetime(PredicateLifetime),
#[doc =
r" A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`."]
Type(PredicateType),
}
impl ::quote::ToTokens for WherePredicate {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
WherePredicate::Lifetime(_e) => _e.to_tokens(tokens),
WherePredicate::Type(_e) => _e.to_tokens(tokens),
}
}
}ast_enum_of_structs! {
504 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
512 #[non_exhaustive]
513 pub enum WherePredicate {
514 Lifetime(PredicateLifetime),
516
517 Type(PredicateType),
519 }
520}
521
522#[doc = r" A lifetime predicate in a `where` clause: `'a: 'b + 'c`."]
pub struct PredicateLifetime {
pub attrs: Vec<Attribute>,
pub lifetime: Lifetime,
pub colon_token: crate::token::Colon,
pub bounds: Punctuated<Lifetime, crate::token::Plus>,
}ast_struct! {
523 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
525 pub struct PredicateLifetime {
526 pub attrs: Vec<Attribute>,
527 pub lifetime: Lifetime,
528 pub colon_token: Token![:],
529 pub bounds: Punctuated<Lifetime, Token![+]>,
530 }
531}
532
533#[doc =
r" A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`."]
pub struct PredicateType {
pub attrs: Vec<Attribute>,
#[doc = r" Any lifetimes from a `for` binding"]
pub lifetimes: Option<BoundLifetimes>,
#[doc = r" The type being bounded"]
pub bounded_ty: Type,
pub colon_token: crate::token::Colon,
#[doc = r" Trait and lifetime bounds (`Clone+Send+'static`)"]
pub bounds: Punctuated<TypeParamBound, crate::token::Plus>,
}ast_struct! {
534 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
536 pub struct PredicateType {
537 pub attrs: Vec<Attribute>,
538 pub lifetimes: Option<BoundLifetimes>,
540 pub bounded_ty: Type,
542 pub colon_token: Token![:],
543 pub bounds: Punctuated<TypeParamBound, Token![+]>,
545 }
546}
547
548#[cfg(feature = "parsing")]
549pub(crate) mod parsing {
550 use crate::attr::Attribute;
551 use crate::error::{Error, Result};
552 use crate::ext::IdentExt as _;
553 use crate::generics::{
554 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
555 PredicateType, TraitBound, TraitBoundModifiers, TypeParam, TypeParamBound, WhereClause,
556 WherePredicate,
557 };
558 #[cfg(feature = "full")]
559 use crate::generics::{CapturedParam, PreciseCapture};
560 use crate::ident::Ident;
561 use crate::lifetime::Lifetime;
562 use crate::parse::{Parse, ParseStream};
563 use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments};
564 use crate::punctuated::Punctuated;
565 use crate::token;
566 use crate::ty::Type;
567 use crate::verbatim;
568
569 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
570 impl Parse for Generics {
571 fn parse(input: ParseStream) -> Result<Self> {
572 if !input.peek(crate::token::LtToken![<]) {
573 return Ok(Generics::default());
574 }
575
576 let lt_token: crate::token::LtToken![<] = input.parse()?;
577
578 let mut params = Punctuated::new();
579 loop {
580 if input.peek(crate::token::GtToken![>]) {
581 break;
582 }
583
584 let attrs = input.call(Attribute::parse_outer)?;
585 let lookahead = input.lookahead1();
586 if lookahead.peek(Lifetime) {
587 params.push_value(GenericParam::Lifetime(LifetimeParam {
588 attrs,
589 ..input.parse()?
590 }));
591 } else if lookahead.peek(Ident) {
592 params.push_value(GenericParam::Type(TypeParam {
593 attrs,
594 ..input.parse()?
595 }));
596 } else if lookahead.peek(crate::token::ConstToken![const]) {
597 params.push_value(GenericParam::Const(ConstParam {
598 attrs,
599 ..input.parse()?
600 }));
601 } else if input.peek(crate::token::UnderscoreToken![_]) {
602 params.push_value(GenericParam::Type(TypeParam {
603 attrs,
604 ident: input.call(Ident::parse_any)?,
605 colon_token: None,
606 bounds: Punctuated::new(),
607 default: None,
608 }));
609 } else {
610 return Err(lookahead.error());
611 }
612
613 if input.peek(crate::token::GtToken![>]) {
614 break;
615 }
616 let punct = input.parse()?;
617 params.push_punct(punct);
618 }
619
620 let gt_token: crate::token::GtToken![>] = input.parse()?;
621
622 Ok(Generics {
623 lt_token: Some(lt_token),
624 params,
625 gt_token: Some(gt_token),
626 where_clause: None,
627 })
628 }
629 }
630
631 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
632 impl Parse for GenericParam {
633 fn parse(input: ParseStream) -> Result<Self> {
634 let attrs = input.call(Attribute::parse_outer)?;
635
636 let lookahead = input.lookahead1();
637 if lookahead.peek(Ident) {
638 Ok(GenericParam::Type(TypeParam {
639 attrs,
640 ..input.parse()?
641 }))
642 } else if lookahead.peek(Lifetime) {
643 Ok(GenericParam::Lifetime(LifetimeParam {
644 attrs,
645 ..input.parse()?
646 }))
647 } else if lookahead.peek(crate::token::ConstToken![const]) {
648 Ok(GenericParam::Const(ConstParam {
649 attrs,
650 ..input.parse()?
651 }))
652 } else {
653 Err(lookahead.error())
654 }
655 }
656 }
657
658 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
659 impl Parse for LifetimeParam {
660 fn parse(input: ParseStream) -> Result<Self> {
661 let has_colon;
662 Ok(LifetimeParam {
663 attrs: input.call(Attribute::parse_outer)?,
664 lifetime: Lifetime::parse_any(input)?,
665 colon_token: {
666 if input.peek(crate::token::ColonToken![:]) {
667 has_colon = true;
668 Some(input.parse()?)
669 } else {
670 has_colon = false;
671 None
672 }
673 },
674 bounds: {
675 let mut bounds = Punctuated::new();
676 if has_colon {
677 loop {
678 if input.is_empty() || input.peek(crate::token::CommaToken![,]) || input.peek(crate::token::GtToken![>]) {
679 break;
680 }
681 let value = Lifetime::parse_any(input)?;
682 bounds.push_value(value);
683 if !input.peek(crate::token::PlusToken![+]) {
684 break;
685 }
686 let punct = input.parse()?;
687 bounds.push_punct(punct);
688 }
689 }
690 bounds
691 },
692 })
693 }
694 }
695
696 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
697 impl Parse for BoundLifetimes {
698 fn parse(input: ParseStream) -> Result<Self> {
699 Ok(BoundLifetimes {
700 for_token: input.parse()?,
701 lt_token: input.parse()?,
702 lifetimes: {
703 let mut lifetimes = Punctuated::new();
704 while !input.peek(crate::token::GtToken![>]) {
705 lifetimes.push_value(input.parse()?);
706 if input.peek(crate::token::GtToken![>]) {
707 break;
708 }
709 lifetimes.push_punct(input.parse()?);
710 }
711 lifetimes
712 },
713 gt_token: input.parse()?,
714 })
715 }
716 }
717
718 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
719 impl Parse for Option<BoundLifetimes> {
720 fn parse(input: ParseStream) -> Result<Self> {
721 if input.peek(crate::token::ForToken![for]) {
722 input.parse().map(Some)
723 } else {
724 Ok(None)
725 }
726 }
727 }
728
729 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
730 impl Parse for TypeParam {
731 fn parse(input: ParseStream) -> Result<Self> {
732 let attrs = input.call(Attribute::parse_outer)?;
733 let ident: Ident = input.parse()?;
734 let colon_token: Option<crate::token::ColonToken![:]> = input.parse()?;
735
736 let mut bounds = Punctuated::new();
737 if colon_token.is_some() {
738 loop {
739 if input.is_empty()
740 || input.peek(crate::token::CommaToken![,])
741 || input.peek(crate::token::GtToken![>])
742 || input.peek(crate::token::EqToken![=])
743 {
744 break;
745 }
746 bounds.push_value({
747 let allow_precise_capture = false;
748 let allow_const = true;
749 TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
750 });
751 if !input.peek(crate::token::PlusToken![+]) {
752 break;
753 }
754 let punct: crate::token::PlusToken![+] = input.parse()?;
755 bounds.push_punct(punct);
756 }
757 }
758
759 let default = if let Some(eq_token) = input.parse::<Option<crate::token::EqToken![=]>>()? {
760 Some((eq_token, input.parse::<Type>()?))
761 } else {
762 None
763 };
764
765 Ok(TypeParam {
766 attrs,
767 ident,
768 colon_token,
769 bounds,
770 default,
771 })
772 }
773 }
774
775 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
776 impl Parse for TypeParamBound {
777 fn parse(input: ParseStream) -> Result<Self> {
778 let allow_precise_capture = true;
779 let allow_const = true;
780 Self::parse_single(input, allow_precise_capture, allow_const)
781 }
782 }
783
784 impl TypeParamBound {
785 pub(crate) fn parse_single(
786 input: ParseStream,
787 #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool,
788 allow_const: bool,
789 ) -> Result<Self> {
790 if input.peek(Lifetime) {
791 return Lifetime::parse_any(input).map(TypeParamBound::Lifetime);
792 }
793
794 #[cfg(feature = "full")]
795 {
796 if input.peek(crate::token::UseToken![use]) {
797 let precise_capture_begin = input.cursor();
798 let precise_capture: PreciseCapture = input.parse()?;
799 return if allow_precise_capture {
800 Ok(TypeParamBound::PreciseCapture(precise_capture))
801 } else {
802 let msg = "`use<...>` precise capturing syntax is not allowed here";
803 Err(Error::new_range(precise_capture_begin..input.cursor(), msg))
804 };
805 }
806 }
807
808 let begin = input.cursor();
809
810 let content;
811 let (paren_token, content) = if input.peek(token::Paren) {
812 (Some(match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input)), &content)
813 } else {
814 (None, input)
815 };
816
817 if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? {
818 bound.paren_token = paren_token;
819 Ok(TypeParamBound::Trait(bound))
820 } else {
821 Ok(TypeParamBound::Verbatim(verbatim::between(
822 begin,
823 input.cursor(),
824 )))
825 }
826 }
827
828 pub(crate) fn parse_multiple(
829 input: ParseStream,
830 allow_plus: bool,
831 allow_precise_capture: bool,
832 allow_const: bool,
833 ) -> Result<Punctuated<Self, crate::token::PlusToken![+]>> {
834 let mut bounds = Punctuated::new();
835 loop {
836 let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
837 bounds.push_value(bound);
838 if !(allow_plus && input.peek(crate::token::PlusToken![+])) {
839 break;
840 }
841 bounds.push_punct(input.parse()?);
842 if !(input.peek(Ident::peek_any)
843 || input.peek(crate::token::PathSepToken![::])
844 || input.peek(crate::token::QuestionToken![?])
845 || input.peek(Lifetime)
846 || input.peek(token::Paren)
847 || (allow_const && (input.peek(token::Bracket) || input.peek(crate::token::ConstToken![const]))))
848 {
849 break;
850 }
851 }
852 Ok(bounds)
853 }
854 }
855
856 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
857 impl Parse for TraitBound {
858 fn parse(input: ParseStream) -> Result<Self> {
859 let allow_const = false;
860 Self::do_parse(input, allow_const).map(Option::unwrap)
861 }
862 }
863
864 impl TraitBound {
865 fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
866 let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
867
868 let is_conditionally_const = truecfg!(feature = "full") && input.peek(token::Bracket);
869 let is_unconditionally_const = truecfg!(feature = "full") && input.peek(crate::token::ConstToken![const]);
870 if is_conditionally_const {
871 let conditionally_const;
872 let bracket_token = match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
conditionally_const = brackets.content;
_ = conditionally_const;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(conditionally_const in input);
873 conditionally_const.parse::<crate::token::ConstToken![const]>()?;
874 if !allow_const {
875 let msg = "`[const]` is not allowed here";
876 return Err(Error::new(bracket_token.span.join(), msg));
877 }
878 } else if is_unconditionally_const {
879 let const_token: crate::token::ConstToken![const] = input.parse()?;
880 if !allow_const {
881 let msg = "`const` is not allowed here";
882 return Err(Error::new(const_token.span, msg));
883 }
884 }
885
886 let maybe: Option<crate::token::QuestionToken![?]> = input.parse()?;
887 if lifetimes.is_none() && maybe.is_some() {
888 lifetimes = input.parse()?;
889 }
890
891 let mut path: Path = input.parse()?;
892 if path.segments.last().unwrap().arguments.is_empty()
893 && (input.peek(token::Paren) || input.peek(crate::token::PathSepToken![::]) && input.peek3(token::Paren))
894 {
895 input.parse::<Option<crate::token::PathSepToken![::]>>()?;
896 let args: ParenthesizedGenericArguments = input.parse()?;
897 let parenthesized = PathArguments::Parenthesized(args);
898 path.segments.last_mut().unwrap().arguments = parenthesized;
899 }
900
901 if lifetimes.is_some() {
902 if let Some(maybe) = maybe {
903 let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
904 return Err(Error::new(maybe.span, msg));
905 }
906 }
907
908 if is_conditionally_const || is_unconditionally_const {
909 Ok(None)
910 } else {
911 Ok(Some(TraitBound {
912 paren_token: None,
913 lifetimes,
914 modifiers: TraitBoundModifiers {},
915 maybe,
916 path,
917 }))
918 }
919 }
920 }
921
922 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
923 impl Parse for ConstParam {
924 fn parse(input: ParseStream) -> Result<Self> {
925 Ok(ConstParam {
926 attrs: input.call(Attribute::parse_outer)?,
927 const_token: input.parse()?,
928 ident: input.parse()?,
929 colon_token: input.parse()?,
930 ty: input.parse()?,
931 default: {
932 if input.peek(crate::token::EqToken![=]) {
933 let eq_token = input.parse()?;
934 let default = path::parsing::const_argument(input)?;
935 Some((eq_token, default))
936 } else {
937 None
938 }
939 },
940 })
941 }
942 }
943
944 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
945 impl Parse for WhereClause {
946 fn parse(input: ParseStream) -> Result<Self> {
947 let where_token: crate::token::WhereToken![where] = input.parse()?;
948
949 if choose_generics_over_qpath(input) {
950 return Err(input
951 .error("generic parameters on `where` clauses are reserved for future use"));
952 }
953
954 Ok(WhereClause {
955 where_token,
956 predicates: {
957 let mut predicates = Punctuated::new();
958 loop {
959 if input.is_empty()
960 || input.peek(token::Brace)
961 || input.peek(crate::token::CommaToken![,])
962 || input.peek(crate::token::SemiToken![;])
963 || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
964 || input.peek(crate::token::EqToken![=])
965 {
966 break;
967 }
968 let value = input.parse()?;
969 predicates.push_value(value);
970 if !input.peek(crate::token::CommaToken![,]) {
971 break;
972 }
973 let punct = input.parse()?;
974 predicates.push_punct(punct);
975 }
976 predicates
977 },
978 })
979 }
980 }
981
982 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
983 impl Parse for Option<WhereClause> {
984 fn parse(input: ParseStream) -> Result<Self> {
985 if input.peek(crate::token::WhereToken![where]) {
986 input.parse().map(Some)
987 } else {
988 Ok(None)
989 }
990 }
991 }
992
993 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
994 impl Parse for WherePredicate {
995 fn parse(input: ParseStream) -> Result<Self> {
996 let attrs = input.call(Attribute::parse_outer)?;
997 if input.peek(Lifetime) && input.peek2(crate::token::ColonToken![:]) {
998 Ok(WherePredicate::Lifetime(PredicateLifetime {
999 attrs,
1000 lifetime: Lifetime::parse_any(input)?,
1001 colon_token: input.parse()?,
1002 bounds: {
1003 let mut bounds = Punctuated::new();
1004 loop {
1005 if input.is_empty()
1006 || input.peek(token::Brace)
1007 || input.peek(crate::token::CommaToken![,])
1008 || input.peek(crate::token::SemiToken![;])
1009 || input.peek(crate::token::ColonToken![:])
1010 || input.peek(crate::token::EqToken![=])
1011 {
1012 break;
1013 }
1014 let value = Lifetime::parse_any(input)?;
1015 bounds.push_value(value);
1016 if !input.peek(crate::token::PlusToken![+]) {
1017 break;
1018 }
1019 let punct = input.parse()?;
1020 bounds.push_punct(punct);
1021 }
1022 bounds
1023 },
1024 }))
1025 } else {
1026 Ok(WherePredicate::Type(PredicateType {
1027 attrs,
1028 lifetimes: input.parse()?,
1029 bounded_ty: input.parse()?,
1030 colon_token: input.parse()?,
1031 bounds: {
1032 let mut bounds = Punctuated::new();
1033 loop {
1034 if input.is_empty()
1035 || input.peek(token::Brace)
1036 || input.peek(crate::token::CommaToken![,])
1037 || input.peek(crate::token::SemiToken![;])
1038 || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
1039 || input.peek(crate::token::EqToken![=])
1040 {
1041 break;
1042 }
1043 bounds.push_value({
1044 let allow_precise_capture = false;
1045 let allow_const = true;
1046 TypeParamBound::parse_single(
1047 input,
1048 allow_precise_capture,
1049 allow_const,
1050 )?
1051 });
1052 if !input.peek(crate::token::PlusToken![+]) {
1053 break;
1054 }
1055 let punct = input.parse()?;
1056 bounds.push_punct(punct);
1057 }
1058 bounds
1059 },
1060 }))
1061 }
1062 }
1063 }
1064
1065 #[cfg(feature = "full")]
1066 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1067 impl Parse for PreciseCapture {
1068 fn parse(input: ParseStream) -> Result<Self> {
1069 let use_token: crate::token::UseToken![use] = input.parse()?;
1070 let lt_token: crate::token::LtToken![<] = input.parse()?;
1071 let mut params = Punctuated::new();
1072 loop {
1073 let lookahead = input.lookahead1();
1074 params.push_value(
1075 if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self])
1076 {
1077 input.parse::<CapturedParam>()?
1078 } else if lookahead.peek(crate::token::GtToken![>]) {
1079 break;
1080 } else {
1081 return Err(lookahead.error());
1082 },
1083 );
1084 let lookahead = input.lookahead1();
1085 params.push_punct(if lookahead.peek(crate::token::CommaToken![,]) {
1086 input.parse::<crate::token::CommaToken![,]>()?
1087 } else if lookahead.peek(crate::token::GtToken![>]) {
1088 break;
1089 } else {
1090 return Err(lookahead.error());
1091 });
1092 }
1093 let gt_token: crate::token::GtToken![>] = input.parse()?;
1094 Ok(PreciseCapture {
1095 use_token,
1096 lt_token,
1097 params,
1098 gt_token,
1099 })
1100 }
1101 }
1102
1103 #[cfg(feature = "full")]
1104 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1105 impl Parse for CapturedParam {
1106 fn parse(input: ParseStream) -> Result<Self> {
1107 let lookahead = input.lookahead1();
1108 if lookahead.peek(Lifetime) {
1109 Lifetime::parse_any(input).map(CapturedParam::Lifetime)
1110 } else if lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self]) {
1111 input.call(Ident::parse_any).map(CapturedParam::Ident)
1112 } else {
1113 Err(lookahead.error())
1114 }
1115 }
1116 }
1117
1118 pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
1119 input.peek(crate::token::LtToken![<])
1142 && (input.peek2(crate::token::GtToken![>])
1143 || input.peek2(crate::token::PoundToken![#])
1144 || (input.peek2(Lifetime) || input.peek2(Ident))
1145 && (input.peek3(crate::token::GtToken![>])
1146 || input.peek3(crate::token::CommaToken![,])
1147 || input.peek3(crate::token::ColonToken![:]) && !input.peek3(crate::token::PathSepToken![::])
1148 || input.peek3(crate::token::EqToken![=]))
1149 || input.peek2(crate::token::ConstToken![const]))
1150 }
1151
1152 #[cfg(feature = "full")]
1153 pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
1154 let input = input.fork();
1155 input.call(Ident::parse_any).unwrap(); choose_generics_over_qpath(&input)
1157 }
1158}
1159
1160#[cfg(feature = "printing")]
1161pub(crate) mod printing {
1162 use crate::attr::FilterAttrs;
1163 #[cfg(feature = "full")]
1164 use crate::expr;
1165 use crate::expr::Expr;
1166 #[cfg(feature = "full")]
1167 use crate::fixup::FixupContext;
1168 use crate::generics::{
1169 BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
1170 PredicateLifetime, PredicateType, TraitBound, Turbofish, TypeGenerics, TypeParam,
1171 WhereClause,
1172 };
1173 #[cfg(feature = "full")]
1174 use crate::generics::{CapturedParam, PreciseCapture};
1175 use crate::print::TokensOrDefault;
1176 use crate::token;
1177 use proc_macro2::TokenStream;
1178 use quote::{ToTokens, TokenStreamExt as _};
1179
1180 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1181 impl ToTokens for Generics {
1182 fn to_tokens(&self, tokens: &mut TokenStream) {
1183 if self.params.is_empty() {
1184 return;
1185 }
1186
1187 TokensOrDefault(&self.lt_token).to_tokens(tokens);
1188
1189 let mut trailing_or_empty = true;
1192 for param in self.params.pairs() {
1193 if let GenericParam::Lifetime(_) = **param.value() {
1194 param.to_tokens(tokens);
1195 trailing_or_empty = param.punct().is_some();
1196 }
1197 }
1198 for param in self.params.pairs() {
1199 match param.value() {
1200 GenericParam::Type(_) | GenericParam::Const(_) => {
1201 if !trailing_or_empty {
1202 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1203 trailing_or_empty = true;
1204 }
1205 param.to_tokens(tokens);
1206 }
1207 GenericParam::Lifetime(_) => {}
1208 }
1209 }
1210
1211 TokensOrDefault(&self.gt_token).to_tokens(tokens);
1212 }
1213 }
1214
1215 impl<'a> ToTokens for ImplGenerics<'a> {
1216 fn to_tokens(&self, tokens: &mut TokenStream) {
1217 if self.0.params.is_empty() {
1218 return;
1219 }
1220
1221 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1222
1223 let mut trailing_or_empty = true;
1226 for param in self.0.params.pairs() {
1227 if let GenericParam::Lifetime(_) = **param.value() {
1228 param.to_tokens(tokens);
1229 trailing_or_empty = param.punct().is_some();
1230 }
1231 }
1232 for param in self.0.params.pairs() {
1233 if let GenericParam::Lifetime(_) = **param.value() {
1234 continue;
1235 }
1236 if !trailing_or_empty {
1237 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1238 trailing_or_empty = true;
1239 }
1240 match param.value() {
1241 GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1242 GenericParam::Type(param) => {
1243 tokens.append_all(param.attrs.outer());
1245 param.ident.to_tokens(tokens);
1246 if !param.bounds.is_empty() {
1247 TokensOrDefault(¶m.colon_token).to_tokens(tokens);
1248 param.bounds.to_tokens(tokens);
1249 }
1250 }
1251 GenericParam::Const(param) => {
1252 tokens.append_all(param.attrs.outer());
1254 param.const_token.to_tokens(tokens);
1255 param.ident.to_tokens(tokens);
1256 param.colon_token.to_tokens(tokens);
1257 param.ty.to_tokens(tokens);
1258 }
1259 }
1260 param.punct().to_tokens(tokens);
1261 }
1262
1263 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1264 }
1265 }
1266
1267 impl<'a> ToTokens for TypeGenerics<'a> {
1268 fn to_tokens(&self, tokens: &mut TokenStream) {
1269 if self.0.params.is_empty() {
1270 return;
1271 }
1272
1273 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1274
1275 let mut trailing_or_empty = true;
1278 for param in self.0.params.pairs() {
1279 if let GenericParam::Lifetime(def) = *param.value() {
1280 def.lifetime.to_tokens(tokens);
1282 param.punct().to_tokens(tokens);
1283 trailing_or_empty = param.punct().is_some();
1284 }
1285 }
1286 for param in self.0.params.pairs() {
1287 if let GenericParam::Lifetime(_) = **param.value() {
1288 continue;
1289 }
1290 if !trailing_or_empty {
1291 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1292 trailing_or_empty = true;
1293 }
1294 match param.value() {
1295 GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1296 GenericParam::Type(param) => {
1297 param.ident.to_tokens(tokens);
1299 }
1300 GenericParam::Const(param) => {
1301 param.ident.to_tokens(tokens);
1303 }
1304 }
1305 param.punct().to_tokens(tokens);
1306 }
1307
1308 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1309 }
1310 }
1311
1312 impl<'a> ToTokens for Turbofish<'a> {
1313 fn to_tokens(&self, tokens: &mut TokenStream) {
1314 if !self.0.params.is_empty() {
1315 <crate::token::PathSepToken![::]>::default().to_tokens(tokens);
1316 TypeGenerics(self.0).to_tokens(tokens);
1317 }
1318 }
1319 }
1320
1321 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1322 impl ToTokens for BoundLifetimes {
1323 fn to_tokens(&self, tokens: &mut TokenStream) {
1324 self.for_token.to_tokens(tokens);
1325 self.lt_token.to_tokens(tokens);
1326 self.lifetimes.to_tokens(tokens);
1327 self.gt_token.to_tokens(tokens);
1328 }
1329 }
1330
1331 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1332 impl ToTokens for LifetimeParam {
1333 fn to_tokens(&self, tokens: &mut TokenStream) {
1334 tokens.append_all(self.attrs.outer());
1335 self.lifetime.to_tokens(tokens);
1336 if !self.bounds.is_empty() {
1337 TokensOrDefault(&self.colon_token).to_tokens(tokens);
1338 self.bounds.to_tokens(tokens);
1339 }
1340 }
1341 }
1342
1343 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1344 impl ToTokens for TypeParam {
1345 fn to_tokens(&self, tokens: &mut TokenStream) {
1346 tokens.append_all(self.attrs.outer());
1347 self.ident.to_tokens(tokens);
1348 if !self.bounds.is_empty() {
1349 TokensOrDefault(&self.colon_token).to_tokens(tokens);
1350 self.bounds.to_tokens(tokens);
1351 }
1352 if let Some((eq_token, default)) = &self.default {
1353 eq_token.to_tokens(tokens);
1354 default.to_tokens(tokens);
1355 }
1356 }
1357 }
1358
1359 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1360 impl ToTokens for TraitBound {
1361 fn to_tokens(&self, tokens: &mut TokenStream) {
1362 let to_tokens = |tokens: &mut TokenStream| {
1363 self.lifetimes.to_tokens(tokens);
1364 self.maybe.to_tokens(tokens);
1365 self.path.to_tokens(tokens);
1366 };
1367 match &self.paren_token {
1368 Some(paren) => paren.surround(tokens, to_tokens),
1369 None => to_tokens(tokens),
1370 }
1371 }
1372 }
1373
1374 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1375 impl ToTokens for ConstParam {
1376 fn to_tokens(&self, tokens: &mut TokenStream) {
1377 tokens.append_all(self.attrs.outer());
1378 self.const_token.to_tokens(tokens);
1379 self.ident.to_tokens(tokens);
1380 self.colon_token.to_tokens(tokens);
1381 self.ty.to_tokens(tokens);
1382 if let Some((eq_token, default)) = &self.default {
1383 eq_token.to_tokens(tokens);
1384 print_const_argument(default, tokens);
1385 }
1386 }
1387 }
1388
1389 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1390 impl ToTokens for WhereClause {
1391 fn to_tokens(&self, tokens: &mut TokenStream) {
1392 if !self.predicates.is_empty() {
1393 self.where_token.to_tokens(tokens);
1394 self.predicates.to_tokens(tokens);
1395 }
1396 }
1397 }
1398
1399 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1400 impl ToTokens for PredicateLifetime {
1401 fn to_tokens(&self, tokens: &mut TokenStream) {
1402 tokens.append_all(self.attrs.outer());
1403 self.lifetime.to_tokens(tokens);
1404 self.colon_token.to_tokens(tokens);
1405 self.bounds.to_tokens(tokens);
1406 }
1407 }
1408
1409 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1410 impl ToTokens for PredicateType {
1411 fn to_tokens(&self, tokens: &mut TokenStream) {
1412 tokens.append_all(self.attrs.outer());
1413 self.lifetimes.to_tokens(tokens);
1414 self.bounded_ty.to_tokens(tokens);
1415 self.colon_token.to_tokens(tokens);
1416 self.bounds.to_tokens(tokens);
1417 }
1418 }
1419
1420 #[cfg(feature = "full")]
1421 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1422 impl ToTokens for PreciseCapture {
1423 fn to_tokens(&self, tokens: &mut TokenStream) {
1424 self.use_token.to_tokens(tokens);
1425 self.lt_token.to_tokens(tokens);
1426
1427 let mut trailing_or_empty = true;
1430 for param in self.params.pairs() {
1431 if let CapturedParam::Lifetime(_) = **param.value() {
1432 param.to_tokens(tokens);
1433 trailing_or_empty = param.punct().is_some();
1434 }
1435 }
1436 for param in self.params.pairs() {
1437 if let CapturedParam::Ident(_) = **param.value() {
1438 if !trailing_or_empty {
1439 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1440 trailing_or_empty = true;
1441 }
1442 param.to_tokens(tokens);
1443 }
1444 }
1445
1446 self.gt_token.to_tokens(tokens);
1447 }
1448 }
1449
1450 #[cfg(feature = "full")]
1451 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1452 impl ToTokens for CapturedParam {
1453 fn to_tokens(&self, tokens: &mut TokenStream) {
1454 match self {
1455 CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
1456 CapturedParam::Ident(ident) => ident.to_tokens(tokens),
1457 }
1458 }
1459 }
1460
1461 pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
1462 match expr {
1463 Expr::Lit(expr) => expr.to_tokens(tokens),
1464
1465 Expr::Path(expr)
1466 if expr.attrs.is_empty()
1467 && expr.qself.is_none()
1468 && expr.path.get_ident().is_some() =>
1469 {
1470 expr.to_tokens(tokens);
1471 }
1472
1473 #[cfg(feature = "full")]
1474 Expr::Block(expr) => expr.to_tokens(tokens),
1475
1476 #[cfg(not(feature = "full"))]
1477 Expr::Verbatim(expr) => expr.to_tokens(tokens),
1478
1479 _ => token::Brace::default().surround(tokens, |tokens| {
1482 #[cfg(feature = "full")]
1483 expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
1484
1485 #[cfg(not(feature = "full"))]
1486 expr.to_tokens(tokens);
1487 }),
1488 }
1489 }
1490}