Let’s consider the following function:

use std::ptr::NonNull;fn transform<T>(option: &Option<NonNull<T>>) -> Option<&T> {    option.map(|x| unsafe { x.as_ref() })}

The function transform takes an Option<NonNull<T>> as input, and converts the inner pointer to an immutable reference &T if possible. The method NonNull::as_ref() is marked unsafe so we need an unsafe block. The snippet causes an compilation error:

error[E0515]: cannot return value referencing function parameter `x` --> src/main.rs:6:29  |6 |     option.map(|x| unsafe { x.as_ref() })  |                             -^^^^^^^^^  |                             |  |                             returns a value referencing data owned by the current function  | `x` is borrowed here

This is a common mistake when transforming Option s. To figure out the problem, we may try to take apart the signature and see how the value flows:

fn Option::map<T, F>(self, f: F) -> Option<&T>    where F: FnOnce(NonNull<T>) -> Option<&T>{}// which implies:fn __closure<T>(x: NonNull<T>) -> &T {}unsafe fn NonNull::as_ref<T, 'a>(&'a self) -> &'a T {}

where __closure denotes the closure Option::map takes.

Note that Option::map is a self-consuming method. During the calling, option is destructed, and the internal value with type NonNull<T> flows into __closure . The closure, however, consumes its argument as well. Consequently x would have a lifetime trapped in the closure. This is what “data owned by the current function” in the error message means.

Now take a look into the closure. Inside we call NonNull::as_ref() to convert a pointer into a reference, which assumes the pointer should live as long as the reference returned. However, the implication could not be satisfied, since x the pointer lives only within the closure, but the reference would be passed out of the closure. The compiler complains for the lifetime mismatch.

One can always employ Option::as_ref() as a solution. The function has a signature as below:

fn Option::as_ref<T>(&self) -> Option<&T> {}

Calling .as_ref() on an Option<T> instance, say x , will return another Option with type Option<&T> , say ref_x , which holds the reference to the inner value of x . It’s worth noting that .as_ref() takes x by reference, so no consuming happens here. Now we can perform .map() or .unwrap() on ref_x to extract the internal &T , and call non-consuming methods on it (e.g., NonNull::as_ref ). ref_x will still be dropped after that, but it does not matter, since all it have is a reference.

We can correct our code like this:

fn transform<T>(option: &Option<NonNull<T>>) -> Option<&T> {    option        .as_ref()  // Note here        .map(|x| unsafe { x.as_ref() })}