# Idea: PlacePattern

**URL:** <https://internals.rust-lang.org/t/idea-placepattern/11090>\
**Category:** language design\
**Created:** [October 12, 2019, 6:39am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090 "2019-10-12T06:39:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [October 12, 2019, 6:39am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/1 "2019-10-12T06:39:28Z")

</div>

Motivated by (but not very related to) the issue [https://github.com/rust-lang/rust/issues/65257](https://github.com/rust-lang/rust/issues/65257) .

Introduce a context keyword `place`. The syntax should be

```bnf
PlacePattern :
      place Expression (@ Pattern ) ?

```

where Expression should be a valid place expression. An assignment is arranged to be performed when the binding is successfully.

An example:

```rust
let mut a, b;
let (place a, place b) = (2, 3);

```

---

<div class="post-metadata">

**Author:** ![sinkuu](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sinkuu/32/5819_2.png) [@sinkuu](https://internals.rust-lang.org/u/sinkuu)\
**Post date:** [October 12, 2019, 7:31am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/2 "2019-10-12T07:31:45Z")

</div>

This is more like [https://github.com/rust-lang/rfcs/issues/372](https://github.com/rust-lang/rfcs/issues/372).

---

<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:** [October 12, 2019, 10:17am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/3 "2019-10-12T10:17:27Z")

</div>

I like this idea; an explicit keyword makes the meaning more obvious.

If we want to use an existing keyword, we could use `let (in x, in y) = foo();`, or more verbosely `become`.

---

<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:** [October 12, 2019, 5:51pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/4 "2019-10-12T17:51:15Z")

</div>

Overall I think there's something there but I think we need to dig into the specifics.

> [@josh](#):
>
> or more verbosely `become` .

`in` feels more obvious (and the brevity is desirable) and iirc we reserved `become` for tail calls.

> [@crlf0710](#):
>
> where Expression should be a valid place expression.

Does this include executing derefs as necessary on e.g. `place.field`?

I would very much like to retain patterns as a pure and total fragment of the language so I would like to restrict this to types which are `!Deref` and `!DerefMut` or at least types which morally are `DerefPure` (i.e. `Box<T>` is OK). Moreover, place expressions like `foo.bar().baz` or `foo.await?.bar` would be forbidden as well.

Also, by "valid place expression" I assume this is a semantic distinction rather than a syntactic one. That is, the parser would accept the full expression grammar. Note that this is ambiguous with or-patterns as in:

```rust
let in x | x = 0;

```

may be interpreted as either `in (x | x)` (bit-or) or `(in x) | x`. Ambiguities can usually be resolved by favoring a specific parse and I think the most convenient one would be `in (x | x)` in terms of how libsyntax (`parser/pat.rs` specifically) is structured today (cc @petrochenkov).

This also leads to interesting questions (cc @varkor @arielb1 @pnkfelix)

- What does `(in x) | x` mean?
- What about `A(mut x, in x)`?
- What about `(in x, in x) = (0, 0);`?

---

<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:** [October 12, 2019, 7:55pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/5 "2019-10-12T19:55:18Z")

</div>

If we want to limit place expressions to pure expressions, I think just having a grammar of `In Ident+ % Dot` for place patterns covers everything that would semantically be allowed. That would solve the ambiguity question, I believe, and doesn't unreasonably complicate the grammar.

That said, I'm mildly against making `Box` more special than it already is. I would prefer to preserve the potential of eventually making `Box` just another library type, or at the very least "just" a `#[lang]` item rather than a special kind of type.

---

<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:** [October 12, 2019, 8:14pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/6 "2019-10-12T20:14:15Z")

</div>

> [@CAD97](#):
>
> If we want to limit place expressions to pure expressions, I think just having a grammar of `In Ident+ % Dot` for place patterns covers everything that would semantically be allowed. That would solve the ambiguity question, I believe, and doesn't unreasonably complicate the grammar.

That's not a sufficient condition. You also need to prevent `place.field` from performing a deref in typeck or in match checking. However `Ident+ % Dot` would also be a wholly new grammatical category since, afaik, we have no such syntactic restriction today.

> [@CAD97](#):
>
> That said, I'm mildly against making `Box` more special than it already is. I would prefer to preserve the potential of eventually making `Box` just another library type, or at the very least "just" a `#[lang]` item rather than a special kind of type.

To make `Box<T>` just another library type we would need `DerefPure` which is the same lang item that we would use for the restriction needed here as well.

---

<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:** [October 12, 2019, 10:03pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/7 "2019-10-12T22:03:20Z")

</div>

> [@Centril](#):
>
> This also leads to interesting questions (cc @varkor @arielb1 @pnkfelix)
> 
> - What does `(in x) | x` mean?
> - What about `A(mut x, in x)` ?
> - What about `(in x, in x) = (0, 0);` ?

This is similar to `(x, x) = (0, 0)`: is the "temporality" of patterns defined?

- some people may want to use `(x, x)` as a fallible pattern allowing a structural equality check within a pattern; I personally don't think that such semantics is that clear, and would rather have a keyword or sigil for that (maybe some prefix `=` somewhere?);

- if there were a clear temporality, `let (x, x) = (42, 0);` would create two bindings, with the latter shadowing the former, so that `x` ends up referring to the binding holding `0`. Note that there could / should be lints against this.

Anyways, this is just how I personally would "intuitively" think about this (if it were to work), I am not saying that's how it should work (maybe all these erroring is a better solution).

---

<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:** [October 12, 2019, 10:21pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/8 "2019-10-12T22:21:43Z")

</div>

> [@dhm](#):
>
> Anyways, this is just how I personally would "intuitively" think about this (if it were to work), I am not saying that's how it should work (maybe all these erroring is a better solution).

Overall I think you've captured the "how things fall out from existing language semantics" well. What you didn't treat with was `let (mut x, in x) = (0, 1);`. It seems to me that this would define one binding `x` and then proceed to overwrite it with `1`.

(PS: `let (x, x) = (0, 0);` is an error; this check is defined in [LateResolutionVisitor in rustc\_resolve::late - Rust](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.LateResolutionVisitor.html#method.resolve_pattern_inner) -- hopefully the logic should be readable or I need to make more improvements to it)

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [October 13, 2019, 9:12am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/9 "2019-10-13T09:12:40Z")

</div>

> [@](#):
>
> ```rust
> let mut a, b;
> let (place a, place b) = (2, 3);
> 
> ```

IMO this is unnecessarily mysterious and verbose. It should just be

```rust
(a, b) = (2, 3);

```

like in many other languages.

---

<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:** [October 13, 2019, 9:16am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/10 "2019-10-13T09:16:28Z")

</div>

> [@Centril](#):
>
> - What does `(in x) | x` mean?
> - What about `A(mut x, in x)` ?
> - What about `(in x, in x) = (0, 0);` ?

In all three cases:

`error[E0416]: identifier `x` is bound more than once in the same pattern`

Similarly, I don't see any use case for combining `in` with `|`, so let's just not allow that unless a specific use case arises that makes sense.

---

<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:** [October 13, 2019, 9:20am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/11 "2019-10-13T09:20:23Z")

</div>

> [@comex](#):
>
> IMO this is unnecessarily mysterious and verbose. It should just be
> 
> ```rust
> (a, b) = (2, 3);
> 
> ```
> 
> like in many other languages.

1. Note that the case you quoted uses more verbose syntax (`place`) than later in the thread (`in`).

2. Are you suggesting that arbitrary irrefutable patterns can appear on the LHS of an assignment, and just leaving off the `let` will change them from a new variable to an assignment to an existing variable?

3. `in` would have the additional advantage (or disadvantage) that you could do this in a `match` too.

I can absolutely see the argument for doing this as a compound assignment, as long as we stay far far away from _overloaded_ assignment. If this only works structurally, with patterns, that seems acceptable. I can also see the argument for allowing this in pattern syntax.

---

<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:** [October 13, 2019, 11:23am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/12 "2019-10-13T11:23:37Z")

</div>

> [@josh](#):
>
> `error[E0416]: identifier `x` is bound more than once in the same pattern`

The point of the `ast::PatKind::AssignIn(P<Expr>)` form is to _avoid_ binding an identifier and instead assign to it using the value at the given place the pattern is matching on. So at least that error message does not make sense and we would need to invent another one (_"assigning with an `in` pattern to the identifier `x` bound in the same pattern"_).

To do so, we would need to change [`LateResolutionVisitor::resolve_pattern_inner`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.LateResolutionVisitor.html#method.resolve_pattern_inner) to store the fact that an `in $expr` pattern is writing to something within the same pattern (using `bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>`).

However I don't see a compelling reason to insert additional logic into resolve just because an edge case feels slightly weird if it can be given well-defined semantics and allowing it is easier than banning it (and I believe that's the case at least in `librustc_resolve` and NLL should hopefully just reject any problematic combinations with e.g. `(ref mut x, in x)` (those checks are necessary anyways because NLL should be sound on its own!).

> [@josh](#):
>
> Similarly, I don't see any use case for combining `in` with `|` , so let's just not allow that unless a specific use case arises that makes sense.

Easy:

```rust
let Ok(in x) | Err(in x) = 0;

```

But I also don't think language design should be done by whitelisting the specific parts of a general logic that we like. That just makes for a bunch of ad-hoc rules rather than composability. Rather, there should be compelling and strong reason _not_ to allow composition with or-patterns.

---

<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:** [October 13, 2019, 11:37am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/13 "2019-10-13T11:37:22Z")

</div>

Being able to both update a value and bind a new variable in the same expression is very useful, I have a few state machines where I would love to be able to write

```rust
let (in self.state, done) = match mem::replace(&mut self.state, State::Invalid) {
   ...
}

```

---

<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:** [October 13, 2019, 11:38am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/14 "2019-10-13T11:38:27Z")

</div>

> [@Centril](#):
>
> (PS: `let (x, x) = (0, 0);` is an error; this check is defined in [LateResolutionVisitor in rustc\_resolve::late - Rust](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.LateResolutionVisitor.html#method.resolve_pattern_inner) -- hopefully the logic should be readable or I need to make more improvements to it)

Yep, the code is quite clear, good job (I don't usually look at `rustc` code since I haven't decided to go and make the dive, so in the meantime I remain at a qualitative level of comments 😅)

> [@Centril](#):
>
> Overall I think you've captured the "how things fall out from existing language semantics" well. What you didn't treat with was `let (mut x, in x) = (0, 1);` . It seems to me that this would define one binding `x` and then proceed to overwrite it with `1` .

Yes, that's what I wanted to say but somehow I got diverted by the `(in x) | x` case

* * *

> [@josh](#):
>
> Similarly, I don't see any use case for combining `in` with `|` , so let's just not allow that unless a specific use case arises that makes sense.

I could imagine, given:

```rust
fn mb_foo (_: bool) -> Option<Foo>;
const DEFAULT_FOO: Foo;

```

writing the following pattern:

```rust
let mut foo: Foo = DEFAULT_FOO:
if let Some(in foo) = mb_foo(true) {}
if let Some(in foo) = mb_foo(false) {}

```

as

```rust
let mut foo = DEFAULT_FOO;
match (mb_foo(true), mb_foo(false)) {
    | (Some(in foo), Some(in foo))
    | (_ , Some(in foo))
    | (Some(in foo), _ )
    | _
    => {}
}

```

- and with nested `|` patterns (if that could ever be possible):

The example may look contrived, and the usage of patterns may not be as readable as the more "explicitely" imperative way, but who knows, it may come in handy.

---

<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:** [October 13, 2019, 11:46am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/15 "2019-10-13T11:46:22Z")

</div>

> [@dhm](#):
>
> and with nested `|` patterns (if that could ever be possible):

It's already being implemented 😁

> <https://github.com/rust-lang/rust/issues/54883>
>
> This is a tracking issue for the RFC "Or patterns, i.e \`Foo(Bar(x) | Baz(x))\`" (…rust-lang/rfcs#2535).
> 
> This issue also tracks the changes in rust-lang/rfcs#2175 and rust-lang/rfcs#2530 since RFC 2535 subsume those.
> 
> \*\*Status:\*\*
> 
> \- the feature was stabilized in https://github.com/rust-lang/rust/pull/79278 though we are still working on implementing the edition migration (#83318)
> 
> \*\*Steps:\*\*
> 
> \- \[x\] Implement the RFC (cc @rust-lang/compiler -- can anyone write up mentoring instructions?)
> \- \[x\] Polish the implementation
> \- \[x\] Dogfood or-patterns in the compiler and standard library (done in #71220, #71221, and #71231)
> \- \[x\] Accumulate good test coverage
> \- \[x\] Adjust documentation (\[see instructions on forge\]\[doc-guide\])
> \- \[x\] Stabilization PR (\[see instructions on forge\]\[stabilization-guide\])
> 
> \[stabilization-guide\]: https://forge.rust-lang.org/stabilization-guide.html
> \[doc-guide\]: https://forge.rust-lang.org/stabilization-guide.html#updating-documentation
> 
> \*\*Unresolved questions:\*\*
> 
> \- \[\] Should we allow \`top\_pat\` or \`pat\<allow\_top\_alt\>\` in \`inferrable\_param\` such that closures permit \`|Ok(x) | Err(x)|\` without first wrapping in parenthesis?
> 
> We defer this decision to stabilization as it may depend on experimentation. Our current inclination is to keep the RFC as-is because the ambiguity is not just for the compiler; for humans, it is likely also ambiguous and thus harder to read.
> 
> This also applies to functions which, although do not look as ambiguous, benefit from better consistency with closures. With respect to function arguments there's also the issue that not disambiguating with parenthesis makes it less clear whether the type ascription applies to the or-pattern as a whole or just the last alternative.
> 
> \- \[\] Should the \`pat\` macro fragment specifier match \`top\_pat\` in different
> Rust editions or should it match \`pat\<no\_top\_alt\>\` as currently specified? We defer such decisions to stabilization because it depends on the outcome of crater runs to see what the extent of the breakage would be.
> 
> The benefit of avoiding \`pat\<no\_top\_alt\>\` in as many places as possible would both be grammatical consistency and fewer surprises for uses. The drawbacks would be possible ambiguity or backtracking for closures and breakage for macros.
> 
> \*\*Implementation history:\*\*
> 
> \- On 2019-08-18, basic parsing landed in https://github.com/rust-lang/rust/pull/61708 landed which was written by @dlrobertson and reviewed by @varkor, @Centril, @petrochenkov, @matthewjasper, and @alexreg.
> 
> \- On 2019-08-27, full and polished parsing landed in https://github.com/rust-lang/rust/pull/63693 which was written by @Centril and reviewed by @estebank.
> 
> \- On 2019-08-29, a typo in #63693 was fixed in https://github.com/rust-lang/rust/pull/63938 which was written by @tshepang and reviewed by @Centril.
> 
> \- On 2019-09-05, https://github.com/rust-lang/rust/pull/64128, written by @Centril and reviewed by @davidtwco, landed. The PR fixed issue https://github.com/rust-lang/rust/issues/64106 where the compiler would spuriously emit \`unused\_parens\` warnings on:
> 
> - \`ref? mut? x @ (p\_0 | ... | p\_n)\`
> - \`box (p\_0 | ... | p\_n)\`
> - \`& mut? (p\_0 | ... | p\_n)\`
> - \`|(p\_0 | ... | p\_n)| $expr\`
> - \`fn foo((p\_0 | ... | p\_n): $type)\`
> 
> \- On 2019-09-06, https://github.com/rust-lang/rust/pull/64111, written by @Centril and reviewed by @petrochenkov, landed. The PR fixed the late-resolution behavior of or-patterns in nested positions including the already-bound check and binding-consistency check. Moreover, the AST now uniformly uses \`ast::PatKind::Or\` and has no special means of representing or-patterns at the top level.
> 
> \- On 2019-09-25, https://github.com/rust-lang/rust/pull/64508, written by @Centril and reviewed by @matthewjasper, @varkor, and @nikomatsakis, landed. The PR adjusted the HIR and HAIR to consistently use or-patterns at the top & nested levels. Moreover, liveness, typeck, and dead\_code analyses were adjusted also. Notably, The PR did however not adjust exhaustiveness checking. Tangentially, https://github.com/rust-lang/rust/pull/64271, landed 2019-09-12, written by @Centril and reviewed by @estebank, adjusted \`check\_match\` diagnostics logic to be better prepared for or-patterns.
> 
> \- On 2019-09-29, https://github.com/rust-lang/rust/pull/64887, written by @Centril and reviewed by @estebank, landed. The PR improved parser recovery for trailing \`|\` in pattern contexts.
> 
> \- On 2019-10-27, https://github.com/rust-lang/rust/pull/65874, written by @Nadrieril and reviewed by @varkor, @arielb1, @nnethercote, and @Centril, landed. The PR refactored the usefulness/exhaustiveness algorithm in match checking. This laid the foundation upon which exhaustiveness checking for or-patterns was later initially implemented in https://github.com/rust-lang/rust/pull/66612.
> 
> \- On 2019-11-23, https://github.com/rust-lang/rust/pull/66639, written by @Centril and reviewed by @petrochenkov, landed. In this follow-up to https://github.com/rust-lang/rust/pull/64111, the resolve logic for adding fresh bindings was simplified and re-written in a more declarative fashion.
> 
> \- On 2019-12-01, https://github.com/rust-lang/rust/pull/66612, written by @Nadrieril and reviewed by @varkor, @Centril, and @matthewjasper, landed. In this follow-up to https://github.com/rust-lang/rust/pull/65874, an initial implementation of exhaustiveness / usefulness checking for or-patterns was implemented.
> 
> \- On 2019-12-03, https://github.com/rust-lang/rust/pull/66967, written by @Nadrieril and reviewed by @varkor and @Centril, landed. In this follow-up to https://github.com/rust-lang/rust/pull/66612, the top-level hack for or-patterns in exhaustiveness checking was removed, making or-patterns truly first-class in match checking.
> 
> \- On 2019-12-21, https://github.com/rust-lang/rust/pull/67428, written by @Centril and reviewed by @matthewjasper, landed. This PR adjusted regionck's \`resolve\_local::is\_binding\_pat\` such that the \`P&\` grammar includes or-patterns.
> 
> \- On 2019-12-22, https://github.com/rust-lang/rust/pull/67439, written by @Centril and reviewed by @matthewjasper, landed. Among other things, this PR simplified HAIR lowering of or-patterns a smidgen.
> 
> \- On 2019-12-26, https://github.com/rust-lang/rust/pull/67592, written by @matthewjasper and reviewed by @Centril, landed. This PR did some preparatory cleanups in MIR lowering of \`match\` expressions before the MIR level support for or-patterns is added. Moreover, the PR gated or-patterns in const contexts under \`const\_if\_match\`.
> 
> \- On 2020-02-04, https://github.com/rust-lang/rust/pull/67668, written by @matthewjasper and reviewed by @pnkfelix, @Centril, @nagisa, @varkor, and @eddyb, landed. The PR finally added the support for or-patterns in MIR building (dynamic semantics, borrow checking, ...). Now, nested or-patterns can actually be used on nightly with \`#!\[feature(or\_patterns)\]\`.
> 
> \- On 2020-02-06, https://github.com/rust-lang/rust/pull/68842, written by @Centril and reviewed by @estebank landed. The PR added a regression test for an issue fixed by https://github.com/rust-lang/rust/pull/67668.
> 
> \- On 2020-02-15, https://github.com/rust-lang/rust/pull/68856, written by @Centril and reviewed by @matthewjasper landed. The PR polished the type checking of patterns with respect to default binding modes. In relation to or-patterns, the PR declared that or-patterns are pass-through (\`AdjustMode::Pass\`) in terms of default binding modes. This was already the case in the implementation (and already stabilized for top level or-patterns) but the PR removed the FIXME that left the question open.
> 
> \- On 2020-02-28, 2020-03-08, and 2020-03-08, PRs https://github.com/rust-lang/rust/pull/69452, https://github.com/rust-lang/rust/pull/69599, and https://github.com/rust-lang/rust/pull/69687 landed. These were written by @Centril and were reviewed by @estebank, @davidtwco, and @estebank respectively. All PRs tweaked and improved diagnostics wrt. or-patterns.
> 
> \- On 2020-03-08, https://github.com/rust-lang/rust/pull/69690, written by @thekuom and reviewed by @Centril, landed. The relevant part of the PR added tests for the dynamic semantics of or-patterns combined with \`x @ y\` patterns, \`box\` patterns, and slice patterns.
> 
> \- On 2020-03-10, https://github.com/rust-lang/rust/pull/69817, written by @thekuom and reviewed by @Centril, landed. The PR added borrow checker tests in combination with other pattern features.
> 
> \- On 2020-03-11, https://github.com/rust-lang/rust/pull/69891, written by @Centril and reviewed by @varkor and @Nadrieril, landed. The PR fixed a bug (https://github.com/rust-lang/rust/issues/69875) in exhaustiveness checking where the patterns \`0 | (1 | 2)\` and \`x @ 0 | x @ (1 | 2)\` would result in an ICE.
> 
> \- On 2020-03-27, https://github.com/rust-lang/rust/pull/70413, written by @AminArria and reviewed by @varkor, @Nadrieril, and @Centril, landed. The PR fixed https://github.com/rust-lang/rust/issues/70372, a false positive in the linting behavior of \`unreachable\_patterns\` when combining or-patterns, bindings, and guards.
> 
> \- On 2020-04-13, https://github.com/rust-lang/rust/pull/67766, written by @sapir and reviewed by @matthewjasper, landed. The PR fixed https://github.com/rust-lang/rust/issues/67691, a bug in the \`unused\_variables\` lint pertaining to or-patterns.

---

<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:** [October 13, 2019, 1:02pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/16 "2019-10-13T13:02:24Z")

</div>

> [@Centril](#):
>
> So at least that error message does not make sense and we would need to invent another one ( _"assigning with an `in` pattern to the identifier `x` bound in the same pattern"_ ).

Sure, the message and ID would need changing.

> [@Centril](#):
>
> However I don't see a compelling reason to insert additional logic into resolve just because an edge case feels slightly weird if it can be given well-defined semantics and allowing it is easier than banning it

I'm not suggesting that the edge case "feels slightly weird", and I have no problem with allowing both `in` assignments and non-`in` bindings in the same `let`. I'm suggesting that allowing both _to the same name_ seems excessively error-prone.

We should absolutely define an ordering semantic for patterns, so that things like `in x, in x.y` can work reliably and deterministically. I do, however, think `in x, in x` deserves _at least_ a warn-by-default lint, and `mut x, in x` deserves an error-by-default lint.

> [@Centril](#):
>
> let Ok(in x) | Err(in x) = 0;

That's a compelling argument, thank you.

I started to say that this seems to suggest it's acceptable if both sides assign to the same names, but then this use case occurred to me:

`let Some(in lastval) | _ = func()`

And I can very easily imagine myself using that, in preference to:

`let lastval = func().unwrap_or(lastval)`

or:

`if let Some(v) = func() { lastval = v }`

---

<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:** [October 13, 2019, 1:58pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/17 "2019-10-13T13:58:23Z")

</div>

> [@josh](#):
>
> I do, however, think `in x, in x` deserves _at least_ a warn-by-default lint, and `mut x, in x` deserves an error-by-default lint.

I'm fine with lints for weird edge cases since they are not a part of the language spec and they don't complicate resolve (they can be implemented as a separate pass).

> [@josh](#):
>
> We should absolutely define an ordering semantic for patterns, so that things like `in x, in x.y` can work reliably and deterministically.

I wonder if that would actually expose the pattern matching / pattern lowering algorithm too much and possibly have negative consequences re. being able to reorder for optimization purposes. cc @matthewjasper

---

<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:** [October 13, 2019, 3:08pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/18 "2019-10-13T15:08:30Z")

</div>

> [@Centril](#):
>
> I wonder if that would actually expose the pattern matching / pattern lowering algorithm too much and possibly have negative consequences re. being able to reorder for optimization purposes

Not necessarily. Pattern match into new locations, assign those locations into the existing locations in order, and let the optimizer coalesce the locations if it can.

---

<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:** [October 13, 2019, 4:30pm UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/19 "2019-10-13T16:30:24Z")

</div>

I think it should be allowed to assign to a variable that was created or changed in the same pattern. Example:

```rust
let (mut x, Ok(in x) | _) = it;

```

This is equivalent to

```rust
let mut x = it.0;
if let Ok(ok) = it.1 {
    x = ok;
}

```

In cases like this, the assignments should be performed left-to-right. That's the obvious solution, because expressions are evaluated left-to-right as well, and patterns in a `match` are also matched from left to right.

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [October 14, 2019, 1:32am UTC](https://internals.rust-lang.org/t/idea-placepattern/11090/20 "2019-10-14T01:32:16Z")

</div>

> [@Nemo157](#):
>
> Being able to both update a value and bind a new variable in the same expression is very useful, I have a few state machines where I would love to be able to write
> 
> ```rust
> let (in self.state, done) = match mem::replace(&mut self.state, State::Invalid) {
> ...
> }
> 
> ```

In principle this could be

```rust
(self.state, let done) = ...

```

That _would_ imply a broader merging of the expression and pattern syntax.

[Next page](https://internals.rust-lang.org/t/idea-placepattern/11090.md?page=2)
