# Idea: braced or-patterns -- Enum::{A | B | C}

**URL:** <https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208>\
**Category:** language design\
**Created:** [April 20, 2020, 4:44pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208 "2020-04-20T16:44:33Z")\
**Posts on this page:** 8\
**Page:** 1

<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:** [April 20, 2020, 4:44pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/1 "2020-04-20T16:44:33Z")

</div>

We can `use Enum::{A, B, C}`, and we can match `Enum::A | Enum:: B | Enum::C` -- what if we combine those ideas and allow patterns like `Enum::{A | B | C}`?

Here's a real example from [pr71231](https://github.com/rust-lang/rust/pull/71231):

```rust
    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect)
    | PlaceContext::MutatingUse(MutatingUseContext::Store)
    | PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
    | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
    | PlaceContext::MutatingUse(MutatingUseContext::AddressOf)
    | PlaceContext::MutatingUse(MutatingUseContext::Projection)
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {

```

Using nested `or_patterns`, this collapsed a fair bit:

```rust
    PlaceContext::MutatingUse(
        MutatingUseContext::Store
        | MutatingUseContext::AsmOutput
        | MutatingUseContext::Borrow
        | MutatingUseContext::AddressOf
        | MutatingUseContext::Projection,
    )
    | PlaceContext::NonMutatingUse(
        NonMutatingUseContext::Inspect
        | NonMutatingUseContext::SharedBorrow
        | NonMutatingUseContext::UniqueBorrow
        | NonMutatingUseContext::ShallowBorrow
        | NonMutatingUseContext::AddressOf
        | NonMutatingUseContext::Projection,
    ) => {

```

But it's still repetitive with those `Context` enum names. What if we could write this instead:

```rust
    PlaceContext::MutatingUse(MutatingUseContext::{
        Store | AsmOutput | Borrow | AddressOf | Projection
    })
    | PlaceContext::NonMutatingUse(NonMutatingUseContext::{
        Inspect | SharedBorrow | UniqueBorrow | ShallowBorrow | AddressOf | Projection
    }) => {

```

Or you could brace it even more:

```rust
    PlaceContext::{
        MutatingUse(MutatingUseContext::{
            Store | AsmOutput | Borrow | AddressOf | Projection
        })
        | NonMutatingUse(NonMutatingUseContext::{
            Inspect | SharedBorrow | UniqueBorrow | ShallowBorrow | AddressOf | Projection
        })
    } => {

```

But I might not choose to go that far in this case due to the added rightward drift. Of course, I'm not certain that this example is formatted how rustfmt would approach it either.

You could also use braced or-patterns when matching with constants, e.g. `std::i32::{MIN | MAX}`, but I don't expect such usage would be as common.

There's some overlap in this idea with the thread "[Bring enum variants in scope for patterns](https://internals.rust-lang.org/t/bring-enum-variants-in-scope-for-patterns/12104)". In my case, you'd still have to repeat that prefix on separate match arms, but I think it has the advantage of being unambiguous syntax.

---

<div class="post-metadata">

**Author:** ![mjbshaw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mjbshaw/32/5103_2.png) [@mjbshaw](https://internals.rust-lang.org/u/mjbshaw)\
**Post date:** [April 20, 2020, 4:54pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/2 "2020-04-20T16:54:50Z")

</div>

FWIW, this is identical to [Alternative syntax for working with enums](https://internals.rust-lang.org/t/alternative-syntax-for-working-with-enums/11717) (which I [linked to](https://internals.rust-lang.org/t/bring-enum-variants-in-scope-for-patterns/12104/9) in the "Bring enum variants in scope for patterns" thread).

---

<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:** [April 20, 2020, 5:03pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/3 "2020-04-20T17:03:17Z")

</div>

Well, that alternative syntax is aiming for much broader application, which is bound to be more controversial and more difficult to implement. They didn't mention patterns AFAICS, but I'll mention the possibility in that thread. Still, I think having this just on patterns would be simple and valuable, and it would be compatible if we later went with that broader idea.

Thinking a little more -- that syntax seems to want an inner scope as if you had `use Enum::*`, but my intention here is that all parts of the braced or-pattern are strictly sharing the prefix. So it would be an error to match a pattern `Enum::{A | B | C | D}` if `Enum::D` does not exist, versus treating this as a sort of scope where `A`, `B`, and `C` are pulled from `Enum` while `D` could resolve to something else.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [April 20, 2020, 5:31pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/4 "2020-04-20T17:31:53Z")

</div>

Just for comparison:

With type-based lookup:

```rust
    | _::NonMutatingUse(_::Inspect)
    | _::MutatingUse(_::Store)
    | _::MutatingUse(_::AsmOutput)
    | _::MutatingUse(_::Borrow)
    | _::MutatingUse(_::AddressOf)
    | _::MutatingUse(_::Projection)
    | _::NonMutatingUse(_::SharedBorrow)
    | _::NonMutatingUse(_::UniqueBorrow)
    | _::NonMutatingUse(_::ShallowBorrow)
    | _::NonMutatingUse(_::AddressOf)
    | _::NonMutatingUse(_::Projection) => {

```

With type-based lookup and or patterns:

```rust
    | _::MutatingUse(
        | _::Store
        | _::AsmOutput
        | _::Borrow
        | _::AddressOf
        | _::Projection,
    )
    | _::NonMutatingUse(
        | _::Inspect
        | _::SharedBorrow
        | _::UniqueBorrow
        | _::ShallowBorrow
        | _::AddressOf
        | _::Projection,
    ) => {

```

With type-based lookup, or patterns, and braced variants:

```rust
    | _::MutatingUse(_::{Store | AsmOutput | Borrow | AddressOf | Projection})
    | _::NonMutatingUse(_::{
        Inspect | SharedBorrow | UniqueBorrow | ShallowBorrow | AddressOf | Projection
    }) => {

```

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [April 21, 2020, 6:26pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/5 "2020-04-21T18:26:06Z")

</div>

Currently accidental use of a variable instead of variant is a non-snake-case style warning and unused var warning. It would be nice if some future edition could elevate it to a proper error.

---

<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:** [April 21, 2020, 6:30pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/6 "2020-04-21T18:30:38Z")

</div>

To be clear, I want `Enum::{A | B | C | D}` to be _exactly_ the same as writing them expanded with the same prefix, `Enum::A | Enum::B | Enum::C | Enum::D`, so there are no accident variables at all.

That also means you could have things like `Enum::{Ident | Struct { .. } | Tuple(..)}`.

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [May 2, 2020, 12:20pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/7 "2020-05-02T12:20:24Z")

</div>

While a concise way to write it is "nice to have", it is another place where there are then two ways to write the same thing, and the benefits then have to be large to warrant a new feature.

It would be consistent in a way, because `use` lines have already been given a similar treatment, and already there that grouping feature does not carry its weight IMO.

I think that bringing the enum variants into scope by some means, for example explicitly 😉 is a good way to improve the code.

---

<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:** [July 31, 2020, 12:22pm UTC](https://internals.rust-lang.org/t/idea-braced-or-patterns-enum-a-b-c/12208/8 "2020-07-31T12:22:29Z")

</div>

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