rust syntax: reason for &mut foo instead of &foo in rust when foo declared mut
Question
For a c routine like
MPI_Comm_rank(MPI_Comm comm, int *rank);
the rust foreign function interface could be declared like this:
extern crate libc;
use libc::{c_int};
#[link(name = "mpi")]
extern {
fn MPI_Comm_rank(mpi_comm: c_int,
rank: *mut c_int);
}
I call the binding like this, which works, but left me puzzled about syntax:
pub static MPI_COMM_WORLD : libc::c_int = 0x44000000;
fn main() {
let mut rank: c_int = 999999;
/* but why '&mut rank' and not simply '&rank' ? */
unsafe {MPI_Comm_rank(MPI_COMM_WORLD, &mut rank)}
}
I originally tried
unsafe {MPI_Comm_rank(MPI_COMM_WORLD, &rank)}
but this gives a compiler error:
mismatched types: expected `*mut i32` but found `&i32` (values differ in mutability)
I declared 'rank' as mut, so what gives?
Solution
You’re conflating two completely distinct features.
let mut x;
makes a mutable binding x
, allowing you to modify what x is bound to (x = 42
) and for non-reference types to modify its contents (x.y = 42
). It does not control the mutability of the target of references.
This is different from the type of references you’re dealing with.
&mut T
is a mutable reference and can be coerced to*mut T
.&T
is an immutable reference can be coerced to*const T
.
As the function you are calling wants *mut T
, you must pass it a *mut T
or a &mut T
; *const T
or &T
will not do.
To be sure, you can only take a mutable reference to mutable data, so let x = 42; &mut x
doesn’t work as it needs let mut x
instead of let x
, but that’s still entirely distinct and is a part of Rust’s rules about mutability.
OTHER TIPS
Your function expects *mut c_int
pointer (a mutable raw pointer), and you need to use &mut
operator to obtain it. However, you can only take &mut
pointer to mut
variables, hence you need to declare rank
variable as mut rank
.
If your function expected *const c_int
pointer, you would be able to use &
, but this is not the case.