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