diff --git a/crates/core/src/yarn_fn.rs b/crates/core/src/yarn_fn.rs index 51e4d176..4208fe6b 100644 --- a/crates/core/src/yarn_fn.rs +++ b/crates/core/src/yarn_fn.rs @@ -4,7 +4,7 @@ mod function_registry; mod function_wrapping; -mod optionality; +pub mod optionality; mod parameter_wrapping; pub(crate) use function_registry::*; diff --git a/crates/core/src/yarn_fn/optionality.rs b/crates/core/src/yarn_fn/optionality.rs index 981986f5..baa30245 100644 --- a/crates/core/src/yarn_fn/optionality.rs +++ b/crates/core/src/yarn_fn/optionality.rs @@ -1,41 +1,55 @@ +//! Marker traits for [`super::YarnFnParam`] to determine if the type is [`Required`] or +//! [`Optional`]. #![allow(missing_debug_implementations)] use yarnspinner_macros::all_tuples; /// Marker trait for valid optionality hints. -pub trait Optionality {} +pub trait Optionality: private::Sealed {} /// An optional parameter or a tuple where /// the last element is optional. pub struct Optional; +impl private::Sealed for Optional {} impl Optionality for Optional {} /// A parameter that is required. pub struct Required; +impl private::Sealed for Required {} impl Optionality for Required {} +mod private { + /// Used to seal [`AllowedOptionalityChain`] so the type can be exported, + /// but not implemented. + pub trait Sealed {} +} + /// A valid chain of optionality hints /// i.e. a chain where no optional element follows /// a required element. -pub trait AllowedOptionalityChain { +pub trait AllowedOptionalityChain: private::Sealed { /// The optionality hint of the last element in the chain. type Last: Optionality; } +impl private::Sealed for () {} impl AllowedOptionalityChain for () { type Last = Required; } +impl private::Sealed for (O,) {} impl AllowedOptionalityChain for (O,) { type Last = O; } +impl private::Sealed for (Required, O) {} impl AllowedOptionalityChain for (Required, O) { type Last = O; } +impl private::Sealed for (Optional, Optional) {} impl AllowedOptionalityChain for (Optional, Optional) { type Last = Optional; } @@ -61,6 +75,7 @@ macro_rules! impl_chain { impl_chain!(@pairwise [$($param),*] [$($tt)* ($a, $b): AllowedOptionalityChain,] $b, $($tail,)*); }; (@emit [$($param: ident),*] [$($tt:tt)*] $last:ident,) => { + impl<$($param: Optionality),*> private::Sealed for ($($param),*) where $($tt)* {} impl<$($param: Optionality),*> AllowedOptionalityChain for ($($param),*) where $($tt)* { type Last = $last; } diff --git a/crates/yarnspinner/src/lib.rs b/crates/yarnspinner/src/lib.rs index 03182a10..ec882b57 100644 --- a/crates/yarnspinner/src/lib.rs +++ b/crates/yarnspinner/src/lib.rs @@ -28,10 +28,10 @@ pub mod prelude { pub mod core { //! Core types and traits that are used by both the compiler and runtime. pub use yarnspinner_core::prelude::{ - yarn_fn_type, yarn_library, Header, Instruction, IntoYarnValueFromNonYarnValue, - InvalidOpCodeError, Library, LineId, Node, Position, Program, Type, UntypedYarnFn, YarnFn, - YarnFnParam, YarnFnParamItem, YarnValue, YarnValueCastError, YarnValueWrapper, - YarnValueWrapperIter, + optionality, yarn_fn_type, yarn_library, Header, Instruction, + IntoYarnValueFromNonYarnValue, InvalidOpCodeError, Library, LineId, Node, Position, + Program, Type, UntypedYarnFn, YarnFn, YarnFnParam, YarnFnParamItem, YarnValue, + YarnValueCastError, YarnValueWrapper, YarnValueWrapperIter, }; } pub mod compiler {