我正在围绕 C 库编写一个 Rust 包装器,同时我试图利用中提到的“可空指针优化”The Book https://doc.rust-lang.org/1.30.0/book/first-edition/ffi.html#the-nullable-pointer-optimization,但我找不到好的转换方法Option<&T>
to *const T
and Option<&mut T>
to *mut T
就像他们所描述的那样。
我真正想要的是能够打电话Some(&foo) as *const _
。不幸的是,这不起作用,所以我能想到的下一个最好的事情是Option<T>
这使我能够打电话Some(&foo).as_ptr()
。以下代码是该特征的工作定义和实现:
use std::ptr;
trait AsPtr<T> {
fn as_ptr(&self) -> *const T;
}
impl<'a, T> AsPtr<T> for Option<&'a T> {
fn as_ptr(&self) -> *const T {
match *self {
Some(val) => val as *const _,
None => ptr::null(),
}
}
}
现在我可以打电话了Some(&foo).as_ptr()
得到一个*const _
,我希望能够打电话Some(&mut foo).as_ptr()
得到一个*mut _
。以下是我为此创建的新特征:
trait AsMutPtr<T> {
fn as_mut_ptr(&self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&self) -> *mut T {
match *self {
Some(val) => val as *mut _,
None => ptr::null_mut(),
}
}
}
问题是,AsMutPtr
特征不会编译。当我尝试时,出现以下错误:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:22:15
|
22 | match *self {
| ^^^^^
| |
| cannot move out of borrowed content
| help: consider removing the `*`: `self`
23 | Some(val) => val as *mut _,
| --- data moved here
|
note: move occurs because `val` has type `&mut T`, which does not implement the `Copy` trait
--> src/lib.rs:23:18
|
23 | Some(val) => val as *mut _,
| ^^^
我不明白这两个特征之间发生了什么变化导致它失败——我没想到添加mut
会有很大的不同。我尝试添加一个ref
,但这只会导致不同的错误,而且我也不希望需要它。
为什么不AsMutPtr
特质工作?