# Feature request: Implement OR for Option and possibly Result

**URL:** <https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389>\
**Category:** language design\
**Created:** [August 17, 2024, 8:35pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389 "2024-08-17T20:35:05Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 17, 2024, 8:35pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/1 "2024-08-17T20:35:05Z")

</div>

I know that `Option::or` and `Option::or_else` exist, but imagine you're trying to find and transform the valid values in a sequence of them:

```rust
let mut ret = Vec::new();

for value in sequence {
    let foo = match value.foo() {
        Some(v) => v,
        None => continue,
    };
    let bar = match value.bar() {
        Some(v) => v,
        None => continue,
    };

    ret.push((foo, bar));
}

ret

```

Normally you have to use:

```rust
let bar = match foo {
    Some(v) => v,
    None => continue /* diverge */
};

```

`Option::or` and `Option::or_else` can't help with this.

If you could somehow do `OR` operations on Options and possibly Results, you could do this:

```rust
let bar = foo || continue /* diverge */;

```

and the compiler would detect that the other expression diverges.

This can of course be done with macros (as almost everything else), but it feels like unnecessary boilerplate.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [August 17, 2024, 8:37pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/2 "2024-08-17T20:37:02Z")

</div>

Not quite as short, but `let Some(foo) = value.foo() else { continue };`

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 17, 2024, 8:39pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/3 "2024-08-17T20:39:26Z")

</div>

I didn't know you could do that.

Also, my intention was to make this a one-liner. That means that using a macro is more concise.

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [August 17, 2024, 9:38pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/4 "2024-08-17T21:38:42Z")

</div>

A bit of `?`-compatible encapsulation can go a long way for conciseness.

```rust
impl Value {
    fn foo_bar(self) -> Option<(Foo, Bar)> {
        Some((self.foo()?, self.bar()?))
    }
}

```

```rust
    // Vec::from_iter(sequence.into_iter().filter_map(Value::foo_bar))
    // or:
    let mut ret = Vec::new();
    for foo_bar in sequence.into_iter().filter_map(Value::foo_bar) {
        ret.push(foo_bar);
    }
    ret

```

Or with [try blocks:](https://github.com/rust-lang/rust/issues/31436)

```rust
    let mut ret = Vec::new();
    for foo_bar in sequence.into_iter().filter_map(|value| try {
        (value.foo()?, value.bar()?)
    }) {
        ret.push(foo_bar);
    }
    ret

```

Or various less-terse variations.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [August 17, 2024, 10:39pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/5 "2024-08-17T22:39:55Z")

</div>

Or if you _don't_ want to transform into an iterator or add any helper functions:

```rust
for value in sequence {
    let Some(pair) = (try { (value.foo()?, value.bar()?) }) else { continue };
    ret.push(pair);
}

```

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 18, 2024, 8:04am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/6 "2024-08-18T08:04:21Z")

</div>

> [@TadaHrd](#):
>
> If you could somehow do `OR` operations on Options and possibly Results, you could do this:
> 
> `let bar = foo | continue /* diverge */;`

Note that this will always diverge, since the `continue` is evaluated unconditionally.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 18, 2024, 8:48am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/7 "2024-08-18T08:48:04Z")

</div>

I'm pretty sure it's lazily evaluated and if it's not, it could be changed in the 2024 edition.

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [August 18, 2024, 9:15am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/8 "2024-08-18T09:15:26Z")

</div>

`|` is definitely not lazily evaluated, and can’t be changed in any edition because it would silently and possibly drastically break code by starting to skip expressions that have side effects. You’d need the hypothetical overloadable `||` (which is not overloadable exactly because you can’t make arguments to function calls lazily evaluatable, among other reasons). `Option` could have a magical compiler-provided &&/||, but realistically nobody wants more magical library types.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 18, 2024, 11:23am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/9 "2024-08-18T11:23:46Z")

</div>

Oh yeah, I got the `|` operator confused with `||`.

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [August 18, 2024, 11:30am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/10 "2024-08-18T11:30:10Z")

</div>

> [@jdahlstrom](#):
>
> but realistically nobody wants more magical library types.

This, but also, nobody wants types whose operator overloads perform control flow that's more than an optimization.

With lazy-and and lazy-or, technically there's control flow going on, but it's just to shortcut the evaluation of later parts that are known not to be needed i.e. it's a performance optimization.

With an operator that can do things like `continue`, the semantics become more complex: can it still be used outside of a loop, for example? Either answer yields new questions, and the story doesn't get simpler.

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [August 25, 2024, 12:55am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/11 "2024-08-25T00:55:43Z")

</div>

> [@jjpe](#):
>
> With an operator that can do things like `continue`, the semantics become more complex: can it still be used outside of a loop, for example? Either answer yields new questions, and the story doesn't get simpler.

you can actually do this already.

`if x { return }` can be rewritten as `x && return;`, since `return` is just an expression of type `!`, and `!` can be coerced into any type.

---

<div class="post-metadata">

**Author:** ![InfernoDeity](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/infernodeity/32/7588_2.png) [@InfernoDeity](https://internals.rust-lang.org/u/InfernoDeity)\
**Post date:** [August 27, 2024, 5:39am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/12 "2024-08-27T05:39:10Z")

</div>

> [@jjpe](#):
>
> With lazy-and and lazy-or, technically there's control flow going on, but it's just to shortcut the evaluation of later parts that are known not to be needed i.e. it's a performance optimization.

It's very much not - you can rely on it for side effects that happen or don't, or even to guard against UB. For example:

```rust
// Deliberately contrived Unsafe Code Example
pub fn foo(x: Option<&bool>) -> bool{
     // Safe because of option layout guarantees, we either get `null` or the reference cast to the pointer
     let p: *const bool = unsafe{ core::mem::transmute(x) };

    return !p.is_null() && unsafe{ p.read() };
}

```

This code unconditionally has defined behaviour - there is no possible inputs to the function that could cause UB (without having already caused UB in the first place, by violating the requirements of the `&bool` inside the `Option`). If we were to instead use `&`, the code instead has undefined behaviour when called with `None`, as `p.read()` would be evaluated with a null `p` and that's UB.

The same goes if we do something like print or panic in the second operand. `x && dbg!(true)` will print `true = true` iff `x` is also `true`, and `x || panic!("Assertion Failed: {x}")` would be a perfectly correct way to handle an assertion.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 27, 2024, 8:36am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/13 "2024-08-27T08:36:34Z")

</div>

Are you saying it might not be possible?

Dne út 27. 8. 2024 7:49 uživatel Connor Horman via Rust Internals \<[notifications@rustlang.discoursemail.com](mailto:notifications@rustlang.discoursemail.com)\> napsal:

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [August 27, 2024, 10:54am UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/14 "2024-08-27T10:54:00Z")

</div>

> [@InfernoDeity](#):
>
> you can rely on it for side effects that happen or don't, or even to guard against UB.

You can also write arbitrary files in procedural macros, and the same thing goes there: you really shouldn't do that. It's likely to be surprising to someone reading that code. Because of that, I'd call using side effects within the lazy operators a slight abuse of those operators.

Honestly, I'd refactor your example immediately to make the side effects more obvious if it was in a code base I was involved in.

---

<div class="post-metadata">

**Author:** ![2e71828](https://avatars.discourse-cdn.com/v4/letter/2/3e96dc/32.png) [@2e71828](https://internals.rust-lang.org/u/2e71828)\
**Post date:** [August 27, 2024, 12:08pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/15 "2024-08-27T12:08:59Z")

</div>

From my understanding, preventing UB is the primary reason that C introduced mandatory short-circuiting in the first place. So that you could write something like `if (i < buf_len && buf[i] > 0)` in a language that doesn't have automatic bounds checks.

Given this history, it doesn't seem like an _abuse_ of these operators to combine a safety precondition with some kind of check that relies on it. Of course, like any other complicated one-liner, it may be a good stylistic choice to break it up into multiple statements. But that should be a case-by-case judgment call, not a blanket prohibition.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [February 18, 2026, 12:09pm UTC](https://internals.rust-lang.org/t/feature-request-implement-or-for-option-and-possibly-result/21389/18 "2026-02-18T12:09:26Z")

</div>

Closed on February 18, 2026, 12:09pm UTC

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
