### Define a base trait with async and impl Trait Source: https://github.com/rust-lang/impl-trait-utils/blob/main/README.md Use the `#[trait_variant::make]` attribute to define a trait with `async fn` and `-> impl Trait` return types. This macro will generate a specialized version of the trait. ```rust #[trait_variant::make(IntFactory: Send)] trait LocalIntFactory { async fn make(&self) -> i32; fn stream(&self) -> impl Iterator; fn call(&self) -> u32; } ``` -------------------------------- ### Implement Experimental trait_transformer with Return Type Notation Source: https://context7.com/rust-lang/impl-trait-utils/llms.txt Utilizes the nightly-only return_type_notation feature to express bounds directly on method return types for trait variants. ```rust #![allow(incomplete_features)] #![feature(return_type_notation)] use std::iter; use trait_transformer::trait_transformer; #[trait_transformer(SendIntFactory: Send)] trait IntFactory { async fn make(&self) -> i32; fn stream(&self) -> impl Iterator; fn call(&self) -> u32; } // The macro generates a subtrait using return type notation: // trait SendIntFactory: IntFactory + Send {} // This is more ergonomic as implementors only need to implement IntFactory struct MyFactory; // Implement only the base trait impl IntFactory for MyFactory { async fn make(&self) -> i32 { 42 } fn stream(&self) -> impl Iterator { iter::once(1).chain(iter::once(2)) } fn call(&self) -> u32 { 0 } } // Opt-in to the Send variant with an empty impl impl SendIntFactory for MyFactory {} // Now the factory can be used with spawn fn thing(factory: impl SendIntFactory + 'static) { tokio::task::spawn(async move { let result = factory.make().await; println!("Made: {}", result); }); } fn main() { let my_factory = MyFactory; thing(my_factory); } ``` -------------------------------- ### Create Send-Bounded Trait Variant with `#[trait_variant::make]` Source: https://context7.com/rust-lang/impl-trait-utils/llms.txt Use `#[trait_variant::make(VariantName: Bounds)]` to generate a new trait variant with specified bounds, preserving the original trait. This is useful for creating a `Send`-compatible version of a trait for async functions and `impl Trait` returns. ```rust use trait_variant::make; use std::future::Future; // Mode 1: Create a new Send-bounded variant while preserving the original trait #[trait_variant::make(SendIntFactory: Send)] pub trait LocalIntFactory { const NAME: &'static str; type MyFut<'a>: Future where Self: 'a; async fn make(&self, x: u32, y: &str) -> i32; fn stream(&self) -> impl Iterator; fn call(&self) -> u32; // Regular methods are not affected fn another_async(&self, input: Result<(), &str>) -> Self::MyFut<'_>; } // The macro generates: // - The original `LocalIntFactory` trait (unchanged) // - A new `SendIntFactory` trait where: // - `async fn make(...)` becomes `fn make(...) -> impl Future + Send` // - `fn stream(...)` becomes `fn stream(...) -> impl Iterator + Send` // - A blanket impl so any `SendIntFactory` implementor also implements `LocalIntFactory` // Implementing the Send variant struct MyFactory; impl SendIntFactory for MyFactory { const NAME: &'static str = "MyFactory"; type MyFut<'a> = std::pin::Pin + Send + 'a>>; fn make(&self, _x: u32, _y: &str) -> impl Future + Send { async { 42 } } fn stream(&self) -> impl Iterator + Send { vec![1, 2, 3].into_iter() } fn call(&self) -> u32 { 100 } fn another_async(&self, _input: Result<(), &str>) -> Self::MyFut<'_> { Box::pin(async {}) } } // Now MyFactory can be spawned on Tokio because it implements SendIntFactory fn spawn_task(factory: impl SendIntFactory + 'static) { tokio::spawn(async move { let result = factory.make(1, "hello").await; println!("Result: {}", result); }); } fn main() { let factory = MyFactory; spawn_task(factory); } ``` -------------------------------- ### Generated specialized trait with Send Source: https://github.com/rust-lang/impl-trait-utils/blob/main/README.md The `trait_variant::make` macro generates a new trait (e.g., `IntFactory`) that is `Send`able and adapts `async fn` to return futures and `-> impl Trait` to include `Send` bounds where appropriate. ```rust use core::future::Future; trait IntFactory: Send { fn make(&self) -> impl Future + Send; fn stream(&self) -> impl Iterator + Send; fn call(&self) -> u32; } ``` -------------------------------- ### Define Generic Traits with trait_variant::make Source: https://context7.com/rust-lang/impl-trait-utils/llms.txt Uses the make macro to generate a Send-bounded variant of a complex generic trait, including support for lifetimes, const generics, and associated types. ```rust use trait_variant::make; use std::fmt::Display; #[trait_variant::make(GenericTrait: Send)] pub trait LocalGenericTrait<'x, S: Sync, Y, const X: usize> where Y: Sync, { const CONST: usize = 3; type F; type A; type B: FromIterator; async fn take(&self, s: S); fn build(&self, items: impl Iterator) -> Self::B; } // This generates: // 1. Original `LocalGenericTrait` with all generics preserved // 2. New `GenericTrait` with the same generics, adding `Send` bound to the trait // and `+ Send` to the async fn return type // 3. Blanket impl: impl<...> LocalGenericTrait<...> for T where T: GenericTrait<...> // Usage with the generated Send variant struct SendableProcessor; impl<'x, const X: usize> GenericTrait<'x, String, i32, X> for SendableProcessor { type F = (); type A = [u8; ANOTHER_CONST as usize]; type B = Vec; async fn take(&self, s: String) { println!("Processing: {}", s); } fn build(&self, items: impl Iterator) -> Self::B { items.collect() } } // Can be used in async spawning contexts async fn process_with_generic<'x, const N: usize>(processor: impl GenericTrait<'x, String, i32, N> + 'static + Send) { tokio::spawn(async move { processor.take("data".to_string()).await; }); } ``` -------------------------------- ### Rewrite Trait In-Place with `#[trait_variant::make]` Source: https://context7.com/rust-lang/impl-trait-utils/llms.txt Use `#[trait_variant::make(Bounds)]` to directly modify the original trait, adding specified bounds to `async fn` and `-> impl Trait` return types without creating a new variant. This is suitable when the original trait definition is no longer needed. ```rust use trait_variant::make; use std::fmt::Display; // Mode 2: Rewrite the trait in place (no new variant created) // Simply pass the bounds without a name prefix #[trait_variant::make(Send + Sync)] pub trait GenericTraitWithBounds<'x, S: Sync, Y, const X: usize> where Y: Sync, { const CONST: usize = 3; type F; type A; type B: FromIterator; async fn take(&self, s: S); fn build(&self, items: impl Iterator) -> Self::B; } // The above gets rewritten to a trait where: // - The trait itself requires `Send + Sync` // - `async fn take(...)` becomes `fn take(...) -> impl Future + Send + Sync` // - Other methods remain unchanged (build returns Self::B, not impl Trait) // Implementation example struct BoundedImpl; impl<'x, S: Sync, Y: Sync, const X: usize> GenericTraitWithBounds<'x, S, Y, X> for BoundedImpl { type F = (); type A = (); type B = Vec; async fn take(&self, _s: S) { // Async work here } fn build(&self, items: impl Iterator) -> Self::B { items.collect() } } ``` -------------------------------- ### Generate Sendable Trait Variant with trait_variant Source: https://github.com/rust-lang/impl-trait-utils/blob/main/trait-variant/README.md Use the `trait_variant::make` attribute to generate a specialized version of a trait that is `Send`able. This is useful for traits involving `async fn` or returning `impl Trait`. ```rust #[trait_variant::make(IntFactory: Send)] trait LocalIntFactory { async fn make(&self) -> i32; fn stream(&self) -> impl Iterator; fn call(&self) -> u32; } ``` ```rust use core::future::Future; trait IntFactory: Send { fn make(&self) -> impl Future + Send; fn stream(&self) -> impl Iterator + Send; fn call(&self) -> u32; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.