Support `mut &self` Syntax

We can write fn method(&self, mut a: i32) but can't write fn method(mut &self, a: i32). However, there is a workaround fn method(mut self: &Self, a: i32).

Supporting mut &self and mut &mut self seems to keep consistency.

Why would you want to do this?

2 Likes

This is a compiled code.

use std::fmt;
enum List {
    Cons(i32, Box<List>),
    Nil,
}

impl fmt::Display for List {
    fn fmt(mut self: &Self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[")?;
        while let List::Cons(item, tail) = self {
            write!(f, "{}, ", item)?;
            self = tail;
        }
        write!(f, "Nil]")
    }
}

fn main() {
    let mut list = List::Cons(1, Box::new(List::Nil));
    println!("{}", list);
}

I think self should remain the instance the method was called on. You can easily write that code with let mut current = self;.

1 Like

And now self can be reassigned. Should restrict or relax the usage maybe.

I think the current state of affairs is good enough. Reassigning self doesn't come up that often, so we don't need to cater to it that well and using mut self: &Self is good enough for such a niche use. On a less important note, I find mut &self to be confusing and ugly. Confusing, because mut is only ever applied to identifiers or self, never anything more than that.

5 Likes

I would tend to agree, although fwiw I wanted mut &self just the other day in the compiler (https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc/ty/util.rs.html#1010-1016 and a similar peel_drop_temps which @ekuber is introducing).

I think this is the key point; we decided that we weren't going to support pat ::= ... | "mut" pat ; and so mut &self becomes sorta weird in that light.

1 Like

Agree. Also note that this code runs.

struct Struct(i32);
impl Struct {
    // `mut self` is quite common
    fn method(mut self) {
        // `self` reassigned
        self = Struct(self.0);
    }
}

And note that mut is before an identifier or self and nothing else