2016-07-19 108 views
9

Ho alcuni tratti che (dopo aver tolto le funzioni e alcuni parametri gonfiare) assomigliano:esecuzione nidificati Tratti

trait Foo { } 
trait Boo { } 
trait Bar<T: Foo> { } 
trait Baz { } 

Se U implementa Bar<T> per qualche T attuazione FooeU implementa Boo, allora si è in grado derivare un'implementazione di Baz per U. Tuttavia, non ero in grado di scrivere codice Rust valido facendo questo.

alcuni tentativi sono stati:

impl<T: Foo, U: Bar<T> + Boo> Baz for U { } 

che dà

error: the type parameter T is not constrained by the impl trait, self type, or predicates [E0207]

mentre

impl<U: Bar<T> + Boo> Baz for U { } 

cede

error: type name T is undefined or not in scope [E0412]

Potrebbe uno/come si può farlo in Rust (stabile) (si spera senza alcun invio dinamico)?

Edit: Alcune persone hanno suggerito ad alcune domande simili per i quali vi erano essenzialmente due approcci (e trovo entrambi inadatti per la mia situazione):

  1. Uso dei tipi di associati. Non voglio farlo perché voglio tenere traccia di T, ad es. Voglio scrivere alcune funzioni che hanno una firma come fn bla<T: Foo, U: Bar<T>, V: Bar<T>>() dove voglio sapere che U e V implementano Bar<T> per lo stessoT. (Oppure esiste un modo per farlo con i tipi associati?)
  2. Utilizzare una sorta di wrapping inserendo U e T in una struttura. Non voglio usarlo neanche perché ho diversi livelli di tali "dipendenze dei tratti", quindi avvolgere le cose in ogni livello farebbe ingrossare molto il codice.

Quindi la domanda aggiornata sarebbe: Esiste una soluzione a questo problema senza l'utilizzo di tipi o wrapper associati?

risposta

7

Puoi farlo facendo T un tipo associato:

trait Foo { } 
trait Boo { } 
trait Bar { 
    type T: Foo; 
} 
trait Baz { } 

impl<U: Bar + Boo> Baz for U 
    // this where clause is not necessary (this bound is already true) 
    // where U::T: Foo 
{ } 

I don't want to do this because I want to keep track of T , e.g. I want to write some functions which have a signature like fn bla<T: Foo, U: Bar<T>, V: Bar<T>>() where I want to know that U and V implement Bar<T> for the sameT . (Or is there way of doing this with associated types?)

Sì, lo si può fare con i tipi di associati:

fn bla<U: Bar, V: Bar<T = U::T>>() { }