Pre-RFC: Overload Short Curcuits

So what if it looked like this then, to make it clear that it's not a generic "is truthy" / "bool coercion", and additionally to make it possible to return custom values when short circuiting:

enum ShortCircuit<S, L> {
    Short(S),
    Long(L),
}

trait LogicalOr<Rhs = Self>: Sized {
    type Output;

    /// Decide whether the *logical or* should short-circuit
    /// or not based on its left-hand side argument. If so,
    /// return its final result, otherwise return the value
    /// that will get passed to `logical_or()` (normally this
    /// means returning self back, but you can change the value).
    fn short_circuit_or(self) -> ShortCircuit<Self::Output, Self>;

    /// Complete the *logical or* in case it did not short-circuit.
    /// Normally this would just return `rhs`.
    fn logical_or(self, rhs: Rhs) -> Self::Output;
}

then A() || B() desugars to

match A().short_circuit_or() {
    ShortCircuit::Short(res) => res,
    ShortCircuit::Long(l) => l.logical_or(B()),
}

This way it'd be possible to have

impl<T> LogicalOr<T> for Option<T> {
    type Output = T;
    ...
}

(currently known as .unwrap_or()), where if it short-circuits, the output type is T, not Option<T>; and it also works for non-Copy types — in your proposal, self would be consumed by is_truthy(), in mine it is (typically) returned back wrapped in ShortCircuit::Long().

Here's a playground with LogicalOr, LogicalAnd, some impls for bool and Option, a logical! macro to perform the desugaring, and a demo.

4 Likes