Here is a toy example:
#[derive(Debug)]
struct Int {
v: i32,
}
#[derive(Debug)]
struct Double {
v: f64,
}
impl Into<Double> for Int {
fn into(self) -> Double {
Double {
v: f64::from(self.v),
}
}
}
This works, but really I want to implement Into<Double>
for &Int
and &mut Int
. This doesn't work:
impl<T> Into<Double> for T
where
T: AsRef<Int>,
{
fn into(self) -> Double {
Double {
v: f64::from(self.as_ref().v),
}
}
}
because trait Into
is not defined in my crate:
error[E0119]: conflicting implementations of trait `std::convert::Into<Double>`:
--> src/main.rs:19:1
|
19 | / impl<T> Into<Double> for T
20 | | where
21 | | T: AsRef<Int>,
22 | | {
... |
27 | | }
28 | | }
| |_^
|
= note: conflicting implementation in crate `core`:
- impl<T, U> std::convert::Into<U> for T
where U: std::convert::From<T>;
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
--> src/main.rs:19:1
|
19 | / impl<T> Into<Double> for T
20 | | where
21 | | T: AsRef<Int>,
22 | | {
... |
27 | | }
28 | | }
| |_^
How should I implement Into<Double>
for &Int
and &mut Int
,
without code duplication like:
impl<'a> Into<Double> for &'a Int {
impl<'a> Into<Double> for &'a mut Int {
You can do what you want, by implementing From
instead of its friend Into
:
impl<T> From<T> for Double
where
T: AsRef<Int>,
{
fn from(i: T) -> Self {
Double {
v: f64::from(i.as_ref().v),
}
}
}
This way we avoid implementing a trait for a generic parameter (the for T
part) which is disallowed by orphan rules. From
and Into
are linked together with this awesome blanket impl:
impl<T, U> Into<U> for T
where
U: From<T>,
However, AsRef
is not the trait you are looking for here (I think). Borrow
might be more fitting in your situation:
impl<T> From<T> for Double
where
T: Borrow<Int>,
{
fn from(i: T) -> Self {
Double {
v: f64::from(i.borrow().v),
}
}
}
This way, the conversion is possible for Int
, &Int
and &mut Int
:
fn foo<T: Into<Double>>(_: T) {}
foo(Int { v: 3 });
foo(&Int { v: 3 });
foo(&mut Int { v: 3 });
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With