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