Is there an implemented convertion from Option<&T> to *const T?

Hello.

The following code fails to compile:

fn main() {
    let a: Option<u16> = Some(123);
    let b: *const u16 = a.as_ref().into();
}

With the following error:

error[E0277]: the trait bound `*const u16: From<Option<&u16>>` is not satisfied

 --> src/main.rs:3:36
  |
3 |     let b: *const u16 = a.as_ref().into();
  |                                    ^^^^ the trait `From<Option<&u16>>` is not implemented for `*const u16`
  |
  = help: the following other types implement trait `From<T>`:
            <u16 as From<bool>>
            <u16 as From<u8>>
            <u16 as From<NonZeroU16>>
  = note: required for `Option<&u16>` to implement `Into<*const u16>`

Some time ago I think I saw in some rust code a transparent convertion from Option<&T> to *const T, which was used for passing a reference to a ffi function accepting a pointer. I might be wrong though.

Is there a way to convert Option<&T> to *const T? Is there such convertion in the standard library:

impl<T> From<Option<&T>> for *const T {
    fn from(value: Option<&T>) -> Self {
        match value {
            Some(v) => v as *const T,
            None => core::ptr::null(),
        }
    }
}

Using Option<&T> as an argument in a function that's actually called with a raw pointer will just work. The pointer is transmitted into an option.

Similarly, the transmute function will also do this conversion for you.

2 Likes

Do I use it correctly?

fn func(p: *const u8) {}

fn main() {
    let a: Option<u8> = Some(123);
    func(a.as_ref());
}

The code fails to compile:

error[E0308]: mismatched types
 --> src/main.rs:5:10
  |
5 |     func(a.as_ref());
  |     ---- ^^^^^^^^^^ expected `*const u8`, found `Option<&u8>`
  |     |
  |     arguments to this function are incorrect
  |
  = note: expected raw pointer `*const u8`
                    found enum `Option<&u8>`

you declare the FFI function type signature using the rust equivalence of a raw pointer. for example:

in C:

void foo(int const *ptr) {
    //...
}

in rust:

extern "C" {
    fn foo(p: Option<&i32>);
}

see the "nullable pointer optimization" section of the nomicon book:

note the book shows an example of a "nullable" function pointer, but data pointers are the same too.

4 Likes