behavior/lib.rs
1//! Pure, typed actor-behavior primitives.
2//!
3//! [`Protocol`] is stable public destination identity (`Addr` plus `Msg`). A
4//! [`Behavior`] separately owns state and folds its complete [`Behavior::Event`]
5//! algebra into exactly [`Actions`]: sends, fresh creations, and its next
6//! behavior or termination. A protocol is not a behavior, and `Behavior` is not
7//! a `Protocol` supertrait. Higher capabilities extend internal event and
8//! effect algebras while transparent wrappers preserve [`Behavior::Protocol`].
9//!
10//! Finite mailbox execution belongs to a runtime or test driver, not to this
11//! one-turn behavior algebra.
12//!
13//! ```compile_fail,E0405
14//! fn requires_reducer<T: behavior::ActionReducer>() {}
15//! ```
16//!
17//! Capability-restricted action products use the existing `Actions` algebra;
18//! there is no second convenience wrapper with an overlapping contract.
19//!
20//! ```compile_fail
21//! fn accepts_duplicate(_: behavior::Effect<u8>) {}
22//! ```
23
24// The `#[behavior]` expansion emits `::behavior::…` paths; this alias lets the
25// expansion resolve inside this crate too.
26extern crate self as behavior;
27
28mod actor;
29mod effects;
30mod next;
31mod transition;
32mod user_event;
33
34pub use actor::{
35 Address, AllocationRejection, BirthMode, BirthNodeAppend, BirthNodeAt, BirthNodeLogicalHosts,
36 BirthNodeProtocols, BirthProtocol, BirthProtocolAt, BirthProtocolHead, BirthProtocolProduct,
37 BirthProtocolTail, BirthProtocols, Births, ChildChoice, ChildCons, ChildCreationOutcome,
38 ChildCreationProduct, ChildCreationSettled, ChildDelivery, ChildDeliveryReason, ChildHead,
39 ChildInput, ChildInputReason, ChildNamespaceExhausted, ChildOccurrence, ChildOccurrenceProduct,
40 ChildOccurrenceProductAt, ChildOccurrenceResolution, ChildOccurrenceShape, ChildOccurrences,
41 ChildPosition, ChildProduct, ChildReport, ChildRole, ChildTail, Children, CommittedChild,
42 CreateChild, CreationCorrelation, CreationId, CreationKind, CreationRejection,
43 CreationSequence, Creations, DeclaredChildOccurrence, Delivery, DispatchBirth, EndpointAddress,
44 EstablishChild, EstablishedActor, EstablishedCreation, EstablishedDelivery,
45 EstablishedRecipient, ExactDeliveryReason, InterpretEstablished, InterpretInstalledActor,
46 LogicalDeliveryReason, MailAddr, NoBirthProtocols, NoBirths, NoChildren, Recipient,
47 RecipientAddress, ResolveChildOccurrence, ResolvedChild, ResolvedChildPosition,
48 RetirementBirths, RoleChild, RoleProtocol, RoutedCreation, StructuralChildOccurrence,
49};
50pub use effects::{
51 Acted, ActionItem, ActionItemResult, ActionSettlement, ActionSettlements, Actions, AppendSend,
52 Become, BehaviorSettlements, ClassifySettlement, CreationEvent, CreationSettlement,
53 CreationSettlements, CreationsSettled, InterpretCreations, InterpretItem, InterpretSends,
54 Interpretation, InterpreterFault, InterpreterRequest, InterpreterRequests, ItemSettlement,
55 LogicalDeliveryProtocols, NoReturnToEmitter, NoSends, Own, ParentReportReason, ReportToParent,
56 RetirementCreationSettlement, ReturnsToEmitter, SendEffects, SendInput, SendLayer,
57 SendSettlements, SendsFor, SettledItem, SettlementStatus, SourceAction, SourceActions,
58 SourceAdmission, SourceCustody, SourceSettlementCustody, SourceSettlements, settle_item,
59};
60pub use next::{Never, Step, Stopped};
61pub use transition::{
62 ActiveTurn, Behavior, BehaviorActed, BehaviorAddr, BehaviorBase, BehaviorLayer,
63 BehaviorMessage, InitializationTurn, LogicalHostRequirements, MessageProtocol, Protocol,
64 delegate_transition, initialize,
65};
66pub use user_event::{
67 ChildInputIngress, ComposedEvent, EventIngress, EventLayer, Here, Ingress, InjectEvent, Inside,
68 RecoverEvent, User, UserEvent,
69};
70
71/// Generate the nominal protocol, closed effect products, and exact `Behavior`
72/// wiring for an inherent impl. `addr` and `message` are required. Omitting
73/// `sends`, `births`, or `error` selects the capability-free `NoSends`,
74/// `NoBirths`, or `Never` type respectively.
75///
76/// A `sends = { lane: Product }` declaration generates a module-private
77/// `ActorSends`; `sends = pub { lane: Product }` exports it for a public actor.
78/// Its lane selectors, settlement product, and fluent trait have the same
79/// visibility. Each field contributes its logical-host protocols in declared
80/// order, including duplicates, through [`LogicalDeliveryProtocols`]. The
81/// product also derives structural `SendEffects`, `SendsFor`,
82/// [`SendSettlements`], and `InterpretSends` implementations. The settlement
83/// product keeps the same semantic field names and one runtime-independent
84/// type. The macro also generates an
85/// `ActorActions` extension trait with one fluent `send_lane` method per named
86/// lane. Each method delegates to [`AppendSend`], changing only the send leg
87/// while preserving creations and the exact next-behavior verdict. A
88/// `births = { lane: Child }` declaration generates `ActorChildren` as the
89/// exact closed child algebra. One child remains its direct concrete type;
90/// multiple alternatives form `ChildChoice` in declaration order. The macro
91/// also generates one nominal role per declaration and an `ActorChild`
92/// namespace for those roles. Every role implements both [`ChildRole`] for its
93/// authored parent and [`ChildOccurrence`] for sealed resolution against that
94/// parent or a topology-transparent wrapper. Creation remains an authored
95/// [`Creations`] or [`Children`] value and is never performed by the macro.
96///
97/// Invalid receivers are rejected at compile time.
98/// A birth-owning generated actor must also select the exact creation-settlement
99/// disposition; there is no implicit discard or generated no-op receiver.
100///
101/// ```compile_fail
102/// struct Child;
103/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
104/// impl Child {
105/// fn receive(
106/// &mut self,
107/// _: behavior::MailAddr,
108/// message: behavior::Never,
109/// ) -> behavior::BehaviorActed<Self> {
110/// match message {}
111/// }
112/// }
113/// struct MissingCreationSettlementDisposition;
114/// #[behavior::behavior(
115/// addr = behavior::MailAddr,
116/// message = behavior::Never,
117/// births = { child: Child },
118/// )]
119/// impl MissingCreationSettlementDisposition {
120/// fn receive(
121/// &mut self,
122/// _: behavior::MailAddr,
123/// message: behavior::Never,
124/// ) -> behavior::BehaviorActed<Self> {
125/// match message {}
126/// }
127/// }
128/// ```
129///
130/// ```compile_fail
131///
132/// struct Invalid;
133/// #[behavior::behavior(
134/// addr = behavior::MailAddr,
135/// message = u8,
136/// )]
137/// impl Invalid {
138/// fn init(&self) -> behavior::BehaviorActed<Self> {
139/// Ok(behavior::Actions::cont())
140/// }
141/// fn receive(&mut self, _: behavior::MailAddr, _: u8) -> behavior::BehaviorActed<Self> {
142/// Ok(behavior::Actions::cont())
143/// }
144/// }
145/// ```
146///
147/// Missing receive methods are rejected by the macro itself:
148///
149/// ```compile_fail
150/// struct Missing;
151/// #[behavior::behavior(
152/// addr = behavior::MailAddr,
153/// message = u8,
154/// )]
155/// impl Missing {
156/// }
157/// ```
158///
159/// Async behavior methods cannot introduce an erased or alternate execution
160/// path:
161///
162/// ```compile_fail
163/// struct Async;
164/// #[behavior::behavior(
165/// addr = behavior::MailAddr,
166/// message = u8,
167/// )]
168/// impl Async {
169/// async fn init(&mut self) -> behavior::BehaviorActed<Self> {
170/// Ok(behavior::Actions::cont())
171/// }
172/// fn receive(&mut self, _: behavior::MailAddr, _: u8) -> behavior::BehaviorActed<Self> {
173/// Ok(behavior::Actions::cont())
174/// }
175/// }
176/// ```
177///
178/// Undeclared send lanes have no selector and cannot be emitted:
179///
180/// ```compile_fail
181/// struct Sender;
182/// #[behavior::behavior(addr = behavior::MailAddr, message = (), sends = { replies: Vec<u8> })]
183/// impl Sender {
184/// fn receive(&mut self, _: behavior::MailAddr, _: ()) -> behavior::BehaviorActed<Self> {
185/// let mut sends: SenderSends = behavior::SendEffects::empty();
186/// behavior::SendEffects::send::<_, SenderSendsUndeclared>(&mut sends, 1);
187/// Ok(behavior::Actions::send(sends))
188/// }
189/// }
190/// ```
191///
192/// Generated lane methods accept only inputs supported by that lane:
193///
194/// ```compile_fail
195/// struct Sender;
196/// #[behavior::behavior(addr = behavior::MailAddr, message = (), sends = { replies: Vec<u8> })]
197/// impl Sender {
198/// fn receive(&mut self, _: behavior::MailAddr, _: ()) -> behavior::BehaviorActed<Self> {
199/// Ok(behavior::Actions::cont().send_replies("not a u8"))
200/// }
201/// }
202/// ```
203///
204/// A child absent from the declared closed birth product cannot be created:
205///
206/// ```compile_fail
207/// struct Declared;
208/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
209/// impl Declared {
210/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
211/// match message {}
212/// }
213/// }
214/// struct Other;
215/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
216/// impl Other {
217/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
218/// match message {}
219/// }
220/// }
221/// struct Root { creations: behavior::CreationSequence }
222/// #[behavior::behavior(
223/// addr = behavior::MailAddr,
224/// message = (),
225/// births = { declared: Declared },
226/// creation_settlements = retain_for_retirement,
227/// )]
228/// impl Root {
229/// fn receive(&mut self, _: behavior::MailAddr, _: ()) -> behavior::BehaviorActed<Self> {
230/// let id = self.creations.issue().expect("fixture creation ID");
231/// Ok(behavior::Actions::create(behavior::Creations::one(behavior::CreateChild::birth(id, Other))))
232/// }
233/// }
234/// ```
235///
236/// Every generated send lane remains a separate interpreter obligation:
237///
238/// ```compile_fail
239/// struct Root;
240/// type AuditProtocol = behavior::MessageProtocol<behavior::MailAddr, u8>;
241/// type MetricsProtocol = behavior::MessageProtocol<behavior::MailAddr, u16>;
242/// #[behavior::behavior(addr = behavior::MailAddr, message = (), sends = {
243/// audit: Vec<behavior::Delivery<AuditProtocol>>,
244/// metrics: Vec<behavior::Delivery<MetricsProtocol>>,
245/// })]
246/// impl Root {
247/// fn receive(&mut self, _: behavior::MailAddr, _: ()) -> behavior::BehaviorActed<Self> {
248/// Ok(behavior::Actions::cont())
249/// }
250/// }
251/// struct Incomplete;
252/// impl<RootEvent, Path> behavior::InterpretItem<behavior::Delivery<AuditProtocol>, RootEvent, Path> for Incomplete {
253/// fn interpret_item(&mut self, _: behavior::Delivery<AuditProtocol>) -> impl core::future::Future<
254/// Output = behavior::ItemSettlement<behavior::Delivery<AuditProtocol>, (), behavior::Never, behavior::Never>,
255/// > + Send {
256/// async { behavior::ItemSettlement::Accepted(()) }
257/// }
258/// }
259/// fn require_complete()
260/// where
261/// RootSends: behavior::InterpretSends<Incomplete, behavior::User<behavior::MailAddr, ()>, behavior::Here>,
262/// {}
263/// ```
264///
265/// Generated child products likewise require one [`EstablishChild`]
266/// implementation for every declared alternative. [`DispatchBirth`] owns the
267/// compile-denial example so this crate overview does not duplicate it.
268///
269/// Two declared roles remain distinct even when they use the same behavior:
270///
271/// ```compile_fail
272/// struct Worker;
273/// #[behavior::behavior(addr = behavior::MailAddr, message = ())]
274/// impl Worker {
275/// fn receive(&mut self, _: behavior::MailAddr, _: ()) -> behavior::BehaviorActed<Self> {
276/// Ok(behavior::Actions::cont())
277/// }
278/// }
279/// struct Root;
280/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never, births = {
281/// primary: Worker,
282/// backup: Worker,
283/// }, creation_settlements = retain_for_retirement)]
284/// impl Root {
285/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
286/// match message {}
287/// }
288/// }
289/// fn requires_primary(
290/// _: behavior::ChildDelivery<<Worker as behavior::Behavior>::Protocol, RootChildrenPrimary>,
291/// ) {}
292/// let mut sequence = behavior::CreationSequence::new();
293/// let id = sequence.issue().expect("fixture creation ID");
294/// let backup = behavior::ChildDelivery::<<Worker as behavior::Behavior>::Protocol, RootChildrenBackup>::after(id, ());
295/// requires_primary(backup);
296/// ```
297///
298/// Named topology selectors accept only the child declared for that parent
299/// role, which lets an application builder remain entirely static:
300///
301/// ```compile_fail
302/// struct Worker;
303/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
304/// impl Worker {
305/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
306/// match message {}
307/// }
308/// }
309/// struct Query;
310/// #[behavior::behavior(addr = behavior::MailAddr, message = behavior::Never)]
311/// impl Query {
312/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
313/// match message {}
314/// }
315/// }
316/// struct Root;
317/// #[behavior::behavior(
318/// addr = behavior::MailAddr,
319/// message = behavior::Never,
320/// births = { workers: Worker },
321/// creation_settlements = retain_for_retirement,
322/// )]
323/// impl Root {
324/// fn receive(&mut self, _: behavior::MailAddr, message: behavior::Never) -> behavior::BehaviorActed<Self> {
325/// match message {}
326/// }
327/// }
328/// fn child<Parent, Role>(_: Role, _: Role::Child)
329/// where
330/// Parent: behavior::Behavior,
331/// Role: behavior::ChildRole<Parent>,
332/// {}
333/// child::<Root, _>(RootChild::Workers, Query);
334/// ```
335pub use behavior_macros::behavior;