Is there a more ergonomic way to dereference NonNull

I'm doing a lot of unsafe code interacting with raw pointers.

In many contexts I can create a NonNull<T>. I prefer these types because they document the invariant the pointer is not null.

However, if I need to do many pointer field access you have to call as_ptr before dereferencing the NonNull. Is there a more ergonomic way to do this?

For example having lines like:

(*(*client_session.as_ptr()).curw).window)

make we want to just forgo using NonNull on client_session even if the return type of the function where I got client_session is NonNull.

it's not improved much in this case, but you can use NonNull::as_ref() (and as_mut()) instead of the deref operator:

client_session.as_ref().curw.as_ref().window

I think method syntax is more pleasant to use over the * oprator, because the operator is a prefix, while methods can be easility chained together.

yeah, that's a good idea, but I'm not sure if it's valid for me to create a &mut or reference in this context.

unless you are dealing with unitialized memory (e.g. the dereferenced value has not been fully initialized or has been partially moved), it's mostly the same whether using the * operator or using as_ref()/as_mut() [1]. if you want to move the dereferenced value, neither * nor a reference allows you do it anyway.


  1. often times, using the * operator would result implicitly reborrows of the value ↩︎

1 Like

Unfortunately I'm iteratively refactoring a c codebase, so sometimes I am dealing with unintialized memory. Once I've refactored enough of it to be sure all uses are initialized and there are never multiple instances of exclusive references I will try to switch things over to rust references.

well, that's a bummer. in such situation, I would probably only use NonNull at API bounaries, and get a raw pointer from it as soon as possible:

fn foo(p: NonNull<Bar>) {
   let p = p.as_ptr();
   //...
}

for struct fields, if they are private fields, I would just use raw pointers (while the constructor probably takes a NonNull), but for public fields, I would stick to NonNull (or Option<NonNull>, depending on the sementics).

if theres too much of it to really bother me, the best I can do is to use a short name macro. but I think it probably won't help much in terms of ergonomics, it may even be worse in terms of readability (unless postfix marco syntax became reality, which should solve both the ergonomics and readablity issue), but other than that, I don't know how else can I reduce the typing.

macro_rules! x {
    ($p:exp) => {  (*NonNull::as_ptr($p))  }
}
(*(*client_session.as_ptr()).curw).window;
(*x!(client_session).curw).window;
1 Like

You may be looking for this:

and

1 Like

If it were, you could just newtype NonNull and implement Deref[Mut] (or abuse Index[Mut]<LocalZst> on NonNull<T>).