# Idea: \`move x\`, in analogue with \`ref x\`

**URL:** <https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168>\
**Category:** language design\
**Created:** [August 10, 2018, 12:02am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168 "2018-08-10T00:02:33Z")\
**Posts on this page:** 10\
**Page:** 1

<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:** [August 10, 2018, 12:02am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/1 "2018-08-10T00:02:33Z")

</div>

I brought this up on Discord and it seems well-received enough that I’d like to get some opinions on it.

I propose introducing a new production to the pattern grammar: `move $pat`, with the following semantics:

```rust
match &Foo(0) {
    Foo(x) => { // secretly Foo(ref x)
        // x: &i32, created by the usual projection
    }
}

match &Foo(0) {
    Foo(move x) => { 
        // x: i32, created by deref (note that i32: Copy, so this 
        // isn't the *best* example)
    }
}

```

Formally, it acts as a dual to `ref`; before match ergonomics, this “move” pattern context was the default, but this is now dependent on the matched expression’s type. I’m proposing this pattern to be able to inform the compiler _which_ mode you’d like, rather than allowing it to be inferred as `ref` by mistake. While I’ve been told that "`ref` is on the way out", I think having explicit restructuring modes is valuable, even if they’re rarely used (the only use of `move` is move-into closures, which are similarly rare).

I actually didn’t think of this because of match ergonomics, but from a discussion on how rustc should unify incomplete types in ascribed patterns. I’d like to hear whether this would solve any of the common complains about match ergonomics (I haven’t had time to come up with too many examples).

---

<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:** [August 10, 2018, 12:18am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/2 "2018-08-10T00:18:36Z")

</div>

This actually would have saved me a bit of time a few days ago.

I had a match where the whole thing was behind a reference and the correct solution to my compile error was to put a `&` in front of the whole pattern, such that the inner binding was by-move. (IIRC it was a copy type, and one that was being used multiple times so dereferencing at the use site was ugly.)

However, what I first attempted to do was to stick a `&` in front of the binding to de-`ref` it (which would work if it were a reference in pre-binding-modes). This did not work and threw a different error that did not help me.

I think the most common point of complaint against match ergonomics is in something like `let Struct { a, b } = make_struct;`, however; would a `move` unref be allowed before these bindings to enforce that these are by-move?

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [August 10, 2018, 12:22am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/3 "2018-08-10T00:22:22Z")

</div>

This has come up a few times, e.g. on the [match ergonomics tracking issue](https://github.com/rust-lang/rust/issues/42640). A similar feature would be to permit `&` patterns on non-reference values when in ref binding mode, aligning with the existing behavior of `&` patterns. This is something existing users tend to reach for intuitively- @Boscop, @nikomatsakis, and myself in the tracking issue, @CAD97 here, etc.

And as I mentioned [at the end of that thread](https://github.com/rust-lang/rust/issues/42640#issuecomment-408507651), we may actually want both of these. `move` seems to fit the mental model implied by match ergonomics (“a `&T` is just a `T` with fewer permissions”), while `&` fits the mental model implied by older match behavior (“a `&T` is a pointer to a `T`" or alternatively "`&` is part of the structure of a type”).

We seem to want to support both of these mental models in _several_ places, not just match ergonomics, as they both make sense in various contexts.

---

<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:** [August 10, 2018, 12:28am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/4 "2018-08-10T00:28:22Z")

</div>

I'm not surprised this isn't a novel idea!

> [@rpjohnst](#):
>
> A similar feature would be to permit `&` patterns on non-reference values when in ref binding mode

Same semantics? That seems like a curious way to spell it, and not what I'd have reached for... I think that the semantics of `ref` and `&` are, to this day, a bit muddy in my head.

> [@rpjohnst](#):
>
> We seem to want to support both of these mental models in _several_ places, not just match ergonomics, as they both make sense in various contexts.

I'm curious what those places are. I'd never quite thought of "`&T` is a weaker `T`", but I suppose it makes sense in the scenario of "I pick this type apart with restructuring".

---

<div class="post-metadata">

**Author:** ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)\
**Post date:** [August 10, 2018, 12:28am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/5 "2018-08-10T00:28:36Z")

</div>

> [@mcy](#):
>
> While I’ve been told that " `ref` is on the way out"

Was this by someone in an official position?

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [August 10, 2018, 12:39am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/6 "2018-08-10T00:39:53Z")

</div>

> [@mcy](#):
>
> Same semantics? That seems like a curious way to spell it, and not what I’d have reached for… I think that the semantics of `ref` and `&` are, to this day, a bit muddy in my head.

Yes, same semantics. To explain why, you can think of `&T` in much the same way as you would think of `Box<T>` or even just some `struct Foo(T)`- as a "containing" type that contributes to a value's structure.

Construction and pattern matching syntax match, so just as you construct a `Foo` via `Foo(some_t)` and destructure it via `Foo(some_t)`, you construct a `&T` via `&some_t` and destructure it via `&some_t`. On both sides, `some_t` is a `T`.

This can be confusing if you've not internalized it, which is part of the motivation for match ergonomics as well as statements like "`ref` is on the way out." (And yes, @phaylon, this has been said by people on the lang team, as an expression of the intent to find something better.)

> [@mcy](#):
>
> I’m curious what those places are. I’d never quite thought of " `&T` is a weaker `T` ", but I suppose it makes sense in the scenario of “I pick this type apart with restructuring”.

Autoderef and autoref apply this logic to method call syntax. For what it's worth, nikomatsakis is usually the one I hear this from.

---

<div class="post-metadata">

**Author:** ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)\
**Post date:** [August 10, 2018, 12:46am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/7 "2018-08-10T00:46:20Z")

</div>

> [@rpjohnst](#):
>
> (And yes, @phaylon, this has been said by people on the lang team, as an expression of the intent to find something better.)

Well, I do hope the same capabilities will still be available.

---

<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:** [August 10, 2018, 1:00am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/8 "2018-08-10T01:00:41Z")

</div>

> [@phaylon](#):
>
> Was this by someone in an official position?

I believe @mcy was paraphrasing me from our Discord conversation. I want to clarify that what I meant by this is that I believe `ref` will be used much less frequently given match ergonomics. I have no plans to propose deprecating `ref` and I think I would be opposed to it at this stage.

* * *

Regarding the idea of having `move`, it seems like filling a missing piece of the puzzle in a natural way. In particular, given type ascription, you can say:

```rust
match expr {
    Some(move x: &usize) => { println!("{:?}", x); }
}

```

and you will _know_ that `expr : &Option<&usize>` and that `expr : &Option<usize>` is not possible.

Furthermore, consider:

```rust
trait Foo { 
    fn new() -> Self;
}

impl Foo for &'static Option<usize> {
    fn new() -> Self { &Some(0) }
}

impl Foo for &'static Option<&'static usize> {
    fn new() -> Self { &Some(&1) }
}

fn main() {
    let x: &_ = Foo::new();
    if let Some(x) = x {
        let x: &usize = x;
        // Prints 0.
        println!("{}", x);
    }
}

```

In this case, the dynamic semantics of printing `x` is directly affected by which mode you pick. By having `move`, we could ensure that `1` gets printed.

Having `move` also strikes me as advantageous for teaching by showing an in-language desugaring for match ergonomics.

All in all, I believe `move $pat` is an idea worth considering.

---

<div class="post-metadata">

**Author:** ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)\
**Post date:** [August 10, 2018, 1:06am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/9 "2018-08-10T01:06:10Z")

</div>

> [@Centril](#):
>
> I believe @drXor was paraphrasing me from our Discord conversation. I want to clarify that what I meant by this is that I believe `ref` will be used much less frequently given match ergonomics. I have no plans to propose deprecating `ref` and I think I would be opposed to it at this stage.

Excellent, thanks. Just wanted to know if I should watch out for RFCs.

---

<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:** [March 25, 2019, 8:30am UTC](https://internals.rust-lang.org/t/idea-move-x-in-analogue-with-ref-x/8168/10 "2019-03-25T08:30:40Z")

</div>

Closed on March 25, 2019, 8:30am UTC

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