macro_tools/generic_params.rs
1//!
2//! Functions and structures to handle and manipulate generic parameters using the `syn` crate. It's designed to support macro-driven code generation by simplifying, merging, extracting, and decomposing `syn ::Generics`.
3//!
4
5// Sub-modules
6pub mod classification;
7pub mod filter;
8pub mod combine;
9
10/// Define a private namespace for all its items.
11mod private
12{
13 use crate :: *;
14
15 /// A `GenericsWithWhere` struct to handle the parsing of Rust generics with an explicit `where` clause.
16 ///
17 /// This wrapper addresses the limitation in the `syn` crate where parsing `Generics` directly from a `ParseStream`
18 /// does not automatically handle associated `where` clauses. By integrating `where` clause parsing into the
19 /// `GenericsWithWhere`, this struct provides a seamless way to capture both the generics and their constraints
20 /// in scenarios where the `where` clause is crucial for type constraints and bounds in Rust macros and code generation.
21 ///
22 /// Usage :
23 ///
24 /// ```
25 /// let parsed_generics: macro_tools ::generic_params ::GenericsWithWhere
26 /// = syn ::parse_str( "< T: Clone, U: Default = Default1 > where T: Default" ).unwrap();
27 /// assert!( parsed_generics.generics.params.len() == 2 );
28 /// assert!( parsed_generics.generics.where_clause.is_some() );
29 /// ```
30 ///
31 #[ derive( Debug ) ]
32 pub struct GenericsWithWhere
33 {
34 /// Syn's generics parameters.
35 pub generics: syn ::Generics,
36 }
37
38 impl GenericsWithWhere
39 {
40 /// Unwraps the `GenericsWithWhere` to retrieve the inner `syn ::Generics`.
41 #[ must_use ]
42 pub fn unwrap(self) -> syn ::Generics
43 {
44 self.generics
45 }
46
47 /// Parses a string to a `GenericsWithWhere`, specifically designed to handle generics syntax with where clauses effectively.
48 ///
49 /// This function provides a convenient way to parse generic parameters and their associated
50 /// `where` clauses from a string slice, returning a `GenericsWithWhere` instance.
51 ///
52 /// # Arguments
53 ///
54 /// * `s` - The string slice containing the generics and optional `where` clause (e.g., `"< T: Debug > where T: Default"`).
55 ///
56 /// # Returns
57 ///
58 /// Returns a `syn ::Result` which is `Ok(GenericsWithWhere)` on successful parsing,
59 /// or `Err(syn ::Error)` if the input string does not conform to valid Rust generics syntax.
60 ///
61 /// # Errors
62 ///
63 /// Returns a `syn ::Error` if the input string `s` cannot be parsed as valid Rust generics
64 /// or a `where` clause.
65 ///
66 /// # Examples
67 ///
68 /// ```rust
69 /// use macro_tools ::generic_params ::GenericsWithWhere;
70 ///
71 /// let parsed = GenericsWithWhere ::parse_from_str( "< T: Clone, U: Default = Default1 > where T: Default" ).unwrap();
72 /// assert!( parsed.generics.params.len() == 2 );
73 /// assert!( parsed.generics.where_clause.is_some() );
74 ///
75 /// let parsed_no_where = GenericsWithWhere ::parse_from_str( "< T >" ).unwrap();
76 /// assert!( parsed_no_where.generics.params.len() == 1 );
77 /// assert!( parsed_no_where.generics.where_clause.is_none() );
78 ///
79 /// let parsed_only_where = GenericsWithWhere ::parse_from_str( "where T: Debug" ).unwrap();
80 /// assert!( parsed_only_where.generics.params.is_empty() );
81 /// assert!( parsed_only_where.generics.where_clause.is_some() );
82 /// ```
83 pub fn parse_from_str(s: &str) -> syn ::Result< GenericsWithWhere >
84 {
85 syn ::parse_str :: < GenericsWithWhere >(s)
86 }
87 }
88
89 impl syn ::parse ::Parse for GenericsWithWhere
90 {
91 fn parse(input: syn ::parse ::ParseStream< '_ >) -> syn ::Result< Self >
92 {
93 let generics: syn ::Generics = input.parse()?;
94 let where_clause: Option< syn ::WhereClause > = input.parse()?;
95
96 let mut generics_clone = generics.clone();
97 generics_clone.where_clause = where_clause;
98
99 Ok(GenericsWithWhere {
100 generics: generics_clone,
101 })
102 }
103 }
104
105 impl quote ::ToTokens for GenericsWithWhere
106 {
107 fn to_tokens(&self, tokens: &mut proc_macro2 ::TokenStream)
108 {
109 self.generics.to_tokens(tokens);
110 }
111 }
112
113 impl From< GenericsWithWhere > for syn ::Generics
114 {
115 fn from(g: GenericsWithWhere) -> Self
116 {
117 g.generics
118 }
119 }
120
121 impl From< syn ::Generics > for GenericsWithWhere
122 {
123 fn from(generics: syn ::Generics) -> Self
124 {
125 GenericsWithWhere { generics }
126 }
127 }
128
129 /// A wrapper around a reference to `syn ::Generics` to provide convenient helper methods
130 /// for generating token streams related to generic parameters.
131 ///
132 /// This is particularly useful in procedural macros for constructing parts of function
133 /// signatures, type paths, and where clauses that involve generics.
134 #[ derive( Debug, Clone, Copy ) ]
135 pub struct GenericsRef< 'a >
136 {
137 syn_generics: &'a syn ::Generics,
138 }
139
140 impl< 'a > GenericsRef< 'a >
141 {
142 /// Creates a new `GenericsRef` from a reference to `syn ::Generics`.
143 #[ must_use ]
144 pub fn new_borrowed(syn_generics: &'a syn ::Generics) -> Self
145 {
146 Self { syn_generics }
147 }
148
149 /// Creates a new `GenericsRef` from a reference to `syn ::Generics`. Alias for `new_borrowed`.
150 #[ must_use ]
151 pub fn new(syn_generics: &'a syn ::Generics) -> Self
152 {
153 Self ::new_borrowed(syn_generics)
154 }
155
156 /// Returns the `impl_generics` part (e.g., `< T: Trait, 'b, const C: usize >`)
157 /// as a `TokenStream` if generics are present, otherwise an empty `TokenStream`.
158 ///
159 /// This is suitable for use in `impl < #impl_generics > Struct ...` contexts.
160 /// It includes bounds and lifetimes.
161 #[ must_use ]
162 pub fn impl_generics_tokens_if_any( &self ) -> proc_macro2 ::TokenStream
163 {
164 if self.syn_generics.params.is_empty()
165 {
166 return quote ::quote! {};
167 }
168 let (impl_g, _, _) = self.syn_generics.split_for_impl();
169 quote ::quote! { #impl_g }
170 }
171
172 /// Returns the `ty_generics` part (e.g., `< T, 'b, C >`) as a `TokenStream`
173 /// if generics are present, otherwise an empty `TokenStream`.
174 ///
175 /// This is suitable for use in type paths like `Struct :: < #ty_generics >`.
176 /// It includes only the identifiers of the generic parameters (types, lifetimes, consts).
177 #[ must_use ]
178 pub fn ty_generics_tokens_if_any( &self ) -> proc_macro2 ::TokenStream
179 {
180 if self.syn_generics.params.is_empty()
181 {
182 return quote ::quote! {};
183 }
184 let (_, ty_g, _) = self.syn_generics.split_for_impl();
185 quote ::quote! { #ty_g }
186 }
187
188 /// Returns the `where_clause` (e.g., `where T: Trait`) as a `TokenStream`
189 /// if a where clause is present in the original generics, otherwise an empty `TokenStream`.
190 #[ must_use ]
191 pub fn where_clause_tokens_if_any( &self ) -> proc_macro2 ::TokenStream
192 {
193 let (_, _, where_clause) = self.syn_generics.split_for_impl();
194 quote ::quote! { #where_clause }
195 }
196
197 /// Returns a token stream representing a path to a type, including its generic arguments
198 /// if present (e.g., `MyType :: < T, U >`). If no generics are present, it returns
199 /// just the `base_ident`.
200 ///
201 /// # Arguments
202 ///
203 /// * `base_ident` : The identifier of the base type (e.g., `MyType`).
204 #[ must_use ]
205 pub fn type_path_tokens_if_any(&self, base_ident: &syn ::Ident) -> proc_macro2 ::TokenStream
206 {
207 if self.syn_generics.params.is_empty()
208 {
209 quote ::quote! { #base_ident }
210 }
211 else
212 {
213 let (_, ty_g, _) = self.syn_generics.split_for_impl();
214 quote ::quote! { #base_ident #ty_g }
215 }
216 }
217
218 /// Get classification of the generics.
219 ///
220 /// This method analyzes the generic parameters and returns a classification
221 /// containing information about the types of parameters present.
222 ///
223 /// # Example
224 ///
225 /// ```
226 /// use macro_tools ::generic_params :: { GenericsRef, classify_generics };
227 /// use syn ::parse_quote;
228 ///
229 /// let generics: syn ::Generics = parse_quote! { < 'a, T, const N: usize > };
230 /// let generics_ref = GenericsRef ::new(&generics);
231 /// let classification = generics_ref.classification();
232 ///
233 /// assert!(classification.has_mixed);
234 /// assert_eq!(classification.lifetimes.len(), 1);
235 /// assert_eq!(classification.types.len(), 1);
236 /// assert_eq!(classification.consts.len(), 1);
237 /// ```
238 #[ must_use ]
239 pub fn classification( &self ) -> super ::classification ::GenericsClassification< 'a >
240 {
241 super ::classification ::classify_generics(self.syn_generics)
242 }
243
244 /// Get impl generics without lifetimes.
245 ///
246 /// This method returns the impl generics token stream with lifetime parameters filtered out,
247 /// keeping only type and const parameters.
248 ///
249 /// # Example
250 ///
251 /// ```
252 /// use macro_tools ::generic_params ::GenericsRef;
253 /// use syn ::parse_quote;
254 ///
255 /// let generics: syn ::Generics = parse_quote! { < 'a, T: Clone, const N: usize > };
256 /// let generics_ref = GenericsRef ::new(&generics);
257 /// let impl_no_lifetimes = generics_ref.impl_generics_no_lifetimes();
258 ///
259 /// // Result will be: < T: Clone, const N: usize >
260 /// ```
261 #[ must_use ]
262 pub fn impl_generics_no_lifetimes( &self ) -> proc_macro2 ::TokenStream
263 {
264 let filtered = super ::filter ::filter_params(&self.syn_generics.params, super ::filter ::filter_non_lifetimes);
265 if filtered.is_empty()
266 {
267 quote ::quote! {}
268 } else {
269 quote ::quote! { < #filtered > }
270 }
271 }
272
273 /// Get type generics without lifetimes.
274 ///
275 /// This method returns the type generics token stream with lifetime parameters filtered out,
276 /// keeping only type and const parameters (simplified for type usage).
277 ///
278 /// # Example
279 ///
280 /// ```
281 /// use macro_tools ::generic_params ::GenericsRef;
282 /// use syn ::parse_quote;
283 ///
284 /// let generics: syn ::Generics = parse_quote! { < 'a, T, const N: usize > };
285 /// let generics_ref = GenericsRef ::new(&generics);
286 /// let ty_no_lifetimes = generics_ref.ty_generics_no_lifetimes();
287 ///
288 /// // Result will be: < T, N >
289 /// ```
290 #[ must_use ]
291 pub fn ty_generics_no_lifetimes( &self ) -> proc_macro2 ::TokenStream
292 {
293 let (_, _, ty_params, _) = crate::generic_params::decompose(self.syn_generics);
294 let filtered = super ::filter ::filter_params(&ty_params, super ::filter ::filter_non_lifetimes);
295 if filtered.is_empty()
296 {
297 quote ::quote! {}
298 } else {
299 quote ::quote! { < #filtered > }
300 }
301 }
302
303 /// Check if generics contain only lifetime parameters.
304 ///
305 /// # Example
306 ///
307 /// ```
308 /// use macro_tools ::generic_params ::GenericsRef;
309 /// use syn ::parse_quote;
310 ///
311 /// let generics: syn ::Generics = parse_quote! { < 'a, 'b > };
312 /// let generics_ref = GenericsRef ::new(&generics);
313 /// assert!(generics_ref.has_only_lifetimes());
314 ///
315 /// let generics2: syn ::Generics = parse_quote! { < 'a, T > };
316 /// let generics_ref2 = GenericsRef ::new(&generics2);
317 /// assert!(!generics_ref2.has_only_lifetimes());
318 /// ```
319 #[ must_use ]
320 pub fn has_only_lifetimes( &self ) -> bool
321 {
322 self.classification().has_only_lifetimes
323 }
324
325 /// Check if generics contain only type parameters.
326 ///
327 /// # Example
328 ///
329 /// ```
330 /// use macro_tools ::generic_params ::GenericsRef;
331 /// use syn ::parse_quote;
332 ///
333 /// let generics: syn ::Generics = parse_quote! { < T, U > };
334 /// let generics_ref = GenericsRef ::new(&generics);
335 /// assert!(generics_ref.has_only_types());
336 ///
337 /// let generics2: syn ::Generics = parse_quote! { < T, const N: usize > };
338 /// let generics_ref2 = GenericsRef ::new(&generics2);
339 /// assert!(!generics_ref2.has_only_types());
340 /// ```
341 #[ must_use ]
342 pub fn has_only_types( &self ) -> bool
343 {
344 self.classification().has_only_types
345 }
346
347 /// Check if generics contain only const parameters.
348 ///
349 /// # Example
350 ///
351 /// ```
352 /// use macro_tools ::generic_params ::GenericsRef;
353 /// use syn ::parse_quote;
354 ///
355 /// let generics: syn ::Generics = parse_quote! { < const N: usize, const M: i32 > };
356 /// let generics_ref = GenericsRef ::new(&generics);
357 /// assert!(generics_ref.has_only_consts());
358 /// ```
359 #[ must_use ]
360 pub fn has_only_consts( &self ) -> bool
361 {
362 self.classification().has_only_consts
363 }
364
365 /// Get type path without lifetime parameters.
366 ///
367 /// This method returns a token stream representing a path to a type with
368 /// lifetime parameters filtered out from the generic arguments.
369 ///
370 /// # Arguments
371 ///
372 /// * `base_ident` - The identifier of the base type
373 ///
374 /// # Example
375 ///
376 /// ```
377 /// use macro_tools ::generic_params ::GenericsRef;
378 /// use syn :: { parse_quote, Ident };
379 /// use quote ::format_ident;
380 ///
381 /// let generics: syn ::Generics = parse_quote! { < 'a, T, const N: usize > };
382 /// let generics_ref = GenericsRef ::new(&generics);
383 /// let base = format_ident!("MyType");
384 /// let path = generics_ref.type_path_no_lifetimes(&base);
385 ///
386 /// // Result will be: MyType :: < T, N >
387 /// ```
388 #[ must_use ]
389 pub fn type_path_no_lifetimes(&self, base_ident: &syn ::Ident) -> proc_macro2 ::TokenStream
390 {
391 let ty_no_lifetimes = self.ty_generics_no_lifetimes();
392 if self.syn_generics.params.is_empty() ||
393 self.syn_generics.params.iter().all(|p| matches!(p, syn ::GenericParam ::Lifetime(_))) {
394 quote ::quote! { #base_ident }
395 } else {
396 quote ::quote! { #base_ident #ty_no_lifetimes }
397 }
398 }
399}
400}
401
402
403
404
405// Function implementations moved outside private module
406/// Merges two `syn ::Generics` instances into a new one.
407///
408/// This function takes two references to `syn ::Generics` and combines their
409/// type parameters and where clauses into a new `syn ::Generics` instance. If
410/// both instances have where clauses, the predicates of these clauses are merged
411/// into a single where clause.
412///
413/// # Arguments
414///
415/// * `a` - A reference to the first `syn ::Generics` instance.
416/// * `b` - A reference to the second `syn ::Generics` instance.
417///
418/// # Returns
419///
420/// Returns a new `syn ::Generics` instance containing the merged type parameters
421/// and where clauses from `a` and `b`.
422#[ must_use ]
423#[ allow( clippy ::default_trait_access ) ]
424pub fn merge(a: &syn ::Generics, b: &syn ::Generics) -> syn ::Generics
425{
426 let mut result = syn ::Generics {
427 params: Default ::default(),
428 where_clause: None,
429 lt_token: Some(syn ::token ::Lt ::default()),
430 gt_token: Some(syn ::token ::Gt ::default()),
431 };
432
433 // Merge params
434 for param in &a.params
435 {
436 result.params.push(param.clone());
437 }
438 for param in &b.params
439 {
440 result.params.push(param.clone());
441 }
442
443 // Merge where clauses
444 result.where_clause = match (&a.where_clause, &b.where_clause)
445 {
446 (Some(a_clause), Some(b_clause)) =>
447 {
448 let mut merged_where_clause = syn ::WhereClause {
449 where_token: a_clause.where_token,
450 predicates: a_clause.predicates.clone(),
451 };
452 for predicate in &b_clause.predicates
453 {
454 merged_where_clause.predicates.push(predicate.clone());
455 }
456 Some(merged_where_clause)
457 }
458 (Some(a_clause), None) => Some(a_clause.clone()),
459 (None, Some(b_clause)) => Some(b_clause.clone()),
460 _ => None,
461 };
462
463 result
464}
465
466/// Extracts parameter names from the given `Generics`,
467/// dropping bounds, defaults, and the where clause.
468#[ allow( clippy ::default_trait_access ) ]
469#[ must_use ]
470pub fn only_names(generics: &syn ::Generics) -> syn ::Generics
471{
472 use syn :: { Generics, GenericParam, LifetimeParam, TypeParam, ConstParam };
473
474 let params = generics
475 .params
476 .iter()
477 .map(|param| match param {
478 GenericParam::Type(TypeParam { ident, .. }) => GenericParam::Type(TypeParam {
479 attrs: Vec::new(),
480 ident: ident.clone(),
481 colon_token: None,
482 bounds: Default::default(),
483 eq_token: None,
484 default: None,
485 }),
486 GenericParam::Lifetime(LifetimeParam { lifetime, .. }) => GenericParam::Lifetime(LifetimeParam {
487 attrs: Vec::new(),
488 lifetime: lifetime.clone(),
489 colon_token: None,
490 bounds: Default::default(),
491 }),
492 GenericParam::Const(ConstParam { ident, ty, .. }) => GenericParam::Const(ConstParam {
493 attrs: Vec::new(),
494 const_token: Default::default(),
495 ident: ident.clone(),
496 colon_token: Default::default(),
497 ty: ty.clone(),
498 eq_token: Default::default(),
499 default: None,
500 }),
501 })
502 .collect();
503
504 Generics {
505 params,
506 where_clause: None,
507 lt_token: generics.lt_token,
508 gt_token: generics.gt_token,
509 }
510}
511
512/// Extracts the names of type parameters, lifetimes, and const parameters from the given `Generics`.
513pub fn names(generics: &syn ::Generics) -> impl Iterator< Item = &syn ::Ident >
514{
515 generics.params.iter().map( |param| match param
516 {
517 syn ::GenericParam ::Type(type_param) => &type_param.ident,
518 syn ::GenericParam ::Lifetime(lifetime_def) => &lifetime_def.lifetime.ident,
519 syn ::GenericParam ::Const(const_param) => &const_param.ident,
520 } )
521}
522
523/// Decomposes `syn ::Generics` into components suitable for different usage contexts in Rust implementations.
524#[ allow( clippy ::type_complexity ) ]
525#[ allow( clippy ::too_many_lines ) ]
526#[ must_use ]
527pub fn decompose(
528 generics: &syn ::Generics,
529) -> (
530 syn ::punctuated ::Punctuated< syn ::GenericParam, syn ::token ::Comma >,
531 syn ::punctuated ::Punctuated< syn ::GenericParam, syn ::token ::Comma >,
532 syn ::punctuated ::Punctuated< syn ::GenericParam, syn ::token ::Comma >,
533 syn ::punctuated ::Punctuated< syn ::WherePredicate, syn ::token ::Comma >,
534) {
535 let mut generics_with_defaults = generics.params.clone();
536 crate::punctuated ::ensure_trailing_comma(&mut generics_with_defaults);
537
538 let mut generics_for_impl = syn ::punctuated ::Punctuated ::new();
539 let mut generics_for_ty = syn ::punctuated ::Punctuated ::new();
540
541 // Process each generic parameter
542 let params_count = generics.params.len();
543 for (idx, param) in generics.params.iter().enumerate()
544 {
545 let is_last = idx == params_count - 1;
546 match param
547 {
548 syn ::GenericParam ::Type(type_param) =>
549 {
550 // Retain bounds for generics_for_impl, remove defaults
551 let impl_param = syn ::GenericParam ::Type(syn ::TypeParam {
552 attrs: vec![],
553 ident: type_param.ident.clone(),
554 colon_token: type_param.colon_token,
555 bounds: type_param.bounds.clone(),
556 eq_token: None, // Remove default token
557 default: None, // Remove default value
558 });
559 generics_for_impl.push_value(impl_param);
560 if !is_last
561 {
562 generics_for_impl.push_punct(syn ::token ::Comma ::default());
563 }
564
565 // Simplify for generics_for_ty by removing all except identifiers
566 let ty_param = syn ::GenericParam ::Type(syn ::TypeParam {
567 attrs: vec![],
568 ident: type_param.ident.clone(),
569 colon_token: None,
570 bounds: syn ::punctuated ::Punctuated ::new(),
571 eq_token: None,
572 default: None,
573 });
574 generics_for_ty.push_value(ty_param);
575 if !is_last
576 {
577 generics_for_ty.push_punct(syn ::token ::Comma ::default());
578 }
579 }
580 syn ::GenericParam ::Const(const_param) =>
581 {
582 // Simplify const parameters by removing all details except the identifier
583 let impl_param = syn ::GenericParam ::Const(syn ::ConstParam {
584 attrs: vec![],
585 const_token: const_param.const_token,
586 ident: const_param.ident.clone(),
587 colon_token: const_param.colon_token,
588 ty: const_param.ty.clone(),
589 eq_token: None,
590 default: None,
591 });
592 generics_for_impl.push_value(impl_param);
593 if !is_last
594 {
595 generics_for_impl.push_punct(syn ::token ::Comma ::default());
596 }
597
598 let ty_param = syn ::GenericParam ::Const(syn ::ConstParam {
599 attrs: vec![],
600 const_token: const_param.const_token,
601 ident: const_param.ident.clone(),
602 colon_token: const_param.colon_token,
603 ty: const_param.ty.clone(),
604 eq_token: None,
605 default: None,
606 });
607 generics_for_ty.push_value(ty_param);
608 if !is_last
609 {
610 generics_for_ty.push_punct(syn ::token ::Comma ::default());
611 }
612 }
613 syn ::GenericParam ::Lifetime(lifetime_param) =>
614 {
615 // Lifetimes are added as-is to generics_for_impl and without bounds to generics_for_ty
616 generics_for_impl.push_value(syn ::GenericParam ::Lifetime(lifetime_param.clone()));
617 if !is_last
618 {
619 generics_for_impl.push_punct(syn ::token ::Comma ::default());
620 }
621
622 let ty_param = syn ::GenericParam ::Lifetime(syn ::LifetimeParam {
623 attrs: vec![],
624 lifetime: lifetime_param.lifetime.clone(),
625 colon_token: None,
626 bounds: syn ::punctuated ::Punctuated ::new(),
627 });
628 generics_for_ty.push_value(ty_param);
629 if !is_last
630 {
631 generics_for_ty.push_punct(syn ::token ::Comma ::default());
632 }
633 }
634 }
635 }
636
637 // Remove any trailing punctuation from impl and ty generics to prevent trailing commas
638 while generics_for_impl.trailing_punct()
639 {
640 generics_for_impl.pop_punct();
641 }
642 while generics_for_ty.trailing_punct()
643 {
644 generics_for_ty.pop_punct();
645 }
646
647 // Clone where predicates if present, ensuring they end with a comma
648 let generics_where = if let Some(where_clause) = &generics.where_clause
649 {
650 let mut predicates = where_clause.predicates.clone();
651 crate::punctuated ::ensure_trailing_comma(&mut predicates);
652 predicates
653 } else {
654 syn ::punctuated ::Punctuated ::new()
655 };
656
657 (generics_with_defaults, generics_for_impl, generics_for_ty, generics_where)
658}
659
660#[ doc( inline ) ]
661#[ allow( unused_imports ) ]
662pub use own :: *;
663
664#[ allow( unused_imports ) ]
665/// Own namespace of the module.
666pub mod own
667{
668
669 use super :: *;
670
671 #[ doc( inline ) ]
672 pub use orphan :: *;
673 #[ doc( inline ) ]
674 pub use crate::generic_params::private :: {
675 GenericsRef, GenericsWithWhere,
676 };
677
678 // Re-export the moved functions
679 pub use super::{ merge, only_names, names, decompose };
680
681
682 // Classification utilities
683 #[ doc( inline ) ]
684 pub use crate::generic_params::classification :: {
685 GenericsClassification, classify_generics,
686 DecomposedClassified, decompose_classified,
687 };
688
689 // Filter utilities
690 #[ doc( inline ) ]
691 pub use crate::generic_params::filter :: {
692 filter_params,
693 filter_lifetimes, filter_types, filter_consts, filter_non_lifetimes,
694 };
695
696 // Combination utilities
697 #[ doc( inline ) ]
698 pub use crate::generic_params::combine :: {
699 merge_params_ordered, params_with_additional, params_from_components,
700 };
701}
702
703/// Orphan namespace of the module.
704#[ allow( unused_imports ) ]
705pub mod orphan
706{
707
708 use super :: *;
709 #[ doc( inline ) ]
710 pub use exposed :: *;
711}
712
713/// Exposed namespace of the module.
714#[ allow( unused_imports ) ]
715pub mod exposed
716{
717
718 use super :: *;
719 pub use crate::generic_params;
720
721 #[ doc( inline ) ]
722 pub use prelude :: *;
723}
724
725/// Prelude to use essentials: `use my_module ::prelude :: *`.
726#[ allow( unused_imports ) ]
727pub mod prelude
728{
729 use super :: *;
730}