Search code examples
rusttraits

Why is mut self in Trait Implementation allowed when Trait definition only uses self?


I'm working on the traits2.rs exercise in rustlings and am confused on Rust's syntax for traits. I have the following working solution (that compiles and passes the test, I'm using Rust 1.50):

trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for Vec<String> {
    fn append_bar(mut self) -> Self {
        self.push("Bar".into());
        self
    }
}

However, I'm confused that, while the trait definition is fn append_bar(self) -> Self, my implementation for it is fn append_bar(mut self) -> Self, which has an additional mut on the signature. Why is this allowed?


Solution

  • The Reference for associated functions says:

    The identifier is the name of the function. The generics, parameter list, return type, and where clause of the associated function must be the same as the associated function declarations's.

    Matching the parameter list means matching the number and types of parameters. The Reference for functions explains the structure of a parameter:

    FunctionParam : OuterAttribute* Pattern : Type

    Where Pattern in this case is an Identifier Pattern:

    IdentifierPattern : ref? mut? IDENTIFIER (@ Pattern ) ?

    This induces that mut is part of the pattern, not part of the type which is the reason why mut (unlike &mut) is not part of the Signature at all, so thats why you are allowed to use it.

    It's important to note here that mut self vs self is not the same as &self vs &mut self. As with other parameters, the mut in mut self is just an annotation on the binding of self, not the type.

    The caller does not need to know about it: you move the value one way or the other, so it's up to the callee if it needs to mutate it or not.