Ensure Generic Type Parameters Aren't The Same Type

I'm trying to implement a generic type and for ease of use i want to implement From for it when the internal types can be converted between each other:

impl<T, U> From<Vec2<T>> for Vec2<U> where U: From<T> {
	fn from(v: Vec2<T>) -> Vec2<U> {
		Vec2 ([
			U::from(v.0[0]),
			U::from(v.0[1]),
		])
	}
}

However, to the compiler both type arguments may refer to the same type, causing a conflict with this implementation of From in core:

impl<T> From<T> for T;

How do I indicate to the compiler that T and U may never be the same type?

Please note that adding custom marker traits is a solution i'd like to avoid, since this implementation should Simply Work for the user of the type, including with builtin types.

As far as I know, this is not currently possible. I think it was supposed to be enabled by specialization, but that’s been a bumpier feature to implement than originally thought.

In this sort of situation, I usually end up either implementing my own trait or just writing an inherent generic method:

trait IntoVec2<T> {
    fn into_vec2(self)->Vec2<T>;
}

impl<T,U> IntoVec2<T> for Vec2<U> where U: Into<T> {
    /* ... */
}

/* or... */

impl<T> Vec2<T> {
    pub fn convert<U>(self)->Vec2<U> where T: Into<U> {
        /* ... */
    }
}
1 Like

I guess I'll leave it out then and implement it specifically when the need arises?

Maybe having a reflexive implementation of From was not the smart choice the authors of core thought it was, considering that it makes a very large set of generic implementations of From impossible to have.

I think it was more premature than anything else. Once there’s some mechanism to either opt-out or override it, it makes a lot of sense. Those mechanisms just didn’t materialize as quickly as they expected.

1 Like