2017-03-03 7 views
4

J'essaie de définir un trait avec une fonction qui renvoie un type associé avec la même durée de vie qu'un paramètre.Définir un trait avec une fonction qui renvoie un type associé avec la même durée de vie qu'un paramètre

Conceptuellement quelque chose comme ce qui suit (ce qui ne fonctionne pas: lifetime parameter not allowed on this type [Self::Output]):

trait Trait { 
    type Output; 
    fn get_output<'a>(&self, input: &'a i32) -> Self::Output<'a>; 
} 

J'ai trouvé plusieurs questions sur la durée de vie pour les types associés sur le débordement de pile et l'Internet, mais aucun ne semble aider. Certains ont suggéré de définir la durée de vie dans l'ensemble trait:

trait Trait<'a> { 
    type Output; 
    fn get_output(&self, input: &'a i32) -> Self::Output; 
} 

mais cela ne fonctionne pas non plus: il compile, mais la fonction suivante ne peut pas compiler:

fn f<'a, T>(var: &T) 
    where T: Trait<'a> 
{ 
    let input = 0i32; 
    let output = var.get_output(&input); 
} 

donnant une erreur:

error: `input` does not live long enough 
    --> <anon>:9:35 
    | 
    |  let output = var.get_output(&input); 
    |         ^^^^^ does not live long enough 
    | } 
    | - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the body at 7:48... 
    --> <anon>:7:49 
    | 
    | fn f<'a, T>(var : &T) where T : Trait<'a> { 
    | _________________________________________________^ starting here... 
    | |  let input = 0i32; 
    | |  let output = var.get_output(&input); 
    | | } 
    | |_^ ...ending here 

Comment dois-je définir le trait pour qu'il se comporte comme je le souhaite?

Répondre

4

Ceci est actuellement impossible, même dans la nuit Rust.

Cela nécessite une forme de type à fort taux de dépendance (HKT), et l'approche actuelle envisagée est appelée ATC (Associated Type Constructor).

La principale motivation pour l'introduction de l'ATC est en fait cette très usecase.

Avec ATC, la syntaxe serait:

trait Trait { 
    type Output<'a>; 
    fn get_output<'a>(&self, input: &'a i32) -> Self::Output<'a>; 
} 

Note: si vous souhaitez en savoir plus sur ATCs, voir Niko's series of articles.


Pour l'exemple particulier que vous avez, vous pouvez contourner ce avec HRTB (Higher Classé n traits Bounds) comme l'a noté Shepmaster:

fn f<T>(var: &T) 
    where for<'a> T: Trait<'a> 
{ ... } 

mais cela est assez limité (notamment, limité à limites de caractères).