Skip to content

Commit 3ede65c

Browse files
committed
Mention #[derive(Into)] and move From impl direction discussion from unresolved questions to Rationale and alternatives
1 parent 0223650 commit 3ede65c

File tree

1 file changed

+22
-18
lines changed

1 file changed

+22
-18
lines changed

text/3809-derive-from.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,24 @@ The `derive_more` crate allows opting into the blanket implementation using a cu
220220

221221
[^blanket]: Noted [here](https://internals.rust-lang.org/t/pre-rfc-derive-from-for-newtypes/22567/6).
222222

223+
## Direction of the `From` impl
224+
In theory, someone could be confused if this code:
225+
```rust
226+
#[derive(From)]
227+
struct Newtype(Inner);
228+
```
229+
generates this impl:
230+
```rust
231+
impl From<Inner> for Newtype { ... }
232+
```
233+
or this impl:
234+
```rust
235+
impl From<Newtype> for Inner { ... }
236+
```
237+
However, `impl From<Inner> for Newtype` is consistent with all other standard traits that can currently be derived, as they all generate code in the form of `impl Trait for Type`. It should thus not be very surprising that `#[derive(From)]` provides the impl for the outer type, not the inner type. This will also be clearly documented.
238+
239+
Generating the other direction of the impl is best left as a separate feature, which is briefly discussed in [Future possibilities][future-possibilities].
240+
223241
# Prior art
224242
[prior-art]: #prior-art
225243

@@ -275,24 +293,6 @@ The `Default` trait actually shares a similarity with `From`, in that they are b
275293
# Unresolved questions
276294
[unresolved-questions]: #unresolved-questions
277295

278-
## Direction of the `From` impl
279-
In theory, someone could be confused if this code:
280-
```rust
281-
#[derive(From)]
282-
struct Newtype(Inner);
283-
```
284-
generates this impl:
285-
```rust
286-
impl From<Inner> for Newtype { ... }
287-
```
288-
or this impl:
289-
```rust
290-
impl From<Newtype> for Inner { ... }
291-
```
292-
However, `impl From<Inner> for Newtype` is consistent with all other standard traits that can currently be derived, as they all generate code in the form of `impl Trait for Type`. It should thus not be very surprising that `#[derive(From)]` provides the impl for the outer type, not the inner type.
293-
294-
This concern was presented [here](https://internals.rust-lang.org/t/pre-rfc-derive-from-for-newtypes/22567/2), with a suggestion to properly document this behavior. The [Guide-level explanation](#guide-level-explanation) discusses this topic.
295-
296296
## Enum support
297297
Should we also support enums? The design space there is more complex than for structs. For example, `derive_more` generates a separate `From` impl for each enum variant by default, which means that the individual variants must not contain the same inner type, otherwise an impl conflict happens:
298298

@@ -360,6 +360,10 @@ impl From<u16> for Port {
360360

361361
This is similar to how [RFC#3107](https://rust-lang.github.io/rfcs/3107-derive-default-enum.html) extended the deriving of the `Default` trait using the `#[default]` attribute.
362362

363+
## Deriving From in the other direction
364+
365+
It is also quite useful to generate `From<InnerType> for Struct`, i.e. generating `From` in the other direction. This could be done in the future using e.g. `#[derive(Into)]`.
366+
363367
## Enum support
364368
We could add support for enums in a similar way, where users could mark the variant that should be constructed using `#[from]`.
365369

0 commit comments

Comments
 (0)