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}