diff --git a/block2/CHANGELOG.md b/block2/CHANGELOG.md index 7561139af..e292d5278 100644 --- a/block2/CHANGELOG.md +++ b/block2/CHANGELOG.md @@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed * **BREAKING**: Cleaned up `BlockArguments` trait, it is now sealed and a subtrait of `EncodeArguments`. +* **BREAKING**: Cleaned up `IntoConcreteBlock` trait, it is now sealed and the + associated output type has been renamed to `Output`. ## 0.2.0-alpha.5 - 2022-07-19 diff --git a/block2/src/concrete_block.rs b/block2/src/concrete_block.rs index e23607650..29a4e0bff 100644 --- a/block2/src/concrete_block.rs +++ b/block2/src/concrete_block.rs @@ -9,13 +9,26 @@ use objc2_encode::{Encode, Encoding, RefEncode}; use crate::{ffi, Block, BlockArguments, RcBlock}; -/// Types that may be converted into a `ConcreteBlock`. -pub trait IntoConcreteBlock: Sized { +mod private { + pub trait Sealed {} +} + +/// Types that may be converted into a [`ConcreteBlock`]. +/// +/// This is implemented for [`Fn`] closures of up to 12 arguments, where each +/// argument and the return type implements [`Encode`]. +/// +/// +/// # Safety +/// +/// This is a sealed trait, and should not need to be implemented. Open an +/// issue if you know a use-case where this restrition should be lifted! +pub unsafe trait IntoConcreteBlock: private::Sealed + Sized { /// The return type of the resulting `ConcreteBlock`. - type Ret: Encode; + type Output: Encode; - /// Consumes self to create a `ConcreteBlock`. - fn into_concrete_block(self) -> ConcreteBlock; + #[doc(hidden)] + fn __into_concrete_block(self) -> ConcreteBlock; } macro_rules! concrete_block_impl { @@ -23,13 +36,18 @@ macro_rules! concrete_block_impl { concrete_block_impl!($f,); ); ($f:ident, $($a:ident : $t:ident),*) => ( - impl<$($t: Encode,)* R: Encode, X> IntoConcreteBlock<($($t,)*)> for X + impl<$($t: Encode,)* R: Encode, X> private::Sealed<($($t,)*)> for X + where + X: Fn($($t,)*) -> R, + {} + + unsafe impl<$($t: Encode,)* R: Encode, X> IntoConcreteBlock<($($t,)*)> for X where X: Fn($($t,)*) -> R, { - type Ret = R; + type Output = R; - fn into_concrete_block(self) -> ConcreteBlock<($($t,)*), R, X> { + fn __into_concrete_block(self) -> ConcreteBlock<($($t,)*), R, X> { extern "C" fn $f<$($t,)* R, X>( block: &ConcreteBlock<($($t,)*), R, X>, $($a: $t,)* @@ -156,13 +174,13 @@ impl ConcreteBlock where A: BlockArguments, R: Encode, - F: IntoConcreteBlock, + F: IntoConcreteBlock, { /// Constructs a `ConcreteBlock` with the given closure. /// When the block is called, it will return the value that results from /// calling the closure. pub fn new(closure: F) -> Self { - closure.into_concrete_block() + closure.__into_concrete_block() } }