Rust 指定函数调用的参数生存期持续

Rust 指定函数调用的参数生存期持续,rust,lifetime,Rust,Lifetime,我有一个函数的特性,它引用迭代器: #[derive(Clone)] struct Dog { name: &'static str, } trait DogListAction<'a, I> where I: Iterator<Item = &'a Dog>, { fn on_dog_list(&mut self, dog_list: I); } struct DogListActionExample {} impl

我有一个函数的特性,它引用迭代器:

#[derive(Clone)]
struct Dog {
    name: &'static str,
}

trait DogListAction<'a, I>
where
    I: Iterator<Item = &'a Dog>,
{
    fn on_dog_list(&mut self, dog_list: I);
}

struct DogListActionExample {}

impl<'a, I> DogListAction<'a, I> for DogListActionExample
where
    I: Iterator<Item = &'a Dog>,
{
    fn on_dog_list(&mut self, dog_list: I) {
        for dog in dog_list {
            println!("{}", dog.name);
        }
    }
}

fn main() {
    let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
    let mut action_example = DogListActionExample {};
    let mut dog_list_actions: Vec<Box<DogListAction<_>>> = vec![Box::new(action_example)];
    loop {
        let dog_clone = dogs.clone();
        for dog_list_action in &mut dog_list_actions {
            dog_list_action.on_dog_list(dog_clone.iter());
        }
    }
}

我猜借用检查器认为,
dog\u clone
中的数据可能会在函数结束后被引用,但事实并非如此。

这里的问题是,代码可能会保存对寿命较长的
dog\u list\u actions
中的
dog\u clone
元素的短期引用。我们需要告诉编译器,我们不会保存迭代器生成的引用。可以这样做:

trait DogListAction {
    fn on_dog_list<'a, I>(&'a mut self, dog_list: I)
    where
        I: Iterator<Item = &'a Dog>;
}
注意
框中的第二个
'a
。Rust在默认情况下添加了一个绑定到盒装trait对象的
'static
trait,我们不希望在这里使用
'static

#[derive(Clone)]
struct Dog {
    name: &'static str,
}

trait DogListAction {
    fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}

struct DogListActionExample {}

impl DogListAction for DogListActionExample {
    fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>) {
        for dog in dog_list {
            println!("{}", dog.name);
        }
    }
}

fn main() {
    let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
    let action_example = DogListActionExample {};
    let mut dog_list_actions: Vec<Box<DogListAction>> = vec![Box::new(action_example)];
    {
        let dogs_clone = dogs.clone();
        for dog_list_action in &mut dog_list_actions {
            dog_list_action.on_dog_list(Box::new(dogs_clone.iter()));
        }
    }
}
#[派生(克隆)]
结构狗{
名称:&'static str,
}
特质独断行为{

fn on_dog_list能否请您提供一个,最好是一个游乐场链接?我看不出您显示的代码有任何错误。(有关更多信息,请参阅。)这里是一个链接,指向操场上的一个最小示例:我仍然认为问题在于编译器认为DogListAction可能会引用迭代器中的数据,即使在调用函数之后也是如此。我正在尝试添加显式的生存期规范,但没有成功far@Clynamen,这里的主要问题是代码c在长寿命的
dog\u list\u actions
元素中可能保存对
dog\u clone
元素的短期引用。如果将
dog\u clone.iter()
替换为
dogs.iter()
,则代码将编译。您需要在\u dog\u list()上对函数进行签名
表达您不保存迭代器生成的引用的意图。
#[derive(Clone)]
struct Dog {
    name: &'static str,
}

trait DogListAction {
    fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}

struct DogListActionExample {}

impl DogListAction for DogListActionExample {
    fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>) {
        for dog in dog_list {
            println!("{}", dog.name);
        }
    }
}

fn main() {
    let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
    let action_example = DogListActionExample {};
    let mut dog_list_actions: Vec<Box<DogListAction>> = vec![Box::new(action_example)];
    {
        let dogs_clone = dogs.clone();
        for dog_list_action in &mut dog_list_actions {
            dog_list_action.on_dog_list(Box::new(dogs_clone.iter()));
        }
    }
}