#[export]#
The #[hyperactor::export] macro turns a regular Actor implementation into a remotely addressable actor by generating its type information and supported message handlers.
It also supports message casting (broadcasting to multiple actors) by specifying cast = true for individual handlers.
What It Adds#
When applied to an actor type like this:
#[hyperactor::spawnable]
#[hyperactor::export(ShoppingList)]
struct ShoppingListActor(HashSet<String>);
The macro expands to include:
A
Namedimplementation for the actorA
Binds<Self>implementation that registers supported message typesImplementations of
RemoteHandles<T>for each type in thehandlers = [...]listA
Referablemarker implementation
This enables the actor to be:
Routed to via typed messages
Reflected on at runtime (for diagnostics, tools, and orchestration)
To make a concrete actor remotely spawnable, add #[hyperactor::spawnable]. For generic instantiations, use hyperactor::register_spawnable!(MyActor<u64>);.
Casting Messages#
For message types that need to be broadcast to multiple actors in a mesh, use cast = true:
#[hyperactor::export(
handlers = [
TestMessage { cast = true },
() { cast = true },
MyGeneric<()> { cast = true },
u64,
],
)]
struct TestActor {
forward_port: PortRef<String>,
}
When cast = true is specified, the macro registers both the concrete message type and its IndexedErasedUnbound<T> wrapper. This enables the message to be multicast to a group of actors via CastMessageEnvelope, with proper handling of reply port mutation so replies can be relayed through intermediate nodes and aggregated.
Generated Implementations (simplified)#
impl Referable for ShoppingListActor {}
impl RemoteHandles<ShoppingList> for ShoppingListActor {}
impl RemoteHandles<Signal> for ShoppingListActor {}
impl Binds<ShoppingListActor> for ShoppingListActor {
fn bind(ports: &HandlerPorts<Self>) {
ports.bind::<ShoppingList>();
}
}
impl Named for ShoppingListActor {
fn typename() -> &'static str {
"my_crate::ShoppingListActor"
}
}
Note: The
Referabletrait itself only requiresNamed. It does not automatically provideSendorSyncbounds. If your actor needs to be passed across threads or stored in shared contexts, those bounds will be enforced at the specific call sites that require them.
If the actor is marked #[hyperactor::spawnable], that attribute emits:
impl RemoteSpawn for ShoppingListActor {}
This enables remote spawning via the default gspawn provided by a blanket implementation.
It also registers the actor into inventory:
inventory::submit!(SpawnableActor {
name: ...,
gspawn: ...,
get_type_id: ...,
});
This allows the actor to be discovered and spawned by name at runtime.
Summary#
The #[export] macro makes an actor remotely visible and routable by declaring:
What messages it handles
How to bind those messages
What its globally unique name is
(Optionally) which messages support multicast (broadcasting)