2017-03-05 4 views
2

Tenir compte de ces deux traits:Pourquoi ne puis-je pas ajouter une implante de couverture sur un trait avec un paramètre de type?

pub trait Foo { 
    fn new(arg: u32) -> Self; 
} 

pub trait Bar<P>: Foo { 
    fn with_parameter(arg: u32, parameter: P) -> Self; 
} 

Je voudrais ajouter les impl couverture:

impl<T: Bar<P>, P: Default> Foo for T { 
    fn new(arg: u32) -> Self { 
     Self::with_parameter(arg, P::default()) 
    } 
} 

Mais je reçois l'erreur du compilateur:

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

Je pense que je reçois ce erreur parce que je suis en train de violer les règles de cohérence des traits, mais je ne comprends pas exactement quelle règle cela pourrait briser. Pourquoi ce modèle n'est-il pas autorisé? Et, plus important encore, puis-je réaliser ce que je veux sans avoir une erreur?

Répondre

4

Le problème est qu'un seul type pourrait implémenter Bar<P> pour plusieurs valeurs de P. Si vous aviez une structure Baz qui a implémenté Bar<i32> et Bar<String>, quel type devez Foo::new utiliser pour P?

La seule solution est de s'assurer qu'un seul type ne peut pas implémenter Bar plus d'une fois (si ce n'est pas ce que vous voulez, alors vous avez une faille dans votre conception!). Pour ce faire, nous devons remplacer le paramètre de type P par un type associé.

pub trait Bar: Foo { 
    type Parameter; 

    fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self; 
} 

impl<T> Foo for T 
    where T: Bar, T::Parameter: Default 
{ 
    fn new(arg: u32) -> Self { 
     Self::with_parameter(arg, T::Parameter::default()) 
    } 
} 

Une mise en œuvre de Bar ressemblerait à ceci:

struct Baz; 

impl Bar for Baz { 
    type Parameter = i32; 

    fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self { 
     unimplemented!() 
    } 
}