From c836eb000cd8bc31998da43c584129d905f20f20 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 1 Feb 2024 05:42:12 +1100 Subject: [PATCH] Remove `async_trait` macro in favor of AFIT & RPITIT (#211) * Use `async fn` in traits * Fix doc tests * Remove more references to async-trait crate * Remove final code reference * Fix docs * Prepare for stable use of RPITIT * Fix compile errors * Remove unnecessary empty lines * Add changelog entry * Fix warning --- .github/workflows/ci.yml | 2 +- BREAKING-CHANGES.md | 2 + Cargo.lock | 13 ------ README.md | 1 - macros/src/lib.rs | 1 - xtra/Cargo.toml | 3 +- xtra/benches/throughput.rs | 4 -- xtra/examples/address_sink.rs | 2 - xtra/examples/backpressure.rs | 1 - xtra/examples/basic_async_std.rs | 1 - xtra/examples/basic_smol.rs | 1 - xtra/examples/basic_tokio.rs | 1 - xtra/examples/basic_wasm_bindgen/Cargo.toml | 1 - xtra/examples/basic_wasm_bindgen/src/lib.rs | 1 - xtra/examples/crude_bench.rs | 5 -- xtra/examples/custom_event_loop.rs | 1 - xtra/examples/interleaved_messages.rs | 3 -- xtra/examples/manual_actor_impl.rs | 4 +- .../message_stealing_multiple_actors.rs | 1 - xtra/examples/scoped_actor_task.rs | 1 - xtra/examples/send_interval.rs | 1 - xtra/src/address.rs | 4 +- xtra/src/chan/ptr.rs | 1 - xtra/src/dispatch_future.rs | 3 +- xtra/src/lib.rs | 46 ++++++++----------- xtra/src/message_channel.rs | 5 +- xtra/tests/basic.rs | 14 ------ xtra/tests/instrumentation.rs | 2 - 28 files changed, 29 insertions(+), 96 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d340fa8..4dd4afbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: toolchain: [ stable, beta, - 1.60.0 # MSRV + 1.75.0 # MSRV ] args: [ --all-features, diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 6daa8b4e..3b6d9fe5 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -8,6 +8,8 @@ ### Changed +- Remove `async_trait` macro in favor of async functions in traits (AFIT). + This bumps xtra's MSRV to `1.75`. - `MessageChannel` is now a `struct` that can be constructed from an `Address` via `MessageChannel::new` or using `From`/`Into`. - Move event-loop related functions from `Context` to xtra's top-level scope. `Context` is now only used within an actor's `Handler`. diff --git a/Cargo.lock b/Cargo.lock index e35a2a89..11b23890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -198,17 +198,6 @@ version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.37", -] - [[package]] name = "atomic-waker" version = "1.1.2" @@ -260,7 +249,6 @@ dependencies = [ name = "basic-wasm-bindgen" version = "0.1.0" dependencies = [ - "async-trait", "console_error_panic_hook", "wasm-bindgen", "wasm-bindgen-futures", @@ -1720,7 +1708,6 @@ name = "xtra" version = "0.6.0" dependencies = [ "async-std", - "async-trait", "catty", "criterion", "event-listener 2.5.3", diff --git a/README.md b/README.md index 5b6653ce..a3419958 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ struct Printer { struct Print(String); -#[async_trait] impl Handler for Printer { type Return = (); diff --git a/macros/src/lib.rs b/macros/src/lib.rs index b4bdb0c1..f40a4a8c 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -19,7 +19,6 @@ pub fn actor_derive(input: TokenStream) -> TokenStream { }; quote! { - #[xtra::prelude::async_trait] impl #impl_generics xtra::Actor for #actor_ident #type_generics #where_clause { type Stop = (); diff --git a/xtra/Cargo.toml b/xtra/Cargo.toml index e73dfc17..ec3de123 100644 --- a/xtra/Cargo.toml +++ b/xtra/Cargo.toml @@ -10,10 +10,9 @@ documentation = "https://docs.rs/xtra" readme = "README.md" keywords = ["async", "actor", "futures", "xtra", "async-await"] categories = ["asynchronous", "concurrency"] -rust-version = "1.60.0" +rust-version = "1.75.0" [dependencies] -async-trait = "0.1.56" catty = "0.1.5" futures-core = "0.3.21" # alloc is the only default feature and we need it. futures-sink = { version = "0.3.21", default-features = false, optional = true } diff --git a/xtra/benches/throughput.rs b/xtra/benches/throughput.rs index 8e32f005..c626450c 100644 --- a/xtra/benches/throughput.rs +++ b/xtra/benches/throughput.rs @@ -1,11 +1,9 @@ -use async_trait::async_trait; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use tokio::runtime::Runtime; use xtra::{Actor, Context, Handler, Mailbox}; struct Counter(u64); -#[async_trait] impl Actor for Counter { type Stop = (); async fn stopped(self) {} @@ -14,7 +12,6 @@ impl Actor for Counter { struct IncrementZst; struct Finish; -#[async_trait::async_trait] impl Handler for Counter { type Return = (); @@ -23,7 +20,6 @@ impl Handler for Counter { } } -#[async_trait::async_trait] impl Handler for Counter { type Return = u64; diff --git a/xtra/examples/address_sink.rs b/xtra/examples/address_sink.rs index 6dc1b318..9c883c2a 100644 --- a/xtra/examples/address_sink.rs +++ b/xtra/examples/address_sink.rs @@ -11,7 +11,6 @@ struct Add(u32); struct GetSum; -#[async_trait] impl Handler for Accumulator { type Return = (); @@ -20,7 +19,6 @@ impl Handler for Accumulator { } } -#[async_trait] impl Handler for Accumulator { type Return = u32; diff --git a/xtra/examples/backpressure.rs b/xtra/examples/backpressure.rs index 12b624cf..8f4f74fa 100644 --- a/xtra/examples/backpressure.rs +++ b/xtra/examples/backpressure.rs @@ -5,7 +5,6 @@ struct Greeter; struct Hello(String); -#[async_trait] impl Handler for Greeter { type Return = (); diff --git a/xtra/examples/basic_async_std.rs b/xtra/examples/basic_async_std.rs index 7ec05e13..5f6f16c3 100644 --- a/xtra/examples/basic_async_std.rs +++ b/xtra/examples/basic_async_std.rs @@ -7,7 +7,6 @@ struct Printer { struct Print(String); -#[async_trait] impl Handler for Printer { type Return = (); diff --git a/xtra/examples/basic_smol.rs b/xtra/examples/basic_smol.rs index 8091d50d..a079934e 100644 --- a/xtra/examples/basic_smol.rs +++ b/xtra/examples/basic_smol.rs @@ -7,7 +7,6 @@ struct Printer { struct Print(String); -#[async_trait] impl Handler for Printer { type Return = (); diff --git a/xtra/examples/basic_tokio.rs b/xtra/examples/basic_tokio.rs index ece043a0..fc11c250 100644 --- a/xtra/examples/basic_tokio.rs +++ b/xtra/examples/basic_tokio.rs @@ -7,7 +7,6 @@ struct Printer { struct Print(String); -#[async_trait] impl Handler for Printer { type Return = (); diff --git a/xtra/examples/basic_wasm_bindgen/Cargo.toml b/xtra/examples/basic_wasm_bindgen/Cargo.toml index 6032a9cc..fa871938 100644 --- a/xtra/examples/basic_wasm_bindgen/Cargo.toml +++ b/xtra/examples/basic_wasm_bindgen/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["cdylib", "rlib"] wasm-bindgen = { version = "0.2.81", default-features = false } wasm-bindgen-futures = { version = "0.4.13", default-features = false } xtra = { path = "../..", features = ["wasm_bindgen", "macros"] } -async-trait = "0.1" [dev-dependencies] wasm-bindgen-test = { version = "0.3.13", default-features = false } diff --git a/xtra/examples/basic_wasm_bindgen/src/lib.rs b/xtra/examples/basic_wasm_bindgen/src/lib.rs index 735bd8f2..c90335bc 100644 --- a/xtra/examples/basic_wasm_bindgen/src/lib.rs +++ b/xtra/examples/basic_wasm_bindgen/src/lib.rs @@ -7,7 +7,6 @@ struct Echoer; struct Echo(String); -#[async_trait] impl Handler for Echoer { type Return = String; diff --git a/xtra/examples/crude_bench.rs b/xtra/examples/crude_bench.rs index 0f8352bd..7928c881 100644 --- a/xtra/examples/crude_bench.rs +++ b/xtra/examples/crude_bench.rs @@ -15,7 +15,6 @@ struct Increment; struct IncrementWithData(usize); struct GetCount; -#[async_trait] impl Handler for Counter { type Return = (); @@ -24,7 +23,6 @@ impl Handler for Counter { } } -#[async_trait] impl Handler for Counter { type Return = (); @@ -33,7 +31,6 @@ impl Handler for Counter { } } -#[async_trait] impl Handler for Counter { type Return = usize; @@ -51,7 +48,6 @@ struct SendTimer { struct GetTime; -#[async_trait] impl Handler for SendTimer { type Return = Duration; @@ -65,7 +61,6 @@ struct ReturnTimer; struct TimeReturn; -#[async_trait] impl Handler for ReturnTimer { type Return = Instant; diff --git a/xtra/examples/custom_event_loop.rs b/xtra/examples/custom_event_loop.rs index c816923b..7a58f78b 100644 --- a/xtra/examples/custom_event_loop.rs +++ b/xtra/examples/custom_event_loop.rs @@ -11,7 +11,6 @@ struct Counter { struct Inc; -#[async_trait] impl Handler for Counter { type Return = (); diff --git a/xtra/examples/interleaved_messages.rs b/xtra/examples/interleaved_messages.rs index 124cb1be..d6c760ff 100644 --- a/xtra/examples/interleaved_messages.rs +++ b/xtra/examples/interleaved_messages.rs @@ -9,7 +9,6 @@ struct ActorA { actor_b: Address, } -#[async_trait] impl Handler for ActorA { type Return = (); @@ -24,7 +23,6 @@ impl Handler for ActorA { #[derive(xtra::Actor)] struct ActorB; -#[async_trait] impl Handler for ActorB { type Return = (); @@ -37,7 +35,6 @@ impl Handler for ActorB { } } -#[async_trait] impl Handler for ActorB { type Return = (); diff --git a/xtra/examples/manual_actor_impl.rs b/xtra/examples/manual_actor_impl.rs index a00686ba..4b76934a 100644 --- a/xtra/examples/manual_actor_impl.rs +++ b/xtra/examples/manual_actor_impl.rs @@ -6,7 +6,7 @@ struct MessageCounter { } // With a manual `Actor` implementation, we can specify a `Stop` type and thus return something from the `stopped` lifecycle callback. -#[async_trait] + impl Actor for MessageCounter { type Stop = usize; @@ -18,7 +18,6 @@ impl Actor for MessageCounter { struct Ping; struct Stop; -#[async_trait] impl Handler for MessageCounter { type Return = (); @@ -27,7 +26,6 @@ impl Handler for MessageCounter { } } -#[async_trait] impl Handler for MessageCounter { type Return = (); diff --git a/xtra/examples/message_stealing_multiple_actors.rs b/xtra/examples/message_stealing_multiple_actors.rs index 3bf518fc..0ca30eb1 100644 --- a/xtra/examples/message_stealing_multiple_actors.rs +++ b/xtra/examples/message_stealing_multiple_actors.rs @@ -23,7 +23,6 @@ impl Printer { struct Print(String); -#[async_trait] impl Handler for Printer { type Return = (); diff --git a/xtra/examples/scoped_actor_task.rs b/xtra/examples/scoped_actor_task.rs index 73bba59d..69d20c4c 100644 --- a/xtra/examples/scoped_actor_task.rs +++ b/xtra/examples/scoped_actor_task.rs @@ -6,7 +6,6 @@ struct MyActor; struct Print(String); -#[async_trait] impl Handler for MyActor { type Return = (); diff --git a/xtra/examples/send_interval.rs b/xtra/examples/send_interval.rs index d4ebe033..e59208c9 100644 --- a/xtra/examples/send_interval.rs +++ b/xtra/examples/send_interval.rs @@ -11,7 +11,6 @@ struct Greeter; struct Greet; -#[async_trait] impl Handler for Greeter { type Return = (); diff --git a/xtra/src/address.rs b/xtra/src/address.rs index 63992e2e..11502caf 100644 --- a/xtra/src/address.rs +++ b/xtra/src/address.rs @@ -130,10 +130,10 @@ impl Address { /// # use xtra::prelude::*; /// # use std::time::Duration; /// # struct MyActor; - /// # #[async_trait] impl Actor for MyActor {type Stop = (); async fn stopped(self) -> Self::Stop {} } + /// # impl Actor for MyActor {type Stop = (); async fn stopped(self) -> Self::Stop {} } /// struct Shutdown; /// - /// #[async_trait] + /// /// impl Handler for MyActor { /// type Return = (); /// diff --git a/xtra/src/chan/ptr.rs b/xtra/src/chan/ptr.rs index fc63c248..9d4dd674 100644 --- a/xtra/src/chan/ptr.rs +++ b/xtra/src/chan/ptr.rs @@ -380,7 +380,6 @@ mod tests { struct Foo; - #[async_trait::async_trait] impl crate::Actor for Foo { type Stop = (); diff --git a/xtra/src/dispatch_future.rs b/xtra/src/dispatch_future.rs index 57e6b802..9bfdefed 100644 --- a/xtra/src/dispatch_future.rs +++ b/xtra/src/dispatch_future.rs @@ -43,13 +43,14 @@ impl<'a, A> DispatchFuture<'a, A> { /// In case this future has not yet been polled, a new span will be created which is why this function takes `&mut self`. /// /// ```rust + /// # use std::ops::ControlFlow; /// # use std::time::Duration; /// # use tokio::time::timeout; /// # use xtra::prelude::*; /// # /// # struct MyActor; - /// # #[async_trait::async_trait] impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } + /// # impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } /// # /// # let mut actor = MyActor; /// # let (addr, mut mailbox) = Mailbox::unbounded(); diff --git a/xtra/src/lib.rs b/xtra/src/lib.rs index d2a6ced7..2c912f0f 100644 --- a/xtra/src/lib.rs +++ b/xtra/src/lib.rs @@ -15,6 +15,7 @@ pub use self::context::Context; pub use self::mailbox::Mailbox; pub use self::scoped_task::scoped; pub use self::send_future::{ActorErasedSending, ActorNamedSending, Receiver, SendFuture}; +#[allow(unused_imports)] pub use self::spawn::*; // Star export so we don't have to write `cfg` attributes here. pub mod address; @@ -34,8 +35,6 @@ mod spawn; /// Commonly used types from xtra pub mod prelude { - pub use async_trait::async_trait; - pub use crate::address::Address; pub use crate::context::Context; pub use crate::message_channel::MessageChannel; @@ -69,7 +68,7 @@ pub mod refcount { /// # use xtra::prelude::*; /// pub struct MyActor; /// -/// #[async_trait] +/// /// impl xtra::Actor for MyActor { /// type Stop = (); /// @@ -86,18 +85,15 @@ use crate::recv_future::Message; /// Defines that an [`Actor`] can handle a given message `M`. /// -/// This is an [`async_trait`](https://docs.rs/async-trait), so implementations should -/// be annotated `#[async_trait]`. -/// /// # Example /// /// ```rust /// # use xtra::prelude::*; /// # struct MyActor; -/// # #[async_trait] impl Actor for MyActor {type Stop = (); async fn stopped(self) -> Self::Stop {} } +/// # impl Actor for MyActor {type Stop = (); async fn stopped(self) -> Self::Stop {} } /// struct Msg; /// -/// #[async_trait] +/// /// impl Handler for MyActor { /// type Return = u32; /// @@ -114,16 +110,16 @@ use crate::recv_future::Message; /// }) /// } /// ``` -#[async_trait::async_trait] pub trait Handler: Actor { /// The return value of this handler. type Return: Send + 'static; /// Handle a given message, returning its result. - /// - /// This is an [`async_trait`](https://docs.rs/async-trait). - /// See the trait documentation to see an example of how this method can be declared. - async fn handle(&mut self, message: M, ctx: &mut Context) -> Self::Return; + fn handle( + &mut self, + message: M, + ctx: &mut Context, + ) -> impl Future + Send; } /// An actor which can handle message one at a time. Actors can only be @@ -132,8 +128,6 @@ pub trait Handler: Actor { /// stop themselves through their [`Context`] by calling [`Context::stop_self`]. /// This will result in any attempt to send messages to the actor in future failing. /// -/// This is an [`async_trait`], so implementations should be annotated `#[async_trait]`. -/// /// # Example /// /// ```rust @@ -141,7 +135,7 @@ pub trait Handler: Actor { /// # use std::time::Duration; /// struct MyActor; /// -/// #[async_trait] +/// /// impl Actor for MyActor { /// type Stop = (); /// async fn started(&mut self, ctx: &Mailbox) -> Result<(), Self::Stop> { @@ -157,7 +151,7 @@ pub trait Handler: Actor { /// /// struct Goodbye; /// -/// #[async_trait] +/// /// impl Handler for MyActor { /// type Return = (); /// @@ -178,15 +172,17 @@ pub trait Handler: Actor { /// ``` /// /// For longer examples, see the `examples` directory. -#[async_trait::async_trait] pub trait Actor: 'static + Send + Sized { /// Value returned from the actor when [`Actor::stopped`] is called. type Stop: Send + 'static; /// Called as soon as the actor has been started. #[allow(unused_variables)] - async fn started(&mut self, mailbox: &Mailbox) -> Result<(), Self::Stop> { - Ok(()) + fn started( + &mut self, + mailbox: &Mailbox, + ) -> impl Future> + Send { + async { Ok(()) } } /// Called at the end of an actor's event loop. @@ -196,7 +192,7 @@ pub trait Actor: 'static + Send + Sized { /// - The actor called [`Context::stop_self`]. /// - An actor called [`Context::stop_all`]. /// - The last [`Address`] with a [`Strong`](crate::refcount::Strong) reference count was dropped. - async fn stopped(self) -> Self::Stop; + fn stopped(self) -> impl Future + Send; } /// An error related to the actor system @@ -262,12 +258,11 @@ where /// # use xtra::prelude::*; /// # use smol::future; /// # struct MyActor; -/// # #[async_trait] impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } +/// # impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } /// /// struct Stop; /// struct Selecting; /// -/// #[async_trait] /// impl Handler for MyActor { /// type Return = (); /// @@ -276,7 +271,6 @@ where /// } /// } /// -/// #[async_trait] /// impl Handler for MyActor { /// type Return = bool; /// @@ -348,12 +342,11 @@ where /// # use xtra::prelude::*; /// # use smol::future; /// # struct MyActor; -/// # #[async_trait] impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } +/// # impl Actor for MyActor { type Stop = (); async fn stopped(self) {} } /// /// struct Stop; /// struct Joining; /// -/// #[async_trait] /// impl Handler for MyActor { /// type Return = (); /// @@ -362,7 +355,6 @@ where /// } /// } /// -/// #[async_trait] /// impl Handler for MyActor { /// type Return = bool; /// diff --git a/xtra/src/message_channel.rs b/xtra/src/message_channel.rs index fbb2840f..7549561c 100644 --- a/xtra/src/message_channel.rs +++ b/xtra/src/message_channel.rs @@ -23,16 +23,14 @@ use crate::Handler; /// struct Alice; /// struct Bob; /// -/// #[async_trait] /// impl Actor for Alice { /// type Stop = (); /// async fn stopped(self) { /// println!("Oh no"); /// } /// } -/// # #[async_trait] impl Actor for Bob {type Stop = (); async fn stopped(self) -> Self::Stop {} } +/// # impl Actor for Bob {type Stop = (); async fn stopped(self) -> Self::Stop {} } /// -/// #[async_trait] /// impl Handler for Alice { /// type Return = &'static str; /// @@ -41,7 +39,6 @@ use crate::Handler; /// } /// } /// -/// #[async_trait] /// impl Handler for Bob { /// type Return = &'static str; /// diff --git a/xtra/tests/basic.rs b/xtra/tests/basic.rs index 312912a0..a2e56201 100644 --- a/xtra/tests/basic.rs +++ b/xtra/tests/basic.rs @@ -13,7 +13,6 @@ use xtra::Error; #[derive(Clone, Debug, Eq, PartialEq)] struct Accumulator(usize); -#[async_trait] impl Actor for Accumulator { type Stop = usize; @@ -26,7 +25,6 @@ struct Inc; struct Report; -#[async_trait] impl Handler for Accumulator { type Return = (); @@ -35,7 +33,6 @@ impl Handler for Accumulator { } } -#[async_trait] impl Handler for Accumulator { type Return = Self; @@ -44,7 +41,6 @@ impl Handler for Accumulator { } } -#[async_trait] impl Handler for Accumulator { type Return = (); @@ -53,7 +49,6 @@ impl Handler for Accumulator { } } -#[async_trait] impl Handler for Accumulator { type Return = (); @@ -85,7 +80,6 @@ struct StopAll; struct StopSelf; -#[async_trait] impl Handler for StopTester { type Return = (); @@ -94,7 +88,6 @@ impl Handler for StopTester { } } -#[async_trait] impl Handler for StopTester { type Return = (); @@ -272,7 +265,6 @@ async fn two_actors_on_address_with_stop_self_context_alive() { #[derive(xtra::Actor)] struct ActorStopSelf; -#[async_trait] impl Handler for ActorStopSelf { type Return = (); @@ -284,7 +276,6 @@ impl Handler for ActorStopSelf { #[derive(xtra::Actor)] struct LongRunningHandler; -#[async_trait] impl Handler for LongRunningHandler { type Return = (); @@ -362,7 +353,6 @@ impl Default for Elephant { } } -#[async_trait] impl Actor for Elephant { type Stop = Vec; @@ -371,7 +361,6 @@ impl Actor for Elephant { } } -#[async_trait] impl Handler for Elephant { type Return = (); @@ -691,7 +680,6 @@ struct Greeter; struct Hello(&'static str); -#[async_trait] impl Handler for Greeter { type Return = String; @@ -703,7 +691,6 @@ impl Handler for Greeter { #[derive(Clone)] struct PrintHello(&'static str); -#[async_trait] impl Handler for Greeter { type Return = (); @@ -899,7 +886,6 @@ fn test_addr_cmp_hash_eq() { struct Pending; -#[async_trait] impl Handler for Greeter { type Return = (); diff --git a/xtra/tests/instrumentation.rs b/xtra/tests/instrumentation.rs index 7de85921..fe2e4d8d 100644 --- a/xtra/tests/instrumentation.rs +++ b/xtra/tests/instrumentation.rs @@ -69,7 +69,6 @@ struct Tracer; struct Hello(&'static str); -#[async_trait] impl Handler for Tracer { type Return = (); @@ -80,7 +79,6 @@ impl Handler for Tracer { struct CreateInfoSpan; -#[async_trait] impl Handler for Tracer { type Return = ();