# \`!\` in pattern position

**URL:** https://internals.rust-lang.org/t/in-pattern-position/12001
**Category:** Uncategorized
**Created:** [March 19, 2020, 2:15pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001 "2020-03-19T14:15:04Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)
#### Post date: [March 19, 2020, 2:15pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/1 "2020-03-19T14:15:04Z")

</div>

A while ago, I remember @nikomatsakis and @RalfJung were talking about allowing `!` to be used in match pattern positions. Doing so would allow/force the match branch to be omitted, making it possible to write code like this:

```rust
let result: Result<u32, !> = Ok(23);
let x = match result {
    Ok(x) => x,
    Err(!), // no branch here!
}

```

Is this still the plan? I ask because I'm currently writing some code that makes heavy use of `futures::select` with futures that never terminate. So I have a lot of `select` cases that would be nice to be able to write like this:

```rust
futures::select! {
    x = do_something() => x,
    ! = daemon(), // no branch here!
}

```

Also, in [#1699](https://github.com/rust-lang/rfcs/pull/1699) I proposed that if a trait impl method takes a `!` as an argument then the user should be allowed to omit the method entirely. Some of the push-back against that proposal has been that it allows method impls to be mysteriously missing for reasons that aren't obvious to the person reading the code, and also that it ties into the larger, unsolved, problem of method impls that can't be called for other reasons (eg. due to unsatisfiable `where` clauses) and how we can allow such trait impls to be written.

If we allowed `!` in pattern positions though it would at least solve the problem for `!`-arguments since we already allow patterns in argument positions. That is, we could just allow the method body to be omitted if `!` is used in an argument pattern (in parallel with the `match` syntax above), like this:

```rust
trait TakeFoo {
    type Foo;
    fn take_foo(self, foo: Self::Foo);
}

impl TakeFoo for String {
    type Foo = !;
    fn take_foo(self, !); // no body here!
}

```

So given that this feature seems pretty useful, is it still planned/wanted? Does need an RFC? Is any of it implemented? Is it far too early to do PRs for `syn` and `futures` to add support for it?

---

<div class="post-metadata">

### Author: ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)
#### Post date: [March 19, 2020, 2:45pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/2 "2020-03-19T14:45:46Z")

</div>

I don't know if that is planned, but I would prefer the pattern to be irrefutable:

```rust
let result: Result<u32, !> = Ok(23);
let Ok(x) = result;

```

This doesn't work at the moment, but in the meantime, you can write

```rust
let result: Result<u32, !> = Ok(23);
let x = match result {
    Ok(x) => x,
    Err(never) => never, // branch is never executed
}

```

---

<div class="post-metadata">

### Author: ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)
#### Post date: [March 19, 2020, 3:01pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/3 "2020-03-19T15:01:06Z")

</div>

I think this is still in the stage of "vague ideas in our minds".

@Aloso the problem is the interaction with other pattern-matching features such as auto-deref. When `x: &!`, we might not want `match x {}` to work.

The reason is that `match x { y => ... }` is supposed to be equivalent to `{ let y = x; ... }`, but then it would be odd if for `x: &!`, we consider that match arm unreachable (and consider it UB to ever get there with unsafe code!), without doing the same with `let`.

What is particularly bad about `match x {}` is that there is something here that deref's `x`, checks its discriminant, and then declares UB because there can be no valid discriminant -- but there is _no code that actually does that_. That should be some way to "point at" the thing that causes the discriminant to be loaded. Hence the proposal to allow `match x { &! /* no code */ }`. Now there is a match arm to point at that determines that there is no possible discriminant, and there is an `&` pattern that explicitly dereferences the reference.

Even with that proposal, `let Ok(x) = r` is legal; we just automatically desugar it to `let x = match r { Ok(x) => x, Err(!) }`. So, we can separate the discussion of "how do matches on uninhabited types behave" from "how much do we do implicitly in that area", because we have some _explicit syntax_ for uninhabited matching and then, orthogonally, can implicitly desugar things to add that syntax without people having to write it.

---

<div class="post-metadata">

### Author: ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)
#### Post date: [March 19, 2020, 3:29pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/4 "2020-03-19T15:29:36Z")

</div>

Another place I've long wanted a `!` pattern is for closures, so you could write something like

```rust
let x = Ok::<u32, !>(6);
let y = x.unwrap_or_else(|!|);

```

(I feel like I had a better example of the utility of this, but I don't remember where it was).

---

<div class="post-metadata">

### Author: ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)
#### Post date: [March 19, 2020, 4:17pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/5 "2020-03-19T16:17:14Z")

</div>

Relevant note in the compiler:

> <https://github.com/rust-lang/rust/blob/260228963211e6497eb0089f4417f89f80f50f0b/src/librustc_mir_build/build/matches/mod.rs#L123-L137>

---

<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: [March 19, 2020, 7:56pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/6 "2020-03-19T19:56:38Z")

</div>

> [@Nemo157](#):
>
> (I feel like I had a better example of the utility of this, but I don't remember where it was).

This pattern is the one allowing to get, for instance, non `try` functions out of their generic-over-the-error-type `try_()` implementations.

```rust
fn try_call<Ok, Err, F> (f: F) -> Result<Ok, Err>
where
    F : FnOnce() -> Result<Ok, Err>,
{ ... }

fn call<R, F> (f : F) -> R
where
    F : FnOnce() -> R
{
    try_call(|| Ok(f()))
        .unwrap_or_else(|!| {})
}

```

I personally use `enum Void {}` and `|it: Void| match it {}` in stable Rust.

---

<div class="post-metadata">

### Author: ![canndrew](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/canndrew/32/1676_2.png) [@canndrew](https://internals.rust-lang.org/u/canndrew)
#### Post date: [March 20, 2020, 4:47am UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/7 "2020-03-20T04:47:57Z")

</div>

@Aloso

> This doesn't work at the moment

It does actually, except that it's been feature gated for years behind `#![feature(exhaustive_patterns)]`.

@RalfJung I'm not sure I understand your point about `let y = x;`. Are you saying that auto-deref could cause `{ let y = x; ... }` to be interpreted as `{ let y = *x; ... }`? (Coz I don't see how that's less likely to happen and cause an uninitialized read for any other type). Or are you saying that if `x: &!` then leaving out the `let` entirely could be considered equivalent to dereferencing `x`? (Coz I don't think that follows). Or are you just saying that `{ let y = x; ... }` would make the `...` unreachable? (Coz I think that does follow, but also that having `x` in scope should make the code unreachable to begin with).

If it's the latter can you give an example of some `unsafe` code which we'd like to consider valid but which could have a `&!` in scope? It's not obvious to me how someone could end up in that situation without doing something which would be wrong even for a type other than `!`. They could have a `*const !` or `MaybeUninit<!>` in scope, but a `&!` could only be created from a raw pointer to an uninitialized `!` or by using a reference to a partially-initialized struct containing a `!`, neither of which can happen if we require data behind a reference to always be fully-initialized.

Also, even if we want to allow users to have a `&!` in scope in live code, that doesn't effect the safety of `match x {}` vs `match x { y => ... }`. It just means that reaching `match x {}` would cause undefined behaviour since it dereferences `x` but `match x { y => ... }` wouldn't since it doesn't. In `match x {}` the user is explicitly dereferencing the `&!` and matching against it. They're doing it "explicitly" by leaving out code, but I don't see how they could do that by accident and have it pass type-checking (which would indicate that they're working specifically with `!` and not some generic type parameter), and have it be invalid.

---

<div class="post-metadata">

### Author: ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)
#### Post date: [March 20, 2020, 5:24pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/8 "2020-03-20T17:24:42Z")

</div>

> [@RalfJung](#):
>
> When `x: &!` , we might not want `match x {}` to work.

I'm sorry I don't follow. References are guaranteed to point to valid data, so `&!` and `!` are pretty much equivalent.

When a value has the `!` or `&!` type, this code is unreachable, so the compiler doesn't need to generate code for this. This means that `Result<Foo, !>` should have the same representation as

```rust
struct Result(Foo);

```

Furthermore, the compiler can eliminate all code paths where a variable with the `!` type exists, so

```rust
match x: Result<Foo, !> {
    Ok(foo) => t,
    // No code emitted for this branch:
    Err(never) => {...}
}

```

IIUC, this means that `(x: Result::<Foo, !>).unwrap()` is a no-op.

---

<div class="post-metadata">

### Author: ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)
#### Post date: [March 20, 2020, 6:51pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/9 "2020-03-20T18:51:43Z")

</div>

> [@Aloso](#):
>
> References are guaranteed to point to valid data,

That's still up for debate:

> <https://github.com/rust-lang/unsafe-code-guidelines/issues/77>
>
> Discussing the memory-related properties of references: does \`&T\` have to point …to allocated memory (with at least \`size\_of::\<T\>()\` bytes being allocated)? If yes, does the memory have to contain data that satisfies the validity invariant of \`T\`?
> 
> If the answer to both of these questions is "yes", one consequence is that \`&!\` is uninhabited: There is no valid reference of type \`&!\`.
> 
> Currently, during LLVM lowering, we add a "dereferencable" attribute to references, indicating that the answer to the first question should be "yes". This is a rather unique case in that this is the only case where validity depends on the contents of memory. This opens some new, interesting questions:
> 
> 1) I mentioned above that \`size\_of::\<T\>()\` many bytes need to be dereferencable. How do we handle unsized types? We could determine the size according to the metadata and the type of the unsized tail. For slices, that's really easy, but for trait objects this involves the vtable, so it would introduce yet another kind of dependy of validity on the memory. However, vtables must not be modified, and they never deallocated (right?), so this is a fairly weak form of dependency where if a pointer was a valid vtable pointer once, then it always will be.
> 
> With more exotic forms of unsized types, this becomes less easy. \`extern type\` we can mostly ignore, we cannot even dynamically know their size so we basically can just assume it is 0, and check dereferencability for that. But what about custom DST? I don't think we want to make validity depend on \*executing arbitrary user-defined code\*. We could just check validity for the sized prefix of this unsized type, but that would introduce an inconsistency between primitive DST and user-defined custom DST. Is that a problem?
> 
> For unsized types, even the requirement that the pointer be well-aligned becomes subtle because determining alignment has similar issues than determining the size.
> 
> 2) What about validity of \`ManuallyDrop\<&T\>\`? \`ManuallyDrop\<T\>\` certainly shares all the bit-level properties of \`T\`, because we perform layout optimization on it. But does \`ManuallyDrop\<&T\>\` have to be dereferencable?
> 
> Note that this is not about aliasing or provenance; those should be discussed separately -- a bunch of open issues already exist for \[provenance in general\](https://github.com/rust-lang/unsafe-code-guidelines/issues?q=is%3Aissue+is%3Aopen+label%3AT-provenance) and \[stacked borrows specifically\](https://github.com/rust-lang/unsafe-code-guidelines/issues?q=is%3Aissue+is%3Aopen+label%3AT-stacked-borrows).
> 
> CURRENT STATE: The thread is long and there were many positions without a good summary. My own latest position can be \[found here\](https://github.com/rust-lang/unsafe-code-guidelines/issues/77#issuecomment-519997799).

---

<div class="post-metadata">

### Author: ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)
#### Post date: [March 22, 2020, 7:30pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/10 "2020-03-22T19:30:22Z")

</div>

Sorry for the brevity, my comment was probably not very comprehensible. I felt like this was all already written up somewhere so I didn't want to spend the time to write it up _again_, but then I should have searched for the previous write-up instead of just leaving away all details.^^

So, I found the previous thread on the topic:

> [@Blog post: never patterns, exhaustive matching, and uninhabited types](https://internals.rust-lang.org/t/blog-post-never-patterns-exhaustive-matching-and-uninhabited-types/8197):
>
> [I wrote a blog post](http://smallcultfollowing.com/babysteps/blog/2018/08/13/never-patterns-exhaustive-matching-and-uninhabited-types-oh-my/): [RFC 1216](https://github.com/rust-lang/rfcs/pull/1216) introduced ! as the sort of “canonical” uninhabited type in Rust, but actually one can readily make an uninhabited type of your very own just by declared an enum with no variants (e.g., enum Void { }). Since such an enum can never be instantiated, the type cannot have any values. Done. However, ever since the introduction of !, we’ve wrestled with some of its implications, particularly around exhaustiveness checking – that is, the checks the compiler does to ensur…

This should help resolve some of the confusion I caused. If there are still questions after reading that, please let me know. 🙂

---

<div class="post-metadata">

### Author: ![Aloso](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aloso/32/5039_2.png) [@Aloso](https://internals.rust-lang.org/u/Aloso)
#### Post date: [March 28, 2020, 5:43pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/11 "2020-03-28T17:43:20Z")

</div>

@RalfJung thanks, this really helped me understand the problem!

---

<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: [June 26, 2020, 5:43pm UTC](https://internals.rust-lang.org/t/in-pattern-position/12001/12 "2020-06-26T17:43:30Z")

</div>

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