The type of the variable a is &mut Foo, i.e. a itself is a mutable reference to a Foo object. Mutating a would mean to make it point to a different Foo object. Since a itself is immutable, you can't change what a is pointing to, and your code does not disprove this in any way.
Your code simply passes the &mut Foo as the self parameter to mut_ref() – note that the type of self is also &mut Foo. No auto-dereferencing is happening – a already has exactly the type that is epxected for the self parameter. However, we are triggering an implicit reborrow here, so the call is equivalent to Foo::mut_ref(&mut *a). This implicit reborrow isn't what's making the code work, though – moving the mutable reference out of a would also be perfectly allowed.
While a is immutable as a variable, it's still a mutable reference, so you can mutate the Foo object it's pointing to (assuming Foo had any state to mutate). You can't obtain a mutable reference to a, which would need to have the type &mut &mut Foo.