Skip to main content

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;