diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs index 3c2343591f8cf..6814986c07676 100644 --- a/library/core/src/array/iter/iter_inner.rs +++ b/library/core/src/array/iter/iter_inner.rs @@ -199,7 +199,7 @@ impl PolymorphicIter<[MaybeUninit]> { #[inline] pub(super) fn fold(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] @@ -257,7 +257,7 @@ impl PolymorphicIter<[MaybeUninit]> { #[inline] pub(super) fn rfold(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { - self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 2dd639d68f0ea..177bc600ec72f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -109,7 +109,7 @@ pub fn from_fn(f: F) -> [T; N] where F: FnMut(usize) -> T, { - try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0 + try_from_fn(NeverShortCircuit::wrap_mut_1(f)).into_continue() } /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. @@ -553,7 +553,7 @@ impl [T; N] { where F: FnMut(T) -> U, { - self.try_map(NeverShortCircuit::wrap_mut_1(f)).0 + self.try_map(NeverShortCircuit::wrap_mut_1(f)).into_continue() } /// A fallible function `f` applied to each element on array `self` in order to @@ -848,7 +848,7 @@ impl [T; N] { /// it easily optimizes away) so it doesn't impact the loop that fills the array. #[inline] fn from_trusted_iterator(iter: impl UncheckedIterator) -> [T; N] { - try_from_trusted_iterator(iter.map(NeverShortCircuit)).0 + try_from_trusted_iterator(iter.map(NeverShortCircuit::Continue)).into_continue() } #[inline] diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 8f1744fc5fbb7..2a46f6baa44ac 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -212,7 +212,7 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index d084bede1eba6..804e6e34ae53b 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -42,7 +42,7 @@ impl Iterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] @@ -78,7 +78,7 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index b96335f415257..08a4c3b766bdf 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -266,7 +266,7 @@ impl SpecTake for Take { F: FnMut(B, Self::Item) -> B, { use crate::ops::NeverShortCircuit; - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index c7e1c4ef767ba..023ba59d8495c 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -377,7 +377,7 @@ macro_rules! impl_fold_via_try_fold { { use crate::ops::NeverShortCircuit; - self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 + self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).into_continue() } }; } diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 84395ddadf2b7..08764fc41d9a8 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -150,7 +150,7 @@ impl Iterator for IndexRange { #[inline] fn fold B>(mut self, init: B, f: F) -> B { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] @@ -192,7 +192,7 @@ impl DoubleEndedIterator for IndexRange { #[inline] fn rfold B>(mut self, init: B, f: F) -> B { - self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).into_continue() } #[inline] diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index f68782c804cdb..34ff67df32486 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -1,3 +1,4 @@ +use crate::convert::Infallible; use crate::ops::ControlFlow; /// The `?` operator and `try {}` blocks. @@ -384,62 +385,33 @@ pub fn residual_into_try_type, O>(r: R) -> >::Tr pub(crate) type ChangeOutputType>, V> = >::TryType; -/// An adapter for implementing non-try methods via the `Try` implementation. -/// -/// Conceptually the same as `Result`, but requiring less work in trait -/// solving and inhabited-ness checking and such, by being an obvious newtype -/// and not having `From` bounds lying around. -/// -/// Not currently planned to be exposed publicly, so just `pub(crate)`. -#[repr(transparent)] -pub(crate) struct NeverShortCircuit(pub T); +/// A helper alias for implementing non-try methods via the `Try` implementation. +pub(crate) type NeverShortCircuit = ControlFlow; impl NeverShortCircuit { /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`. /// /// This is useful for implementing infallible functions in terms of the `try_` ones, /// without accidentally capturing extra generic parameters in a closure. - #[inline] + #[rustc_force_inline] pub(crate) fn wrap_mut_1( mut f: impl FnMut(A) -> T, ) -> impl FnMut(A) -> NeverShortCircuit { - move |a| NeverShortCircuit(f(a)) + move |a| NeverShortCircuit::Continue(f(a)) } - #[inline] + #[rustc_force_inline] pub(crate) fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { - move |a, b| NeverShortCircuit(f(a, b)) - } -} - -pub(crate) enum NeverShortCircuitResidual {} - -impl Try for NeverShortCircuit { - type Output = T; - type Residual = NeverShortCircuitResidual; - - #[inline] - fn branch(self) -> ControlFlow { - ControlFlow::Continue(self.0) - } - - #[inline] - fn from_output(x: T) -> Self { - NeverShortCircuit(x) + move |a, b| NeverShortCircuit::Continue(f(a, b)) } -} -impl FromResidual for NeverShortCircuit { - #[inline] - fn from_residual(never: NeverShortCircuitResidual) -> Self { - match never {} + #[rustc_force_inline] + pub(crate) fn into_continue(self) -> T { + let NeverShortCircuit::Continue(v) = self; + v } } -impl Residual for NeverShortCircuitResidual { - type TryType = NeverShortCircuit; -} - /// Implement `FromResidual>` on your type to enable /// `do yeet expr` syntax in functions returning your type. #[unstable(feature = "try_trait_v2_yeet", issue = "96374")]