如何在Rust中返回锁定结构成员的迭代器?

4
这是我所能达到的程度,使用rental,部分基于如何在与其迭代的字符串相同的结构体中存储Chars迭代器?。这里的区别在于锁定成员的get_iter方法必须使用可变自身引用。
我不一定要使用rental:如果使用reffersowning_ref解决方案,我会很高兴。 PhantomData在这里存在只是为了让MyIter与被迭代的东西MyIterable之间保持正常的生命周期关系。
我也尝试将#[rental]更改为#[rental(deref_mut_suffix)],并将MyIterable.get_iter的返回类型更改为Box<Iterator<Item=i32> + 'a>,但这给我带来了其他生命周期错误,这些错误源自于我无法解释的宏。
#[macro_use]
extern crate rental;

use std::marker::PhantomData;

pub struct MyIterable {}

impl MyIterable {
    // In the real use-case I can't remove the 'mut'.
    pub fn get_iter<'a>(&'a mut self) -> MyIter<'a> {
        MyIter {
            marker: PhantomData,
        }
    }
}

pub struct MyIter<'a> {
    marker: PhantomData<&'a MyIterable>,
}

impl<'a> Iterator for MyIter<'a> {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        Some(42)
    }
}

use std::sync::Mutex;

rental! {
    mod locking_iter {
        pub use super::{MyIterable, MyIter};
        use std::sync::MutexGuard;

        #[rental]
        pub struct LockingIter<'a> {
            guard: MutexGuard<'a, MyIterable>,
            iter: MyIter<'guard>,
        }
    }
}

use locking_iter::LockingIter;

impl<'a> Iterator for LockingIter<'a> {
    type Item = i32;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.rent_mut(|iter| iter.next())
    }
}

struct Access {
    shared: Mutex<MyIterable>,
}

impl Access {
    pub fn get_iter<'a>(&'a self) -> Box<Iterator<Item = i32> + 'a> {
        Box::new(LockingIter::new(self.shared.lock().unwrap(), |mi| {
            mi.get_iter()
        }))
    }
}

fn main() {
    let access = Access {
        shared: Mutex::new(MyIterable {}),
    };
    let iter = access.get_iter();
    let contents: Vec<i32> = iter.take(2).collect();
    println!("contents: {:?}", contents);
}

1
如果唯一的问题是 mut,那么只需要使用 #[rental_mut] 而不是 #[rental] 应该就可以解决了,不是吗? - rodrigo
哦,男孩,我怎么没发现那个?非常感谢! - Oliver Goodman
2
如果这是解决方案,您应该编写一个答案并接受它,而不是将其编辑到问题中。回答自己的问题很正常,并使未来的读者更容易知道问题已经解决。 - trent
@trentol,完成了。看来我必须等待24小时才能接受它 :)。 - Oliver Goodman
1个回答

5

正如用户rodrigo在评论中指出的那样,解决方案就是将#[rental]更改为#[rental_mut]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接