What #[derive(AsRef)] generates

Deriving AsRef generates one or more implementations of AsRef, each corresponding to one of the fields of the decorated type. This allows types which contain some T to be passed anywhere that an AsRef<T> is accepted.

1 Newtypes and Structs with One Field

When AsRef is derived for a newtype or struct with one field, a single implementation is generated to expose the underlying field.

#[derive(AsRef)]
struct MyWrapper(String);

Generates:

impl AsRef<String> for MyWrapper {
    fn as_ref(&self) -> &String {
        &self.0
    }
}

It’s also possible to use the #[as_ref(forward)] attribute to forward to the as_ref implementation of the field. So here SigleFieldForward implements all AsRef for all types that Vec<i32> implements AsRef for.

#[derive(AsRef)]
#[as_ref(forward)]
struct SingleFieldForward(Vec<i32>);

fn main() {
    let item = SingleFieldForward(vec![]);
    let _: &[i32] = (&item).as_ref();
}

This generates:

impl<__AsRefT: ?::core::marker::Sized> ::core::convert::AsRef<__AsRefT> for SingleFieldForward
where
    Vec<i32>: ::core::convert::AsRef<__AsRefT>,
{
    #[inline]
    fn as_ref(&self) -> &__AsRefT {
        <Vec<i32> as ::core::convert::AsRef<__AsRefT>>::as_ref(&self.0)
    }
}

2 Structs with Multiple Fields

When AsRef is derived for a struct with more than one field (including tuple structs), you must also mark one or more fields with the #[as_ref] attribute. An implementation will be generated for each indicated field. You can also exclude a specific field by using #[as_ref(ignore)].

#[derive(AsRef)]
struct MyWrapper {
    #[as_ref]
    name: String,
    #[as_ref]
    num: i32,
    valid: bool,
}

Generates:

impl AsRef<String> for MyWrapper {
    fn as_ref(&self) -> &String {
        &self.name
    }
}

impl AsRef<i32> for MyWrapper {
    fn as_ref(&self) -> &i32 {
        &self.num
    }
}

Note that AsRef<T> may only be implemented once for any given type T. This means any attempt to mark more than one field of the same type with #[as_ref] will result in a compilation error.

// Error! Conflicting implementations of AsRef<String>
#[derive(AsRef)]
struct MyWrapper {
    #[as_ref]
    str1: String,
    #[as_ref]
    str2: String,
}

3 Enums

Deriving AsRef for enums is not supported.