diff --git a/futures/src/subscription.rs b/futures/src/subscription.rs index cb5d811e..d14724f5 100644 --- a/futures/src/subscription.rs +++ b/futures/src/subscription.rs @@ -299,20 +299,14 @@ impl Subscription { /// Transforms the [`Subscription`] output with the given function. /// - /// # Panics - /// The closure provided must be a non-capturing closure. The method - /// will panic in debug mode otherwise. + /// The closure provided must be a non-capturing closure. pub fn map(self, f: F) -> Subscription where T: 'static, F: Fn(T) -> A + MaybeSend + Clone + 'static, A: 'static, { - debug_assert!( - std::mem::size_of::() == 0, - "the closure {} provided in `Subscription::map` is capturing", - std::any::type_name::(), - ); + F::assert_zero_size(); struct Map where @@ -362,20 +356,14 @@ impl Subscription { /// Transforms the [`Subscription`] output with the given function, yielding only /// values only when the function returns `Some(A)`. /// - /// # Panics - /// The closure provided must be a non-capturing closure. The method - /// will panic in debug mode otherwise. + /// The closure provided must be a non-capturing closure. pub fn filter_map(mut self, f: F) -> Subscription where T: MaybeSend + 'static, F: Fn(T) -> Option + MaybeSend + Clone + 'static, A: MaybeSend + 'static, { - debug_assert!( - std::mem::size_of::() == 0, - "the closure {} provided in `Subscription::filter_map` is capturing", - std::any::type_name::(), - ); + F::assert_zero_size(); struct FilterMap where @@ -533,3 +521,25 @@ where crate::boxed_stream((self.spawn)(&self.data, input)) } } + +trait PanicWhenNotZeroSized: Sized { + const _CHECK: () = check_zero_sized::(); + + #[allow(path_statements, clippy::no_effect)] + fn assert_zero_size() { + ::_CHECK; + } +} + +impl PanicWhenNotZeroSized for T {} + +const fn check_zero_sized() { + if std::mem::size_of::() != 0 { + panic!( + "The Subscription closure provided is not non-capturing. \ + Closures given to Subscription::map or filter_map cannot \ + capture external variables. If you need to capture state, \ + consider using Subscription::with." + ); + } +}