Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions library/core/src/array/iter/iter_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<T> PolymorphicIter<[MaybeUninit<T>]> {

#[inline]
pub(super) fn fold<B>(&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]
Expand Down Expand Up @@ -257,7 +257,7 @@ impl<T> PolymorphicIter<[MaybeUninit<T>]> {

#[inline]
pub(super) fn rfold<B>(&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]
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub fn from_fn<T, const N: usize, F>(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.
Expand Down Expand Up @@ -553,7 +553,7 @@ impl<T, const N: usize> [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
Expand Down Expand Up @@ -848,7 +848,7 @@ impl<T, const N: usize> [T; N] {
/// it easily optimizes away) so it doesn't impact the loop that fills the array.
#[inline]
fn from_trusted_iterator<T, const N: usize>(iter: impl UncheckedIterator<Item = T>) -> [T; N] {
try_from_trusted_iterator(iter.map(NeverShortCircuit)).0
try_from_trusted_iterator(iter.map(NeverShortCircuit::Continue)).into_continue()
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/array_chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/by_ref_sized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<I: Iterator> 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]
Expand Down Expand Up @@ -78,7 +78,7 @@ impl<I: DoubleEndedIterator> 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]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/take.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ impl<I: Iterator> SpecTake for Take<I> {
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]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
};
}
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/ops/index_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl Iterator for IndexRange {

#[inline]
fn fold<B, F: FnMut(B, usize) -> 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]
Expand Down Expand Up @@ -192,7 +192,7 @@ impl DoubleEndedIterator for IndexRange {

#[inline]
fn rfold<B, F: FnMut(B, usize) -> 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]
Expand Down
50 changes: 11 additions & 39 deletions library/core/src/ops/try_trait.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::convert::Infallible;
use crate::ops::ControlFlow;

/// The `?` operator and `try {}` blocks.
Expand Down Expand Up @@ -384,62 +385,33 @@ pub fn residual_into_try_type<R: Residual<O>, O>(r: R) -> <R as Residual<O>>::Tr
pub(crate) type ChangeOutputType<T: Try<Residual: Residual<V>>, V> =
<T::Residual as Residual<V>>::TryType;

/// An adapter for implementing non-try methods via the `Try` implementation.
///
/// Conceptually the same as `Result<T, !>`, 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<T>(pub T);
/// A helper alias for implementing non-try methods via the `Try` implementation.
pub(crate) type NeverShortCircuit<T> = ControlFlow<Infallible, T>;

impl<T> NeverShortCircuit<T> {
/// 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<A>(
mut f: impl FnMut(A) -> T,
) -> impl FnMut(A) -> NeverShortCircuit<T> {
move |a| NeverShortCircuit(f(a))
move |a| NeverShortCircuit::Continue(f(a))
}

#[inline]
#[rustc_force_inline]
pub(crate) fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
move |a, b| NeverShortCircuit(f(a, b))
}
}

pub(crate) enum NeverShortCircuitResidual {}

impl<T> Try for NeverShortCircuit<T> {
type Output = T;
type Residual = NeverShortCircuitResidual;

#[inline]
fn branch(self) -> ControlFlow<NeverShortCircuitResidual, T> {
ControlFlow::Continue(self.0)
}

#[inline]
fn from_output(x: T) -> Self {
NeverShortCircuit(x)
move |a, b| NeverShortCircuit::Continue(f(a, b))
}
}

impl<T> FromResidual for NeverShortCircuit<T> {
#[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<T> Residual<T> for NeverShortCircuitResidual {
type TryType = NeverShortCircuit<T>;
}

/// Implement `FromResidual<Yeet<T>>` on your type to enable
/// `do yeet expr` syntax in functions returning your type.
#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
Expand Down
Loading