#[doc(hidden)]
#[macro_export]
macro_rules! __StateUnion {
(
@trait $marker:ident [$first_super:ident $(, $supertrait:ident)*] $enum:tt:
$first:ident $(| $state:ident)*
) => {
$crate::__private::paste! {
#[doc = concat!(
"State-union marker for `",
stringify!($marker),
"`.\n\n",
"Use this marker as the type-level name of the union. ",
"The generated `In",
stringify!($marker),
"` trait restricts APIs to members of the union, and the generated enum ",
"named by `StateUnionDiscriminant::Enum` carries concrete state values.\n\n",
"`",
stringify!($marker),
"` is not a concrete runtime state. It is a ZST used to name ",
"the set of states in generic signatures, for example ",
"`State<S, Connection, impl In",
stringify!($marker),
">`. When a value must remember which concrete member it ",
"currently contains, use `DiscriminatedState<S, T, ",
stringify!($marker),
">` or the generated enum instead."
)]
#[allow(dead_code)]
pub struct $marker;
impl $crate::StateMarker for $marker {
type Kind = $crate::UnionStateKind;
fn erased_state() -> &'static dyn $crate::StateTrait {
panic!("union state markers cannot be stored as ErasedState")
}
}
#[doc(hidden)]
#[allow(dead_code)]
mod [<__state_union_seal_ $marker:snake>] {
#[allow(dead_code)]
pub trait Sealed {}
}
impl [<__state_union_seal_ $first_super:snake>]::Sealed
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionProofMembership<$first_super>
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionErased<$first_super>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(
@erased_union_variant_impl $marker => $first_super:
$first $(| $state)*
);
}
impl [<In $first_super>]
for $crate::StateUnionState<$marker>
{}
impl $crate::In<$first_super>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(
@into_discriminated_union_variant_impl $marker => $first_super:
$first $(| $state)*
);
}
impl $crate::StateUnionMember<
$crate::StateUnionState<$marker>
> for $first_super {}
$(
impl [<__state_union_seal_ $supertrait:snake>]::Sealed
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionProofMembership<$supertrait>
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionErased<$supertrait>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(@erased_identity_impl $supertrait);
}
impl [<In $supertrait>]
for $crate::StateUnionState<$marker>
{}
impl $crate::In<$supertrait>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(@into_discriminated_identity_impl $supertrait);
}
impl $crate::StateUnionMember<
$crate::StateUnionState<$marker>
> for $supertrait {}
)*
#[doc = concat!(
"Sealed membership trait for states in the `",
stringify!($marker),
"` state union.\n\n",
"This trait is generated by `StateUnion!` and is implemented only for ",
"the concrete states listed in that macro invocation. Use `impl In",
stringify!($marker),
"` in method receivers and generic bounds when an API accepts any ",
"state in the union.\n\n",
"Because the trait is sealed, downstream crates cannot widen the union ",
"by implementing it for additional states. That keeps a method such as ",
"`fn endpoint(self: &State<impl SRef, Self, impl In",
stringify!($marker),
">)` tied to the definition crate's contract. For generic helper APIs ",
"that receive the marker as a type parameter, use `In<",
stringify!($marker),
">` instead; this generated trait is the ergonomic spelling for normal ",
"method signatures."
)]
#[allow(dead_code)]
pub trait [<In $marker>]:
$crate::StateTrait
+ $crate::StateMarker
+ [<__state_union_seal_ $marker:snake>]::Sealed
+ $crate::In<$marker>
+ $crate::StateUnionErased<$marker>
+ $crate::StateUnionProofMembership<$marker>
+ [<In $first_super>]
$(+ [<In $supertrait>])*
{
}
impl [<__state_union_seal_ $marker:snake>]::Sealed
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionProofMembership<$marker>
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionErased<$marker>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(@erased_identity_impl $marker);
}
impl [<In $marker>] for $crate::StateUnionState<$marker> {}
impl $crate::In<$marker> for $crate::StateUnionState<$marker> {
$crate::__StateUnion!(@into_discriminated_identity_impl $marker);
}
impl [<__state_union_seal_ $marker:snake>]::Sealed for $first {}
impl $crate::StateUnionProofMembership<$marker> for $first {}
impl $crate::StateUnionErased<$marker> for $first {
$crate::__StateUnion!(@erased_variant_impl $marker $first);
}
impl [<In $marker>] for $first {}
impl $crate::In<$marker> for $first {
$crate::__StateUnion!(@into_discriminated_variant_impl $marker $first);
}
impl $crate::StateUnionMember<$first>
for $marker
{}
$(
impl [<__state_union_seal_ $marker:snake>]::Sealed for $state {}
impl $crate::StateUnionProofMembership<$marker> for $state {}
impl $crate::StateUnionErased<$marker> for $state {
$crate::__StateUnion!(@erased_variant_impl $marker $state);
}
impl [<In $marker>] for $state {}
impl $crate::In<$marker> for $state {
$crate::__StateUnion!(@into_discriminated_variant_impl $marker $state);
}
impl $crate::StateUnionMember<$state>
for $marker
{}
)*
impl<Standin, To> $crate::StateUnionTransition<Standin, To>
for $marker
where
Standin: $crate::Transition<$first, To>,
$(
Standin: $crate::Transition<
$state,
To,
F = <Standin as $crate::Transition<$first, To>>::F,
>,
)*
{
type F = <Standin as $crate::Transition<$first, To>>::F;
}
$crate::__StateUnion!(
@shared_effect $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@shared_pinned_effect $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@discriminated_transition $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@discriminated_pinned_transition $marker:
$first $(| $state)*
);
impl $crate::StateUnionRuntime for $marker {
fn contains(state: &dyn $crate::StateTrait) -> bool {
state.type_id() == ::core::any::TypeId::of::<$first>()
$(
|| state.type_id() == ::core::any::TypeId::of::<$state>()
)*
|| state.type_id()
== ::core::any::TypeId::of::<$crate::StateUnionState<$marker>>()
}
fn expected_type_name() -> &'static str {
::core::any::type_name::<$crate::StateUnionState<$marker>>()
}
}
$crate::__StateUnion!(
@maybe_conversion_trait $enum $marker:
$first $(| $state)*
);
}
};
(
@trait $marker:ident [] $enum:tt:
$first:ident $(| $state:ident)*
) => {
$crate::__private::paste! {
#[doc = concat!(
"State-union marker for `",
stringify!($marker),
"`.\n\n",
"Use this marker as the type-level name of the union. ",
"The generated `In",
stringify!($marker),
"` trait restricts APIs to members of the union, and the generated enum ",
"named by `StateUnionDiscriminant::Enum` carries concrete state values.\n\n",
"`",
stringify!($marker),
"` is not a concrete runtime state. It is a ZST used to name ",
"the set of states in generic signatures, for example ",
"`State<S, Connection, impl In",
stringify!($marker),
">`. When a value must remember which concrete member it ",
"currently contains, use `DiscriminatedState<S, T, ",
stringify!($marker),
">` or the generated enum instead."
)]
#[allow(dead_code)]
pub struct $marker;
impl $crate::StateMarker for $marker {
type Kind = $crate::UnionStateKind;
fn erased_state() -> &'static dyn $crate::StateTrait {
panic!("union state markers cannot be stored as ErasedState")
}
}
#[doc(hidden)]
#[allow(dead_code)]
mod [<__state_union_seal_ $marker:snake>] {
#[allow(dead_code)]
pub trait Sealed {}
}
#[doc = concat!(
"Sealed membership trait for states in the `",
stringify!($marker),
"` state union.\n\n",
"This trait is generated by `StateUnion!` and is implemented only for ",
"the concrete states listed in that macro invocation. Use `impl In",
stringify!($marker),
"` in method receivers and generic bounds when an API accepts any ",
"state in the union.\n\n",
"Because the trait is sealed, downstream crates cannot widen the union ",
"by implementing it for additional states. That keeps a method such as ",
"`fn endpoint(self: &State<impl SRef, Self, impl In",
stringify!($marker),
">)` tied to the definition crate's contract. For generic helper APIs ",
"that receive the marker as a type parameter, use `In<",
stringify!($marker),
">` instead; this generated trait is the ergonomic spelling for normal ",
"method signatures."
)]
#[allow(dead_code)]
pub trait [<In $marker>]:
$crate::StateTrait
+ $crate::StateMarker
+ [<__state_union_seal_ $marker:snake>]::Sealed
+ $crate::In<$marker>
+ $crate::StateUnionErased<$marker>
+ $crate::StateUnionProofMembership<$marker>
{
}
impl [<__state_union_seal_ $marker:snake>]::Sealed
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionProofMembership<$marker>
for $crate::StateUnionState<$marker>
{}
impl $crate::StateUnionErased<$marker>
for $crate::StateUnionState<$marker>
{
$crate::__StateUnion!(@erased_identity_impl $marker);
}
impl [<In $marker>] for $crate::StateUnionState<$marker> {}
impl $crate::In<$marker> for $crate::StateUnionState<$marker> {
$crate::__StateUnion!(@into_discriminated_identity_impl $marker);
}
impl [<__state_union_seal_ $marker:snake>]::Sealed for $first {}
impl $crate::StateUnionProofMembership<$marker> for $first {}
impl $crate::StateUnionErased<$marker> for $first {
$crate::__StateUnion!(@erased_variant_impl $marker $first);
}
impl [<In $marker>] for $first {}
impl $crate::In<$marker> for $first {
$crate::__StateUnion!(@into_discriminated_variant_impl $marker $first);
}
impl $crate::StateUnionMember<$first>
for $marker
{}
$(
impl [<__state_union_seal_ $marker:snake>]::Sealed for $state {}
impl $crate::StateUnionProofMembership<$marker> for $state {}
impl $crate::StateUnionErased<$marker> for $state {
$crate::__StateUnion!(@erased_variant_impl $marker $state);
}
impl [<In $marker>] for $state {}
impl $crate::In<$marker> for $state {
$crate::__StateUnion!(@into_discriminated_variant_impl $marker $state);
}
impl $crate::StateUnionMember<$state>
for $marker
{}
)*
impl<Standin, To> $crate::StateUnionTransition<Standin, To>
for $marker
where
Standin: $crate::Transition<$first, To>,
$(
Standin: $crate::Transition<
$state,
To,
F = <Standin as $crate::Transition<$first, To>>::F,
>,
)*
{
type F = <Standin as $crate::Transition<$first, To>>::F;
}
$crate::__StateUnion!(
@shared_effect $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@shared_pinned_effect $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@discriminated_transition $marker:
$first $(| $state)*
);
$crate::__StateUnion!(
@discriminated_pinned_transition $marker:
$first $(| $state)*
);
impl $crate::StateUnionRuntime for $marker {
fn contains(state: &dyn $crate::StateTrait) -> bool {
state.type_id() == ::core::any::TypeId::of::<$first>()
$(
|| state.type_id() == ::core::any::TypeId::of::<$state>()
)*
|| state.type_id()
== ::core::any::TypeId::of::<$crate::StateUnionState<$marker>>()
}
fn expected_type_name() -> &'static str {
::core::any::type_name::<$crate::StateUnionState<$marker>>()
}
}
$crate::__StateUnion!(
@maybe_conversion_trait $enum $marker:
$first $(| $state)*
);
}
};
(
@standalone_enum $enum_name:ident:
$first:ident $(| $state:ident)*
) => {
$crate::__StateUnionEnum!(@standalone_enum $enum_name: $first $(| $state)*);
};
(
@discriminated_transition $marker:ident:
$first:ident $(| $state:ident)*
) => {
impl<T, To, Args> $crate::StateUnionDiscriminatedTransition<T, To, Args> for $marker
where
T: $crate::StateMachineImpl
+ $crate::TransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
<T as $crate::TransitionEffectSelector<$first, To>>::Effect:
$crate::TransitionEffect<T, $first, To, Args>,
$(
T: $crate::TransitionEffectSelector<$state, To>,
<T as $crate::TransitionEffectSelector<$state, To>>::Effect:
$crate::TransitionEffect<T, $state, To, Args>,
)*
{
fn transition<Storage>(
state: $crate::DiscriminatedState<Storage, T, Self>,
args: Args,
callsite: $crate::TransitionCallsite,
) -> $crate::State<Storage, T, To>
where
Storage: $crate::SMut,
To: $crate::ConcreteStateTrait,
{
let inferred_state_type = $crate::erased_state_type_id(
&$crate::discriminated_state_marker(&state),
);
match inferred_state_type {
state_type if state_type == ::core::any::TypeId::of::<$first>() => {
let state =
$crate::concretize_discriminated_state::<Storage, T, $marker, $first>(
state,
);
$crate::transition_concrete_after_effect::<
Storage,
T,
$first,
To,
Args,
<T as $crate::TransitionEffectSelector<$first, To>>::Effect,
>(state, args, callsite)
}
$(
state_type if state_type == ::core::any::TypeId::of::<$state>() => {
let state =
$crate::concretize_discriminated_state::<Storage, T, $marker, $state>(
state,
);
$crate::transition_concrete_after_effect::<
Storage,
T,
$state,
To,
Args,
<T as $crate::TransitionEffectSelector<$state, To>>::Effect,
>(state, args, callsite)
}
)*
_ => unreachable!("state union inferred a state outside of its variants"),
}
}
}
};
(
@discriminated_pinned_transition $marker:ident:
$first:ident $(| $state:ident)*
) => {
impl<T, To, Args> $crate::StateUnionDiscriminatedPinnedTransition<T, To, Args> for $marker
where
T: $crate::StateMachineImpl
+ $crate::PinnedTransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
<T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect:
$crate::PinnedTransitionEffect<T, $first, To, Args>,
$(
T: $crate::PinnedTransitionEffectSelector<$state, To>,
<T as $crate::PinnedTransitionEffectSelector<$state, To>>::Effect:
$crate::PinnedTransitionEffect<T, $state, To, Args>,
)*
{
fn pinned_transition<Storage>(
state: $crate::DiscriminatedState<Storage, T, Self>,
args: Args,
callsite: $crate::TransitionCallsite,
) -> $crate::State<Storage, T, To>
where
Storage: $crate::SPinMut,
To: $crate::ConcreteStateTrait,
{
let inferred_state_type = $crate::erased_state_type_id(
&$crate::discriminated_state_marker(&state),
);
match inferred_state_type {
state_type if state_type == ::core::any::TypeId::of::<$first>() => {
let state =
$crate::concretize_discriminated_state::<Storage, T, $marker, $first>(
state,
);
$crate::transition_concrete_after_pinned_effect::<
Storage,
T,
$first,
To,
Args,
<T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect,
>(state, args, callsite)
}
$(
state_type if state_type == ::core::any::TypeId::of::<$state>() => {
let state =
$crate::concretize_discriminated_state::<Storage, T, $marker, $state>(
state,
);
$crate::transition_concrete_after_pinned_effect::<
Storage,
T,
$state,
To,
Args,
<T as $crate::PinnedTransitionEffectSelector<$state, To>>::Effect,
>(state, args, callsite)
}
)*
_ => unreachable!("state union inferred a state outside of its variants"),
}
}
}
};
(
@shared_effect $marker:ident:
$first:ident $(| $state:ident)*
) => {
impl<T, To> $crate::StateUnionSharedEffect<T, To> for $marker
where
T: $crate::StateMachineImpl
+ $crate::TransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
$marker: $crate::StateUnionTransition<T::Standin, To>,
$(
T: $crate::TransitionEffectSelector<
$state,
To,
Effect = <T as $crate::TransitionEffectSelector<$first, To>>::Effect,
>,
)*
{
type Effect = <T as $crate::TransitionEffectSelector<$first, To>>::Effect;
}
impl<T, To, Args> $crate::StateUnionSharedTransitionEffect<T, To, Args>
for $marker
where
T: $crate::StateMachineImpl
+ $crate::TransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
$marker: $crate::StateUnionSharedEffect<
T,
To,
Effect = <T as $crate::TransitionEffectSelector<$first, To>>::Effect,
>,
<T as $crate::TransitionEffectSelector<$first, To>>::Effect:
$crate::TransitionEffect<T, $first, To, Args>,
{
fn apply(value: &mut T, args: Args) {
<<T as $crate::TransitionEffectSelector<$first, To>>::Effect as $crate::TransitionEffect<
T,
$first,
To,
Args,
>>::apply(value, args);
}
}
};
(
@shared_pinned_effect $marker:ident:
$first:ident $(| $state:ident)*
) => {
impl<T, To> $crate::StateUnionSharedPinnedEffect<T, To> for $marker
where
T: $crate::StateMachineImpl
+ $crate::PinnedTransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
$marker: $crate::StateUnionTransition<T::Standin, To>,
$(
T: $crate::PinnedTransitionEffectSelector<
$state,
To,
Effect = <T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect,
>,
)*
{
type Effect = <T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect;
}
impl<T, To, Args> $crate::StateUnionSharedPinnedTransitionEffect<T, To, Args>
for $marker
where
T: $crate::StateMachineImpl
+ $crate::PinnedTransitionEffectSelector<$first, To>,
To: $crate::ConcreteStateTrait,
$marker: $crate::StateUnionSharedPinnedEffect<
T,
To,
Effect = <T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect,
>,
<T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect:
$crate::PinnedTransitionEffect<T, $first, To, Args>,
{
fn apply_pinned(value: ::core::pin::Pin<&mut T>, args: Args) {
<<T as $crate::PinnedTransitionEffectSelector<$first, To>>::Effect as $crate::PinnedTransitionEffect<
T,
$first,
To,
Args,
>>::apply(value, args);
}
}
};
(@into_discriminated_method $marker:ident) => {
type Marker: $crate::StateUnionDiscriminant
+ $crate::StateMarker<Kind = $crate::UnionStateKind>;
#[must_use]
fn into_discriminated<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $marker>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl;
};
(@erased_identity_impl $marker:ident) => {
fn into_union_erased<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $marker>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
$marker: $crate::StateUnionDiscriminant,
{
$crate::rediscriminate_union_state::<Storage, T, $marker, $marker>(state)
}
};
(@erased_variant_impl $marker:ident $variant:ident) => {
fn into_union_erased<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $marker>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
$marker: $crate::StateUnionDiscriminant,
{
$crate::discriminate_state::<Storage, T, Self, $marker>(state)
}
};
(
@erased_union_variant_impl $source:ident => $target:ident:
$first:ident $(| $state:ident)*
) => {
fn into_union_erased<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $target>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
$target: $crate::StateUnionDiscriminant,
{
$crate::rediscriminate_union_state::<Storage, T, $source, $target>(state)
}
};
(@into_discriminated_identity_impl $marker:ident) => {
fn into_discriminated<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $marker>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
{
$crate::rediscriminate_union_state::<Storage, T, $marker, $marker>(state)
}
};
(@into_discriminated_variant_impl $marker:ident $variant:ident) => {
fn into_discriminated<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $marker>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
{
$crate::discriminate_state::<Storage, T, Self, $marker>(state)
}
};
(
@into_discriminated_union_variant_impl $source:ident => $target:ident:
$first:ident $(| $state:ident)*
) => {
fn into_discriminated<Storage, T>(
state: $crate::State<Storage, T, Self>,
) -> $crate::DiscriminatedState<Storage, T, $target>
where
Self: Sized,
Storage: $crate::StateStorage,
T: $crate::StateMachineImpl,
{
$crate::rediscriminate_union_state::<Storage, T, $source, $target>(state)
}
};
(
@maybe_conversion_trait [enum $enum_name:ident] $marker:ident:
$first:ident $(| $state:ident)*
) => {};
(
@maybe_conversion_trait [] $marker:ident:
$first:ident $(| $state:ident)*
) => {};
(
@enum $enum_name:ident $marker:ident:
$first:ident $(| $state:ident)*
) => {
$crate::__StateUnionEnum!(@enum $enum_name $marker: $first $(| $state)*);
};
}