錆びた構文:foo が mut を宣言したときに Rust で &foo の代わりに &mut foo が使用される理由
質問
次のような C ルーチンの場合
MPI_Comm_rank(MPI_Comm comm, int *rank);
Rust の外部関数インターフェイスは次のように宣言できます。
extern crate libc;
use libc::{c_int};
#[link(name = "mpi")]
extern {
fn MPI_Comm_rank(mpi_comm: c_int,
rank: *mut c_int);
}
バインディングを次のように呼び出します。これは機能しますが、構文については困惑しました。
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)}
}
もともと試してみたのですが
unsafe {MPI_Comm_rank(MPI_COMM_WORLD, &rank)}
しかし、これではコンパイラエラーが発生します。
mismatched types: expected `*mut i32` but found `&i32` (values differ in mutability)
「ランク」を mut として宣言しましたが、何が得られるでしょうか?
解決
2 つの完全に異なる機能を混同しています。
let mut x;
変更可能なバインディングを作成します x
, 、x のバインド先を変更できるようになります (x = 42
) および非参照型の場合はその内容を変更します (x.y = 42
)。の可変性は制御しません。 目標 参考文献の。
これは、扱っている参照の種類とは異なります。
&mut T
は変更可能な参照であり、強制的に適用できます。*mut T
.&T
は不変参照です。強制的に適用できます。*const T
.
呼び出している関数が必要とするように *mut T
, 、それを渡す必要があります *mut T
または &mut T
; *const T
または &T
しません。
確かに、変更可能なデータへの変更可能な参照しか取得できません。 let x = 42; &mut x
必要どおりに機能しない let mut x
の代わりに let x
, しかし、それは依然として完全に異なり、可変性に関する Rust のルールの一部です。
他のヒント
あなたの関数は*mut c_int
ポインタ(可変の生ポインタ)を想定しており、&mut
演算子を使用して入手する必要があります。ただし、&mut
変数へのmut
ポインタを実行することができます。したがって、rank
変数をmut rank
として宣言する必要があります。
関数が*const c_int
ポインタを予期している場合は、&
を使用することができますが、これはそうではありません。