About mutable binding

Hi guys,
I can declare a mutable binding like this

struct U;
let mut u : &U;
u = &U;   // first binding
u = &U;   // second binding

but I can't mimic this in nested situation. help me please.

struct U;
struct Y {
   u : U,
}
let Y{mut u} : &Y;
u = &U;   // not work , expected struct `U`, found `&U`

In your second example, the type of u is U and not &U. To change it:

Playground

struct U;
struct Y<'a> {
       u : &'a U,
}
let Y{mut u} : &Y;
u = &U;
u = &U;
1 Like

Both of these are mutable bindings.

In the first case you are creating a mutable binding with type &U, in other words you are binding u to a reference to a U. This means that you can modify the referenced value or reassign u to any other reference to U.

In the second case you are trying creating a mutable binding to the u field within a &Y. This binding has type U not type &U. This means that you can modify the value or reassign u to any other U but you can't assign a &U to u because it is the wrong type.

struct U;
struct Y {
    u: U,
}
let Y { mut u }: &Y;
u = U;
u = U;
1 Like

but the u is not a borrower , it's the owner , this is different from the first case.

but this changed the type of Y.

And the u field is of type U which is different from the first case. The u field is owned by Y, so Y must always hold an owned value.

It might help if you were to give a more real world example of what you are trying to achieve?

You can:

    // Saying directly what you mean
    let Y { ref u }: Y;
    u = &U;
    // The nesting binding can't be mutable initially as far as
    // I'm aware, but you can always "reset" the mutability of
    // owned variables
    let mut u = u;
    u = &U;

Or:

    // Here, "match ergonomics" make this the same as above
    // because the left side is not a reference pattern and the
    // right side is a reference... and there's nothing to
    // "reset the binding mode"
    let Y { u }: &Y;
    u = &U;
    let mut u = u;
    u = &U;

Or (not recommended):

    // This is the same "match ergonomics" case as before; the `ref`
    // is just ignored.  The mix of styles can cause confusion.
    let Y { ref u }: &Y;
    u = &U;
    let mut u = u;
    u = &U;

What's going on with your original example then? This:

// `mut` resets the binding mode in a weird way so that
// this is the same as `let Y { mut u }: Y;`.  So what
// you get is a mutable binding with type `U`.
let Y {mut u} : &Y;
u = &U;   // not work , expected struct `U`, found `&U

The mut resetting binding isn't part of the RFC and is considered a bug.


And finally note that this:

let Y { ref mut u } : Y;

(or any equivalent variation) is not what you want, because that creates a &mut U binding, not a mut &U binding. Hence the need for let mut u = u; later on if you want to reassign u.

1 Like

@quinedot thanks for your elaborated explanation. This is a good chance for me to learn more about pattern.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.