as_ and _ref: reference conversions
as is a prefix for methods that convert references. ref is a suffix (but
prefer as.)
as methods borrow out the primary piece of data contained in &self.
Most commonly return references, but can also return a custom borrowing type or an unsafe pointer.
#![allow(unused)] fn main() { impl<T> Rc<T> { fn as_ptr(&self) -> *const T; // Very common on container types, see how it's also on Option. fn as_ref(&self) -> &T; } impl<T> Option<T> { fn as_ref(&self) -> Option<&T>; // Slices can be empty! So this is 0 or 1 elements. fn as_slice(&self) -> &[T]; } impl OwnedFd { // Covered later. fn as_fd(&'a self) -> BorrowedFd<'a>; } }
-
Method that returns a borrow of the primary piece of contained data.
-
The borrowing relationship is most often straightforward: the return value is a reference that borrows
self. -
Borrowing can also be subtle, and merely implied.
-
The returned value could be a custom borrowing type, fore example,
BorrowedFdborrowsOwnedFdthrough an explicit lifetime. -
We cover custom borrowing types later in this deep dive, PhantomData: OwnedFd & BorrowedFd.
-
The returned value could borrow
selfonly logically, for example,as_ptr()methods return an unsafe pointer. The borrow checker does not track borrowing for pointers.
-
-
The type implementing an “as” method should contain one primary piece of data that is being borrowed out.
- The “as” naming convention does not work if the data type is an aggregate of many fields without an obvious primary one. Think about the call site:
#![allow(unused)] fn main() { my_vec.as_ptr() // OK my_person.as_first_name() // does not read right, don't use "as_" my_person.first_name() // OK }- If you want to have two getters that you need to distinguish, one that
returns first name by value, and another one that returns it by reference,
use
_refsuffix:
#![allow(unused)] fn main() { impl Person { fn first_name(&self) -> String fn first_name_ref() -> &str fn first_name_mut() -> &mut String } }