I'm writing a Rust wrapper around a C library and while doing so I'm trying to take advantage of the "nullable pointer optimization" mentioned in The Book, but I can't find a good way to convert Option<&T>
to *const T
and Option<&mut T>
to *mut T
like what they're describing.
What I really want is to be able to call Some(&foo) as *const _
. Unfortunately that doesn't work, so the next best thing I can think of is a trait on Option<T>
that enables me to call Some(&foo).as_ptr()
. The following code is a working definition and implementation for that trait:
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(),
}
}
}
Now that I can call Some(&foo).as_ptr()
to get a *const _
, I want to be able to call Some(&mut foo).as_ptr()
to get a *mut _
. The following is the new trait I made to do this:
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(),
}
}
}
The problem is, the AsMutPtr
trait won't compile. When I try, I get the following error:
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 _,
| ^^^
I don't see what changed between the two traits that causes it to fail — I didn't think adding mut
would make that big a difference. I tried adding a ref
, but that just causes a different error, and I wouldn't expect to need that anyway.
Why doesn't the AsMutPtr
trait work?