Каковы некоторые общие стратегии для разрешения реализаций черт при использовании обобщений в Rust?В качестве надуманного примера рассмотрим следующий код, который позволяет преобразовывать примитивные типы в структуру:
// External libraries
use std::fmt::Debug;
// Create some structure that we can convert from and into
#[derive(Debug)]
struct MyStruct <T> {
val : T,
}
// Convert from a value
trait ConvertFrom <T>
where
Self : Sized
{
fn from(t : T) -> Self;
}
// Convert T into a T
impl <T> ConvertFrom <T> for T {
fn from(t : T) -> Self {
t
}
}
// Convert f32 into f64
impl ConvertFrom <f32> for f64 {
fn from(t : f32) -> Self {
t as f64
}
}
// Convert T into a MyStruct <U>
impl <T,U> ConvertFrom <T> for MyStruct <U>
where
U : ConvertFrom <T>
{
fn from(t : T) -> Self {
MyStruct{ val : ConvertFrom::<T>::from(t) }
}
}
// Test our conversion
fn foo01 <T> () -> ()
where
T : ConvertFrom <f32> + Debug
{
let y01 : T = ConvertFrom::<f32>::from(1.2_f32);
println!("{:?}",y01);
}
fn main() {
foo01::<MyStruct<f32>>();
foo01::<f64>();
}
Это дает ошибку компилятора:
error[E0119]: conflicting implementations of trait `ConvertFrom<MyStruct<_>>` for type `MyStruct<_>`:
--> src/test03.rs:33:1
|
19 | impl <T> ConvertFrom <T> for T {
| ------------------------------ first implementation here
...
33 | / impl <T,U> ConvertFrom <T> for MyStruct <U>
34 | | where
35 | | U : ConvertFrom <T>
36 | | {
... |
39 | | }
40 | | }
| |_^ conflicting implementation for `MyStruct<_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.
error: Could not compile `rust_from_to`
Это имеет смысл, есть двусмысленностьмежду преобразованием идентичности из T->T
и из T->MyStruct <U>
, поскольку T
может быть чем-то вроде MyStruct<f32>
, а U
может быть f32
.Что мне не понятно, так это то, как ее решить, и rustc --explain E0119
не дал больших намеков.Проблема в том, что я хотел бы иметь функцию преобразования, которая преобразует T
в MyStruct <U>
всякий раз, когда T
преобразуется в U
.Я могу сделать эту работу, если T=U
с чертой:
// Convert T into a MyStruct <T>
impl <T> ConvertFrom <T> for MyStruct <T> {
fn from(t : T) -> Self {
MyStruct{ val : t }
}
}
, но это менее общее, чем хотелось бы.Существует ли общая стратегия построения таких признаков или функций?