# Suggestion unwrap\_safe for Result\<T, !\>, or \`impl From\<Result\<T, !\>\> for T\`

**URL:** <https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455>\
**Category:** libs\
**Created:** [February 16, 2019, 9:09am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455 "2019-02-16T09:09:53Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 16, 2019, 9:09am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/1 "2019-02-16T09:09:53Z")

</div>

I’ve noticed that people have started to evaluate crate quality by looking for branches that may panic and seeing if they have been audited as impossible. So I propose adding something like

```rust
impl<T> Result<T, !> {
    fn unwrap_safe(self) -> T {
        self.unwrap()
    }
}

```

which saves you having to explain that the unwrap is audited safe in a comment.

Thoughts?

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 16, 2019, 9:18am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/2 "2019-02-16T09:18:49Z")

</div>

An example of current practice from embedded-hal (the comment would become unnecessary, reducing cognitive load for the reviewer)

```rust
            await!(timer.wait()).unwrap(); // NOTE(unwrap) E = Void

```

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [February 16, 2019, 10:19am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/3 "2019-02-16T10:19:10Z")

</div>

I’m definitely supportive of something like this but the implementation should be evocative of the very safety it tries to provide: instead of merely delegating to `unwrap`, I think it would be nicer to implement it with a non-fallible pattern match.

The name could be better, too – if I recall correctly, adding `_safe` to a method name is not really idiomatic in Rust; the no-panic guarantee of this method would also be unrelated to the kind of unsafety the language tries to protect programmers from. I would rather call it something like `into_inner()` that is pretty common for wrapper types which guarantee the ability to retrieve the wrapped value.

And while we are at it, would it be possible to `impl From<Result<T, !>> for T`? Then we could simply call `.into()` on an always-`Ok` result. (Not sure about the coherence rules here but I _think_ it should work.)

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [February 17, 2019, 10:51am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/4 "2019-02-17T10:51:24Z")

</div>

Since `!` should be isomorphic to `enum Never {}` (correct me if I am wrong), we could imagine a trait for their common behavior (naming could change):

```rust
trait UnReach : Into<!> {
  fn unreachable (self) -> ! { self.into() }
}
impl < Never : Into<!> > Unreach for Never {}

```

Where for all `enum Never {}` types, all we would have to is define/derive the `Into<!>` impl:

```rust
enum Never {}

impl Into<!> for Never {
  fn into(self) -> ! {
    match self {
      // ! /* there was a blog post about this */
    }
  }
}

```

We could then have:

```rust
/// in `::core`
impl <T, Never : Unreach> From< Result<T, Never> > for T
{
  fn from (
    result: Result<T, Never>,
  ) -> Self
  {
    match result {
      Ok(inner) => inner,
      Err(never) => never.unreachable(),
    }
  }
}

```

EDIT: link to the `!` pattern blog post: [http://smallcultfollowing.com/babysteps/blog/2018/08/13/never-patterns-exhaustive-matching-and-uninhabited-types-oh-my/](http://smallcultfollowing.com/babysteps/blog/2018/08/13/never-patterns-exhaustive-matching-and-uninhabited-types-oh-my/)

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 17, 2019, 1:20pm UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/7 "2019-02-17T13:20:34Z")

</div>

> [@dhm](#):
>
> Since `!` should be isomorphic to `enum Never {}` (correct me if I am wrong), we could imagine a trait for their common behavior

In theory, yeah, but I’m guessing that once `!` stabilizes, all uninhabited enums will disappear. Also, they exist in old code as a hack way of defining an external type, so I don’t know if these types _could_ exist even thought its kinda breaking the language rules.

> [@H2CO3](#):
>
> And while we are at it, would it be possible to `impl From<Result<T, !>> for T` ? Then we could simply call `.into()` on an always- `Ok` result. (Not sure about the coherence rules here but I _think_ it should work.)

It would be awesome, and a better solution, if you could just use `Into::into` .

**EDIT** combined responses.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [February 17, 2019, 2:55pm UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/8 "2019-02-17T14:55:13Z")

</div>

> [@derekdreery](#):
>
> I’m guessing that once `!` stabilizes, all uninhabited enums will disappear

They would indeed become an obsolete pattern, but keeping the options open can still be useful: in the same vein that `()` does not make any zero-sized struct useless (even if we ignored new-type usage for traits) since they can convey richer information.

Take, for instance, the return type of `::std::iter::Iterator::next()`, and let's call it `IteratorState<Item>`:

- Currently, `IteratorState<Item>` is `Option<Item>`:

- with generators, it could be seen as [`::std::ops::GeneratorState`](https://doc.rust-lang.org/std/ops/enum.GeneratorState.html)`<Iterator::Item, ()>`,

- 

```rust
enum IteratorState<T>
{
  Yielded(T),
  Exhausted,
}
use self::IteratorState::*;
impl<T> IteratorState<T> {
  fn some(self) -> Option<T> { match self {
    Yielded(value) => Some(value),
    Exhausted => None,
  }}
}

```

I thus think that custom never types may very well exist, either in the form

```rust
struct Never /* = */ (!);

```

or in the empty `enum` form. Hence the need for such a trait.

As an aside, I find custom inhabited types useful for "type-level enums", since it prevents using them as values.

Those are useful for truly immutable settings that can then lead to constant propagation and dead code removal:

```rust
trait Bool { const TRUTH: bool; fn is_true () -> bool { Self::TRUTH } }
  enum True {} impl Bool for True { const TRUTH: bool = true ; }
  enum False {} impl Bool for False { const TRUTH: bool = false; }

/// they can be "converted back to (zero-sized) values" with `PhantomData`
use ::std::marker::PhantomData;

struct Config<Verbose : Bool> {
  // ...
  _phantom: PhantomData<Verbose>,
}

impl<Verbose : Bool> Config<Verbose> {
  fn run (
    // ...
  )
  {
    if Verbose::is_true() { /* be verbose */ }
    // do some stuff
    if Verbose::is_true() { /* be verbose */ }
    // do more stuff
    if Verbose::is_true() { /* be verbose */ }
  }
}

```

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 24, 2019, 9:53am UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/9 "2019-02-24T09:53:32Z")

</div>

Interesting, thanks for taking the time to write this.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 25, 2019, 3:27pm UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/10 "2019-02-25T15:27:59Z")

</div>

It’s not immediately clear what the value is (rather than more `into` inference… ugh). `Result<T, !>` is (or should be) represented as a `T`, so I doubt `unwrap` is more than a nop.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [February 25, 2019, 3:39pm UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/11 "2019-02-25T15:39:38Z")

</div>

unwrap is a nop, as tested on the latest stable on playground. Even with empty enums like `Void` below.

playground link: [https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=26f2231c576149736f2966dd41b6b045](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=26f2231c576149736f2966dd41b6b045)

```rust
#[derive(Debug)]
pub enum Void {}

type T = u32;

#[inline(never)]
fn abort<T>() -> T {
    panic!()
}

#[inline(never)]
pub fn unwrap_me_test(r: Result<T, Void>) -> T {
    match r {
        Ok(x) => x,
        Err(y) => abort()
    }
}

```

```rust
playground::unwrap_me_test:
	movl	%edi, %eax
	retq

<playground::Void as core::fmt::Debug>::fmt:
	ud2

```

As you can see `playground::abort` is nowhere to be seen because it was completely optimized away.

---

<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:** [May 26, 2019, 3:39pm UTC](https://internals.rust-lang.org/t/suggestion-unwrap-safe-for-result-t-or-impl-from-result-t-for-t/9455/12 "2019-05-26T15:39:38Z")

</div>

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