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