Why the compiler didn't catch this one? (pointer vs lifetime)


consider this:

pub trait AsStr {
    fn as_str(&self) -> &str;

    fn to_utf16(&self) -> Vec<u16> {

    fn to_pcwstr(&self) -> PCWSTR {

In to_pcwstr It seems that the Vec created by to_utf16() doesn't live long enough for the pointer created by as_ptr() to be valid.

I'm encountering non systematic failure calling some Windows API and I've tracked down the cause to this.

Did I found a bug or (more likely), what am I missing?

The lifetime of pointers is not checked by the compiler.

The docs for as_ptr mention this:

The caller must ensure that the vector outlives the pointer this function returns, or else it will end up pointing to garbage.

1 Like

In Rust, a str always stores UTF-8 data. Therefore, whatever crate provides the str::to_utf16() function must translate it into a new buffer. As a consequence, you cannot return a reference to the to_utf16() output from to_pcwstr(); you'll have to provide some kind of free function:

pub fn slice_as_pcwstr(slice: &[u16]) -> PCWSTR {

pub fn example(s: impl AsStr) {
    let buf: Vec<u8> = s.to_utf16();
    let pcwstr: PCWSTR = slice_as_pcwstr(&buf);

Silly me, thanks!

For things such as pointers which are not lifetime-tracked, I personally recommend using a scoped / callback pattern, so that programmers can easily view the area / scope of usability of the pointer:

    fn with_pcwstr<R>(&self, scope: impl FnOnce(PCWSTR) -> R) -> R {

so as to:

    let buf: Vec<u8> = s.to_utf16();
    buf.with_pcwstr(|pcwstr| {
    }) // <- `pcwstr` valid until here; beyond this point it's a dangling pointer
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.