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