#[protocol]Expand description
Generates message types and blanket implementations from a protocol trait.
#[protocol] transforms a trait definition into a full message-passing interface.
Each trait method becomes a message struct, and any ActorRef<A> where A handles
those messages automatically implements the trait — so you call methods directly on
the actor reference.
§What It Generates
For a trait FooProtocol, the macro generates:
- Message structs in a
foo_protocolsubmodule — one per method, with public fields matching the method parameters. Each implementsMessage. Unit structs (methods with no parameters beyond&self) automatically deriveClone. - Type alias
pub type FooRef = Arc<dyn FooProtocol>— a type-erased reference. - Converter trait
ToFooRefwith ato_foo_ref(&self) -> FooRefmethod. - Blanket impls —
impl FooProtocol for ActorRef<A>andimpl ToFooRef for ActorRef<A>for any actorAthat handles all the generated message types.
§Type Resolution in Generated Structs
The generated message module uses use super::* to access types from the
parent scope. Types used in method parameters are qualified with super::
in the generated structs — this means any type you reference in a protocol
method signature must be in scope where the #[protocol] trait is defined.
Prelude types (String, Vec, Option, Result, Box, bool, u32, etc.)
and fully qualified paths (std::, core::, alloc::) are used as-is without
super:: prefixing.
§Return Type Conventions
The return type on each method determines the message kind:
| Return type | Kind | Runtime | Caller behavior |
|---|---|---|---|
Response<T> | Request | Both | .await.unwrap() (tasks) / .unwrap() (threads) — 5s default timeout |
Result<(), ActorError> | Send | Both | Returns send result |
(none) / -> () | Send | Both | Fire-and-forget (discards send result) |
§Naming
- Module: trait name →
snake_case(e.g.,ChatRoomProtocol→chat_room_protocol) - Structs: method name →
PascalCase(e.g.,send_message→SendMessage) - XRef alias: strips
Protocolsuffix →{Base}Ref(e.g.,ChatRoomProtocol→ChatRoomRef) - Converter:
To{Base}Refwithto_{snake_base}_ref()method
§Example
use spawned_concurrency::Response;
use spawned_concurrency::protocol;
#[protocol]
pub trait CounterProtocol: Send + Sync {
fn increment(&self, amount: u64); // send (fire-and-forget)
fn get_count(&self) -> Response<u64>; // request (both modes)
}
// Generated:
// - pub mod counter_protocol { pub struct Increment { pub amount: u64 }, pub struct GetCount }
// - pub type CounterRef = Arc<dyn CounterProtocol>;
// - pub trait ToCounterRef { fn to_counter_ref(&self) -> CounterRef; }
// - impl CounterProtocol for ActorRef<A> where A: Handler<Increment> + Handler<GetCount>