Bon, j'ai trouvé LE truc chiant du Rust.
Quand tu codes des traits, la logique voudrait que tu puisses écrire quelque chose comme ça :
Code:
trait Container<T> {
type I: Iterator<T>;
fn iter() -> I;
}
C'est à dire un trait "container qui contient des T" dont la fonction iter() renvoie un objet de type I dont on sait qu'il implémente "itérateur sur T".
Sauf que tu ne peux pas définir de type à l'intérieur de tes traits, du coup t'es obligé de faire ça :
Code:
trait Container<T, I: Iterator<T>> {
fn iter() -> I;
}
Ce qui devient un trait "container qui contient des T et qui renvoie un itérateur de type I".
On pourrait se dire que c'est pas très grâve, mais en fait si. Parce qu'au lieu d'avoir une fonction comme ça :
Code:
fn foo<T, C: Container<T>>(cnt: C);
On est obligé d'écrire la fonction comme ça :
Code:
fn foo<T, I: Iterator<T>, C:Container<T,I>>(cnt: C);
Et là c'est le cas simple.
Un autre exemple, au lieu d'écrire ça :
Code:
fn foo<D: Display>(display: &D);
Tu es obligé d'écrire ça :
Code:
fn foo<'a, T: Texture<'a>, VB: VertexBuffer<'a>, IB: IndexBuffer<'a>, ST: ShaderType, S: Shader<'a, ST>, P: Program<'a>, D: Display<T,VB,IB,S,P>(display: &D);
Et en plus tu es obligé de copier-coller ça avant 100 % des fonctions qui utilisent un Display, et de modifier toutes les définitions si jamais tu modifies ton trait "Display".
Apparemment ils ont déjà repéré le problème, mais ne vont pas le corriger à court-moyen terme parce que "la correction peut être implémentée de façon backward-compatible", et que pour l'instant la priorité absolue c'est d'avoir une version stable du langage. Toutes les features qui peuvent être ajoutées sans casser la rétrocompatibilité ne seront ajoutées qu'après la version 1.0 prévue pour la fin de l'année.
En attendant ça rend le langage extrêmement chiant à utiliser dans certains cas.