hacky_types/
lib.rs

1mod extension_method;
2
3/// Creates an "extension" method for a type by implementing a custom trait with a single method.
4/// This is a workaround to enable chaining utility functions without modifying the original type.
5/// The first parameter of the annotated function will be used as `self` in the trait method.
6///
7/// If it is a generic type parameter (e.g., `T`, `*const T`, `&mut T`, etc.),
8/// the same type parameter and its lifetime (if any) will be used as the trait generics.
9///
10/// If the first parameter type is `impl Trait`, it will be converted to a generic type parameter with a trait bound.
11/// - To specify a custom name for the generated trait, use `trait_name = "MyTraitName"`
12/// - To specify a custom name for the generic type parameter for `impl Trait`, use `impl_type_param = "MyT"`
13/// - The original function will be preserved by default, use `remove_fn = true` to remove it
14///
15/// Note: The annotated function cannot be `extern`, and must have at least one input parameter. The input parameter cannot be of type `Self`.
16/// Example:
17/// ```rust no_run
18/// use core::ops::Add;
19///
20/// #[extension_method(trait_name = "Double", remove_fn = true)]
21/// pub fn double<T>(val: T) -> T where T: Add<Output = T> + Copy {
22///     val + val
23/// }
24///
25/// let a = 2;
26/// assert_eq!(a.double(), 4);
27#[proc_macro_attribute]
28pub fn extension_method(
29    attr: proc_macro::TokenStream,
30    item: proc_macro::TokenStream,
31) -> proc_macro::TokenStream {
32    extension_method::main(attr, item)
33}