summaryrefslogtreecommitdiffstats
path: root/third_party/rust/derive_more-impl/doc/as_ref.md
blob: 112ba15a1c68d347fcdd6d5463f07753fb45a8a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 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.

```rust
# use derive_more::AsRef;
#
#[derive(AsRef)]
struct MyWrapper(String);
```

Generates:

```rust
# struct MyWrapper(String);
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 `SingleFieldForward`
implements all `AsRef` for all types that `Vec<i32>` implements `AsRef` for.

```rust
# use derive_more::AsRef;
#
#[derive(AsRef)]
#[as_ref(forward)]
struct SingleFieldForward(Vec<i32>);

let item = SingleFieldForward(vec![]);
let _: &[i32] = (&item).as_ref();
```

This generates:

```rust
# struct SingleFieldForward(Vec<i32>);
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)
    }
}
```




## 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)]`.

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

Generates:

```rust
# struct MyWrapper {
#     name: String,
#     num: i32,
#     valid: bool,
# }
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.

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




## Enums

Deriving `AsRef` for enums is not supported.