2017-02-03 1 views
4

J'applique une fermeture sur l'itérateur et je veux utiliser stable, donc je veux retourner une boîte Iterator. La façon évidente de le faire est la suivante:Pourquoi Box <Iterator <Item = &Foo> + 'a> nécessaire?

struct Foo; 

fn into_iterator(myvec: &Vec<Foo>) -> Box<Iterator<Item = &Foo>> { 
    Box::new(myvec.iter()) 
} 

Cela échoue parce que le vérificateur d'emprunt ne peut pas déduire les durées de vie appropriées.

Après quelques recherches, j'ai trouvé Correct way to return an Iterator?, ce qui m'a amené à ajouter + 'a:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<Iterator<Item = &'a Foo> + 'a> { 
    Box::new(myvec.iter()) 
} 

Mais je ne comprends pas

  • Qu'est-ce que cela ne
  • Et pourquoi il est nécessaire ici

Répondre

8

Il y a une chose que l'on oublie facilement: Si vous avez un trait Foo et que vous souhaitez avoir un objet de trait encadré Box<Foo>, le compilateur ajoute automatiquement une limite de durée de vie 'static (comme indiqué dans RFC 599). Cela signifie que Box<Foo> et Box<Foo + 'static> sont équivalents!

Dans votre cas, le compilateur ajoute automatiquement statique lié tel que ce ...

fn into_iterator(myvec: &Vec<Foo>) -> Box<Iterator<Item = &Foo>> 

... est équivalente à celle:

fn into_iterator(myvec: &Vec<Foo>) -> Box<Iterator<Item = &Foo> + 'static> 

règles maintenant la vie de élision coup de pied et "connect" les deux slots de durée de vie, tels que le code ci-dessus est équivalent à:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<Iterator<Item = &'a Foo> + 'static> 

Mais le type Iter<'a, Foo> (le type d'itérateur spécifique pour Vec<Foo>) ne satisfait évidemment pas le 'static lié (parce qu'il emprunte le Vec<Foo>)! Nous devons donc dire au compilateur que nous ne voulons pas la valeur par défaut 'static lié en spécifiant notre propre vie liée:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<Iterator<Item = &Foo> + 'a> 

Maintenant, le compilateur sait que l'objet de trait est uniquement valable pour la durée de vie 'a. Notez que nous n'avons pas explicitement besoin d'annoter la durée de vie du type Item associé! Les règles d'élision à vie prennent soin de cela.

+0

Oh bien sûr! J'ai complètement oublié qu'il ne s'agit pas de Foo mais de l'Iterator lui-même; J'ai d'abord pensé que la limite de vie était sur une structure ... Merci d'avoir clarifié ça! – torkleyy