Skip to content

operator& requires an already-graded error to conjoin different error types #384

Description

@Bronek

expected<int, Error> & expected<bool, ErrorOther> is ill-formed when neither error type is a copack, while the very same pair disjoins:

using L = fn::expected<int, Error>;
using R = fn::expected<bool, ErrorOther>;

static_assert(requires(L l, R r) { l | r; }); // expected<copack_for<int, bool>, pack<Error, ErrorOther>>
static_assert(requires(L l, R r) { l & r; }); // fails

The conjunction's error channel is the sum: producing the grade is what & does there, so requiring an operand to arrive already graded inverts the rule. Nowhere else in the channel algebra does a sum ask for one — | forms its value sum out of two ungraded value types, in every carrier:

expected<int, E> | expected<bool, E>  //  expected<copack_for<int, bool>, pack<E, E>>
optional<int>    | optional<bool>     //  optional<copack_for<int, bool>>
choice<int>      | choice<bool>       //  choice_for<int, bool>

Of the four channels — &'s value product and error sum, |'s value sum and error product — this is the only one that was gated.

Four operator& overloads in include/fn/expected.hpp — the different-error arms, one per value shape (void×value, value×void, void×void, value×value) — carry

&& (some_copack<typename ::std::remove_cvref_t<Lh>::error_type>
    || some_copack<typename ::std::remove_cvref_t<Rh>::error_type>)

on top of not is_same_v<El, Er>. Dropping that clause makes each arm serve any distinct pair: every one of them already computes copack_for<El, Er> and lifts each operand's error through the copack<>-guarded _nothrow_arm, so nothing downstream changes. fn::conjoin follows, being the fold of &.

Purely additive — everything newly accepted was ill-formed before, and a matching pair of error types still collapses to the plain error it had.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrelease-0.1Planned for release 0.1

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions