Why does the following code not issue any warnings that the mut
in foo
is superfluous?
fn main() {
let mut x = X { x: 10 };
foo(&mut x);
}
fn foo(x: &mut X) {
println!("{}", x.x);
}
struct X {
x: usize,
}
Why does the following code not issue any warnings that the mut
in foo
is superfluous?
fn main() {
let mut x = X { x: 10 };
foo(&mut x);
}
fn foo(x: &mut X) {
println!("{}", x.x);
}
struct X {
x: usize,
}
I would say because this allows you to later change foo
's implementation if you want to. Declaring foo
as fn foo(x: &mut X)
means that foo
can modify *x
if it wants to.
I'd say it's not superfluous - that mut
is part of the function signature and therefore part of your API.
In general, the compiler can't tell whether the mut
in an &mut T
parameter is superfluous because we doing something like let f: fn(&mut X) = foo;
or passing it to a closure which expects some F: Fn(&mut X)
. Telling the user they should remove the mut
could break code.
I guess it could be a good candidate for a "pedantic" clippy lint, though.
I want to point out something that trips people up sometimes; you may already know this.
The mutability of a binding is basically just a lint. It is not part of the type of the variable at all; it's not a property that values carry around with them -- it's a lint on how you can use a specific binding.
// `hw` is a `String` with a non-mutable binding
let hw = "Hello".to_string();
// `hw` is still a `String` but we've rebound it as mutable
let mut hw = hw;
// The underlying value is not immutable, as we own it
hw.push_str(", World!");
println!("{hw}");
References are a different story. &i32
and &mut i32
are two different types. You can't turn a &i32
into a &mut i32
and they behave differently in other deep ways.
The compiler doesn't know your intent with foo
. For all it knows, there might be a reason that it only makes sense with exclusive access. Certainly as a human you can tell that it's not important in this case, but imagine if there was an AtomicUsize
in there — the exclusive reference could mean that you can do a non-synchronized read since the type system says that's ok in a way that wouldn't be if it took a shared reference.
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.