What #[derive(From)] generates

The point of deriving this type is that it makes it easy to create a new instance of the type by using the .into() method on the value(s) that it should contain. This is done by implementing the From trait for the type that is passed to the derive. For structs with a single field you can call .into() on the desired content itself after deriving From. For structs that have multiple fields .into() needs to be called on a tuple containing the desired content for each field. For enums .into() works for each variant as if they were structs. This way the variant can not only be initialized, but also be chosen based on the type that .into() is called on.

1 Example usage


// Allow converting from i32
#[derive(From, PartialEq)]
struct MyInt(i32);

// Forward from call to the field, so allow converting
// from anything that can be converted into an i64 (so most integers)
#[derive(From, PartialEq)]
#[from(forward)]
struct MyInt64(i64);

// You can ignore a variant
#[derive(From, PartialEq)]
enum MyEnum {
    SmallInt(i32),
    NamedBigInt { int: i64 },
    #[from(ignore)]
    NoFromImpl(i64),
}

// Or explicitly annotate the once you need
#[derive(From, PartialEq)]
enum MyEnum2 {
    #[from]
    SmallInt(i32),
    #[from]
    NamedBigInt { int: i64 },
    NoFromImpl(i64),
}

// And even specify additional conversions for them
#[derive(From, PartialEq)]
enum MyEnum3 {
    #[from(types(i8))]
    SmallInt(i32),
    #[from(types(i16))]
    NamedBigInt { int: i64 },
    NoFromImpl(i64),
}

fn main() {
    assert!(MyInt(2) == 2.into());
    assert!(MyInt64(6) == 6u8.into());
    assert!(MyEnum::SmallInt(123) == 123i32.into());
    assert!(MyEnum::SmallInt(123) != 123i64.into());
    assert!(MyEnum::NamedBigInt{int: 123} == 123i64.into());
    assert!(MyEnum3::SmallInt(123) == 123i8.into());
    assert!(MyEnum3::NamedBigInt{int: 123} == 123i16.into());
}

2 Tuple structs

When deriving for a tuple struct with a single field (i.e. a newtype) like this:

#[derive(From)]
struct MyInt(i32);

Code like this will be generated:

impl ::core::convert::From<(i32)> for MyInt {
    fn from(original: (i32)) -> MyInt {
        MyInt(original)
    }
}

The behaviour is a bit different when deriving for a struct with multiple fields. For instance when deriving for a tuple struct with two fields like this:

#[derive(From)]
struct MyInts(i32, i32);

Code like this will be generated:

impl ::core::convert::From<(i32, i32)> for MyInts {
    fn from(original: (i32, i32)) -> MyInts {
        MyInts(original.0, original.1)
    }
}

3 Regular structs

For regular structs almost the same code is generated as for tuple structs except in the way the field values are assigned to the new struct. When deriving for a regular struct with a single field like this:

#[derive(From)]
struct Point1D {
    x: i32,
}

Code like this will be generated:

impl ::core::convert::From<(i32)> for Point1D {
    fn from(original: (i32)) -> Point1D {
        Point1D { x: original }
    }
}

The behaviour is a bit different when deriving for a struct with multiple fields. For instance when deriving for a tuple struct with two fields like this:

#[derive(From)]
struct Point2D {
    x: i32,
    y: i32,
}

Code like this will be generated:

impl ::core::convert::From<(i32, i32)> for Point2D {
    fn from(original: (i32, i32)) -> Point2D {
        Point2D {
            x: original.0,
            y: original.1,
        }
    }
}

4 Enums

When deriving From for enums a new impl will be generated for each of its variants. If you don’t want this for a variant you can put the #[from(ignore)] attribute on that variant. One case where this can be useful is when two variants would overlap. For instance when deriving From for the following enum:

#[derive(From)]
enum MixedInts {
    SmallInt(i32),
    NamedBigInt { int: i64 },
    TwoSmallInts(i32, i32),
    NamedBigInts { x: i64, y: i64 },
    #[from(ignore)]
    Unsigned(u32),
    NamedUnsigned { x: u32 },
}

Code like this will be generated:

impl ::core::convert::From<(i32)> for MixedInts {
    #[allow(unused_variables)]
    #[inline]
    fn from(original: (i32)) -> MixedInts {
        MixedInts::SmallInt(original)
    }
}

impl ::core::convert::From<(i64)> for MixedInts {
    #[allow(unused_variables)]
    #[inline]
    fn from(original: (i64)) -> MixedInts {
        MixedInts::NamedBigInt { int: original }
    }
}

impl ::core::convert::From<(i32, i32)> for MixedInts {
    #[allow(unused_variables)]
    #[inline]
    fn from(original: (i32, i32)) -> MixedInts {
        MixedInts::TwoSmallInts(original.0, original.1)
    }
}

impl ::core::convert::From<(i64, i64)> for MixedInts {
    #[allow(unused_variables)]
    #[inline]
    fn from(original: (i64, i64)) -> MixedInts {
        MixedInts::NamedBigInts {
            x: original.0,
            y: original.1,
        }
    }
}

impl ::core::convert::From<(u32)> for MixedInts {
    #[allow(unused_variables)]
    #[inline]
    fn from(original: (u32)) -> MixedInts {
        MixedInts::NamedUnsigned { x: original }
    }
}

Without the #[from(ignore)] on Unsigned, no impl would be generated for Unsigned and NamedUnsigned. The reason for this is that it would be impossible for the compiler to know which implementation to choose, since they would both implement From<u32>.