Стратегии разрешения конфликтующих реализаций черт при использовании обобщений в Rust? - PullRequest
0 голосов
/ 20 сентября 2019

Каковы некоторые общие стратегии для разрешения реализаций черт при использовании обобщений в 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 }                        
    }
}  

, но это менее общее, чем хотелось бы.Существует ли общая стратегия построения таких признаков или функций?

...