# Idea: \`Option::is\_none\_or\`/\`Result::is\_ok\_or\`/\`Result::is\_err\_or\`

**URL:** <https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212>\
**Category:** Uncategorized\
**Created:** [July 21, 2024, 7:00am UTC](https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212 "2024-07-21T07:00:56Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![uzytkownik](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/uzytkownik/32/5013_2.png) [@uzytkownik](https://internals.rust-lang.org/u/uzytkownik)\
**Post date:** [July 21, 2024, 7:00am UTC](https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212/1 "2024-07-21T07:00:56Z")

</div>

Currently all those types implement positive version of those functions - `Option::is_some_and`/`Result::is_err_and`/`Result::is_ok_and`. It would be nice if there was a symmetric function doing the negative (`val.is_some_and(f) == !val.is_none_or(f)`).

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [July 21, 2024, 7:34am UTC](https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212/2 "2024-07-21T07:34:06Z")

</div>

> <https://github.com/rust-lang/libs-team/issues/212>
>
> \# Proposal
> 
> \## Problem statement
> 
> It seems like there is a common use-case t…o check if an option is \`None\` or some condition holds for its value.
> 
> \## Motivation, use-cases
> 
> Similarly to how we have \`Option::is\_some\_and\` which is basically \`.map\_or(false, ...)\`, sometimes it is desirable to have the opposite "default" value, i.e. sometimes a better name for \`.map\_or(true, ...)\` is wanted. See for example comments on the \[\`Option::is\_some\_and\`\](https://github.com/rust-lang/rust/issues/93050) tracking issue:
> 
> \- https://github.com/rust-lang/rust/issues/93050#issuecomment-1151881604
> \- https://github.com/rust-lang/rust/issues/93050#issuecomment-1160253211
> \- https://github.com/rust-lang/rust/issues/93050#issuecomment-1164666533
> \- https://github.com/rust-lang/rust/issues/93050#issuecomment-1180638364
> 
> See also 45 occurrences of \`.map\_or(true, ...)\` in the rustc itself:
> 
> \<details\>\<summary\>list\</summary\>
> \<p\>
> 
> \`\`\`
> :~/rust-lib (rust-lib); rg ".map\_or\\(true" ./compiler --stats -q | rg "\\d+ matches"
> 45 matches
> :~/rust-lib (rust-lib); rg ".map\_or\\(true" ./compiler
> ./compiler/rustc\_middle/src/values.rs
> 180: let check\_params = def\_id.as\_local().map\_or(true, |def\_id| {
> 
> ./compiler/rustc\_middle/src/ty/instance.rs
> 236: return ty.ty\_adt\_def().map\_or(true, |adt\_def| {
> 
> ./compiler/rustc\_session/src/parse.rs
> 58: self.spans.borrow().get(&feature).map\_or(true, |spans| spans.is\_empty())
> 
> ./compiler/rustc\_passes/src/dead.rs
> 682: .map\_or(true, |layout| layout.is\_zst())
> 
> ./compiler/rustc\_hir\_analysis/src/coherence/inherent\_impls\_overlap.rs
> 152: .map\_or(true, |overlap| {
> 
> ./compiler/rustc\_codegen\_cranelift/build\_system/build\_sysroot.rs
> 72: if file.extension().map\_or(true, |ext| ext.to\_str().unwrap() != "o") {
> 
> ./compiler/rustc\_hir\_analysis/src/check\_unused.rs
> 79: tcx.extern\_mod\_stmt\_cnum(def\_id).map\_or(true, |cnum| {
> 
> ./compiler/rustc\_attr/src/builtin.rs
> 1092: if sess.opts.pretty.map\_or(true, |pp| pp.needs\_analysis()) {
> 
> ./compiler/rustc\_resolve/src/macros.rs
> 840: if kind != NonMacroAttrKind::Tool && binding.map\_or(true, |b| b.is\_import()) {
> 
> ./compiler/rustc\_resolve/src/imports.rs
> 249: || max\_vis.get().map\_or(true, |max\_vis| vis.is\_at\_least(max\_vis, self))
> 
> ./compiler/rustc\_parse/src/parser/attr.rs
> 428: attr.ident().map\_or(true, |ident| {
> 
> ./compiler/rustc\_resolve/src/lib.rs
> 1066: if def\_id.map\_or(true, |def\_id| def\_id.is\_local()) {
> 
> ./compiler/rustc\_resolve/src/diagnostics.rs
> 285: self.extern\_prelude.get(&ident).map\_or(true, |entry| entry.introduced\_by\_item);
> 512: if filter\_fn(res) && ctxt.map\_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
> 
> ./compiler/rustc\_trait\_selection/src/traits/error\_reporting/suggestions.rs
> 1463: .map\_or(true, |def\_id| self.tcx.object\_safety\_violations(def\_id).is\_empty())
> 1499: && last\_ty.map\_or(true, |last\_ty| {
> 
> ./compiler/rustc\_infer/src/infer/mod.rs
> 1474: value.as\_ref().map\_or(true, |value| !value.needs\_infer()),
> 
> ./compiler/rustc\_mir\_dataflow/src/framework/graphviz.rs
> 416: assert!(befores.as\_ref().map\_or(true, ExactSizeIterator::is\_empty));
> 
> ./compiler/rustc\_mir\_dataflow/src/framework/direction.rs
> 290: if dead\_unwinds.map\_or(true, |dead| !dead.contains(bb)) {
> 505: if dead\_unwinds.map\_or(true, |dead| !dead.contains(bb)) {
> 537: if dead\_unwinds.map\_or(true, |dead| !dead.contains(bb)) {
> 563: if dead\_unwinds.map\_or(true, |dead| !dead.contains(bb)) {
> 
> ./compiler/rustc\_hir\_typeck/src/\_match.rs
> 155: && prior\_arm.map\_or(true, |(\_, t, \_)| self.can\_coerce(t, ret\_ty))
> 
> ./compiler/rustc\_hir\_typeck/src/lib.rs
> 490: trait\_did.map\_or(true, |trait\_did| {
> 
> ./compiler/rustc\_hir\_typeck/src/expr.rs
> 1458: if count.try\_eval\_usize(tcx, self.param\_env).map\_or(true, |len| len \> 1) {
> 
> ./compiler/rustc\_hir\_typeck/src/coercion.rs
> 947: .map\_or(true, |u| u.is\_empty()) =\>
> 
> ./compiler/rustc\_hir\_typeck/src/fn\_ctxt/\_impl.rs
> 992: .map\_or(true, |ty| expected.peel\_refs() != ty.peel\_refs())
> 
> ./compiler/rustc\_hir\_typeck/src/generator\_interior/mod.rs
> 396: || ty.map\_or(true, |ty| {
> 
> ./compiler/rustc\_hir\_typeck/src/fn\_ctxt/checks.rs
> 2190: .filter(|(idx, \_)| expected\_idx.map\_or(true, |expected\_idx| expected\_idx == \*idx))
> 
> ./compiler/rustc\_hir/src/def.rs
> 729: self.ns().map\_or(true, |actual\_ns| actual\_ns == ns)
> 
> ./compiler/rustc\_index/src/interval.rs
> 234: current.map\_or(true, |x| x \< self.domain as u32)
> 
> ./compiler/rustc\_expand/src/config.rs
> 466: parse\_cfg(&meta\_item, &self.sess).map\_or(true, |meta\_item| {
> 474: if !self.features.map\_or(true, |features| features.stmt\_expr\_attributes) {
> 
> ./compiler/rustc\_const\_eval/src/interpret/util.rs
> 44: let is\_used = unused\_params.contains(index).map\_or(true, |unused| !unused);
> 
> ./compiler/rustc\_const\_eval/src/interpret/intern.rs
> 117: let frozen = ty.map\_or(true, |ty| ty.is\_freeze(\*ecx.tcx, ecx.param\_env));
> 
> ./compiler/rustc\_const\_eval/src/interpret/memory.rs
> 431: if offset.checked\_add(size, &self.tcx).map\_or(true, |end| end \> alloc\_size) {
> 
> ./compiler/rustc\_const\_eval/src/interpret/projection.rs
> 295: if from.checked\_add(to).map\_or(true, |to| to \> len) {
> 
> ./compiler/rustc\_mir\_transform/src/const\_prop\_lint.rs
> 722: .map\_or(true, |layout| layout.is\_zst())
> 
> ./compiler/rustc\_mir\_transform/src/coverage/graph.rs
> 387: if !self.counter\_kind.as\_ref().map\_or(true, |c| c.is\_expression()) {
> 
> ./compiler/rustc\_mir\_transform/src/const\_prop.rs
> 1142: .map\_or(true, |layout| layout.is\_zst())
> 
> ./compiler/rustc\_mir\_transform/src/coverage/spans.rs
> 484: if self.prev\_expn\_span.map\_or(true, |prev\_expn\_span| {
> 
> ./compiler/rustc\_mir\_build/src/check\_unsafety.rs
> 172: ref kind if ExprCategory::of(kind).map\_or(true, |cat| cat == ExprCategory::Place) =\> {
> 
> ./compiler/rustc\_borrowck/src/type\_check/mod.rs
> 1892: if len.try\_eval\_usize(tcx, self.param\_env).map\_or(true, |len| len \> 1) {
> 
> ./compiler/rustc\_lint/src/expect.rs
> 29: && tool\_filter.map\_or(true, |filter| expectation.lint\_tool == Some(filter))
> 
> ./compiler/rustc\_ast\_passes/src/feature\_gate.rs
> 100: if self.sess.opts.pretty.map\_or(true, |ppm| ppm.needs\_hir()) {
> \`\`\`
> 
> \</p\>
> \</details\>
> 
> \## Solution sketches
> 
> \`\`\`rust
> impl\<T\> Option\<T\> {
> pub fn is\_none\_or(self, f: impl FnOnce(T) -\> bool) -\> bool {
> match self {
> None =\> true,
> Some(x) =\> f(x),
> }
> }
> }
> \`\`\`
> 
> \## Links and related work
> 
> There is an open PR implementing this, that was untouched for 8 moths: https://github.com/rust-lang/rust/pull/100602
> 
> \## What happens now?
> 
> This issue is part of the libs-api team \[API change proposal process\]. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
> 
> \[API change proposal process\]: https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [July 21, 2024, 2:04pm UTC](https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212/3 "2024-07-21T14:04:05Z")

</div>

Available in nightly

> **[Option in std::option - Rust](https://doc.rust-lang.org/nightly/std/option/enum.Option.html#method.is_none_or)**
>
> The \`Option\` type. See the module level documentation for more.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [October 19, 2024, 2:04pm UTC](https://internals.rust-lang.org/t/idea-option-is-none-or-result-is-ok-or-result-is-err-or/21212/4 "2024-10-19T14:04:44Z")

</div>

Closed on October 19, 2024, 2:04pm UTC

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