Macro AsRef
macro_rules! AsRef { ... }
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.
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.
# use AsRef;
#
;
Generates:
# ;
It's also possible to use the #[as_ref(forward)] attribute to forward
to the as_ref implementation of the field. So here SingleFieldForward
implements all AsRef for all types that Vec<i32> implements AsRef for.
# use AsRef;
#
;
let item = SingleFieldForward;
let _: & = .as_ref;
This generates code equivalent to:
# ;
Specifying concrete types, to derive impls for, is also supported via
#[as_ref(<types>)] attribute. These types can include both the type
of the field itself, and types for which the field type implements AsRef.
# use AsRef;
#
;
let item = Types;
let _: &str = item.as_ref;
let _: & = item.as_ref;
let _: &String = item.as_ref;
WARNING: When either the field type, or the specified conversion type, contains generic parameters, they are considered as the same type only if are named string-equally, otherwise are assumed as different types even when represent the same type in fact (type aliases, for example).
# use AsRef; # // generates `impl<T: AsRef<i32>> AsRef<i32> for Generic<T>` ; // generates `impl<T> AsRef<T> for Transparent<T>` ; // #[as_ref(RenamedVec<T>)] // not supported, as types are not named string-equally ; type RenamedVec<T> = ; // generates `impl AsRef<RenamedString> for Bar`, ; // as generics are not involved type RenamedString = String;
Generating code like this is not supported:
;
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.
# use AsRef;
#
Generates:
#
Tuples (not supported)
Only conversions that use a single field are possible with this derive.
Something like this wouldn't work, due to the nature of the AsRef trait
itself:
# use AsRef
#
If you need to convert into a tuple of references, consider using the
Into derive with #[into(ref)].
Skipping
Or vice versa: you can exclude a specific field by using #[as_ref(skip)] (or
#[as_ref(ignore)]). Then, implementations will be generated for non-indicated fields.
# use AsRef;
#
Generates:
#
Coherence
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.
# use AsRef;
#
// Error! Conflicting implementations of AsRef<String>
Similarly, if some field is annotated with #[as_ref(forward)], no other
field can be marked.
# use AsRef;
#
// Error! Conflicting implementations of `AsRef<i32>`
// note: upstream crates may add a new impl of trait `AsRef<i32>`
// for type `String` in future versions
Multiple forwarded impls with different concrete types, however, can be used.
# use AsRef;
#
let item = Types ;
let _: &str = item.as_ref;
let _: & = item.as_ref;
Enums
Deriving AsRef for enums is not supported.