Skip to main content

behavior

Attribute Macro behavior 

Source
#[behavior]
Expand description

Generate the nominal protocol, closed effect products, and exact Behavior wiring for an inherent impl. addr and message are required. Omitting sends, births, or error selects the capability-free NoSends, NoBirths, or Never type respectively.

A sends = { lane: Product } declaration generates ActorSends, one distinct ActorSendsLane selector per field, and structural SendEffects, SendsFor, and InterpretSends implementations. A births = { lane: Child } declaration generates ActorChildren as the exact recursive ChildChoice produced by Children calls in declaration order. The lane labels document each child role; creation remains an authored Children value and is never performed by the macro.

Invalid receivers are rejected at compile time.

ⓘ
use behavior::{Actions, BehaviorActed, MailAddr};

struct Invalid;
#[behavior::behavior(
    addr = MailAddr,
    message = u8,
)]
impl Invalid {
    fn init(&self) -> BehaviorActed<Self> {
        Ok(Actions::cont())
    }
    fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
        Ok(Actions::cont())
    }
}

Missing receive methods are rejected by the macro itself:

ⓘ
use behavior::MailAddr;
struct Missing;
#[behavior::behavior(
    addr = MailAddr,
    message = u8,
)]
impl Missing {
}

Async behavior methods cannot introduce an erased or alternate execution path:

ⓘ
use behavior::{Actions, BehaviorActed, MailAddr};
struct Async;
#[behavior::behavior(
    addr = MailAddr,
    message = u8,
)]
impl Async {
    async fn init(&mut self) -> BehaviorActed<Self> {
        Ok(Actions::cont())
    }
    fn receive(&mut self, _: MailAddr, _: u8) -> BehaviorActed<Self> {
        Ok(Actions::cont())
    }
}

Undeclared send lanes have no selector and cannot be emitted:

ⓘ
use behavior::{Actions, BehaviorActed, MailAddr, SendEffects};
struct Sender;
#[behavior::behavior(addr = MailAddr, message = (), sends = { replies: Vec<u8> })]
impl Sender {
    fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
        let mut sends = SenderSends::empty();
        sends.send::<_, SenderSendsUndeclared>(1);
        Ok(Actions::send(sends))
    }
}

A child absent from the declared closed birth product cannot be created:

ⓘ
use behavior::{Actions, BehaviorActed, Create, MailAddr};
struct Declared;
struct Other;
struct Root;
#[behavior::behavior(addr = MailAddr, message = (), births = { declared: Declared })]
impl Root {
    fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
        Ok(Actions::create(vec![Create::birth(1, Other)]))
    }
}

Every generated send lane remains a separate interpreter obligation:

ⓘ
use behavior::{BehaviorActed, Delivery, InterpretDelivery, InterpretSends, MailAddr,
    MessageProtocol, Recipient, SendInterpreter};
struct Root;
type First = MessageProtocol<MailAddr, u8>;
type Second = MessageProtocol<MailAddr, u16>;
#[behavior::behavior(addr = MailAddr, message = (), sends = {
    first: Vec<Delivery<First>>,
    second: Vec<Delivery<Second>>,
})]
impl Root {
    fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
        Ok(behavior::Actions::cont())
    }
}
struct Incomplete;
impl SendInterpreter for Incomplete { type Error = (); }
impl InterpretDelivery<First> for Incomplete {
    fn interpret_delivery(&mut self, _: Delivery<First>) -> impl core::future::Future<Output = Result<(), ()>> + Send {
        async { Ok(()) }
    }
}
fn require_complete()
where
    RootSends: InterpretSends<Incomplete, behavior::User<MailAddr, ()>, behavior::Here>,
{}

Generated child products likewise require an installer for every declared alternative:

ⓘ
use behavior::{BehaviorActed, Create, DispatchBirth, InstallBirth, MailAddr, Never};
struct First;
struct Second;
#[behavior::behavior(addr = MailAddr, message = Never)]
impl First {
    fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> { match message {} }
}
#[behavior::behavior(addr = MailAddr, message = Never)]
impl Second {
    fn receive(&mut self, _: MailAddr, message: Never) -> BehaviorActed<Self> { match message {} }
}
struct Root;
#[behavior::behavior(addr = MailAddr, message = (), births = {
    first: First,
    second: Second,
})]
impl Root {
    fn receive(&mut self, _: MailAddr, _: ()) -> BehaviorActed<Self> {
        Ok(behavior::Actions::cont())
    }
}
struct Incomplete;
impl InstallBirth<MailAddr, First, (), Never> for Incomplete {
    async fn install_birth(&mut self, _: Create<MailAddr, First>) -> Result<(), Never> { Ok(()) }
}
fn require_complete<T: DispatchBirth<MailAddr, Incomplete, (), Never>>() {}
require_complete::<RootChildren>();

Generate the mechanical Behavior implementation for a normal inherent impl containing receive(&mut self, from, message) and, optionally, init(&mut self). Omitting init selects the behavior algebra’s empty initialization transition. The original impl and methods are preserved unchanged.