我正在开发一个涉及以下结构的程序:
struct App {
data: Vec<u8>,
overlay: Vec<(usize, Vec<u8>)>,
sink: Sink,
}
简而言之,该data
字段包含一些字节,并且overlay
是要在特定索引处插入的一系列字节序列。类型并不重要,Sink
只是它具有如下功能:
impl Sink {
fn process<'a>(&mut self, input: Vec<&'a [u8]>) {
// ...
}
}
我已经实现了一个迭代器来合并来自data
和overlay
消费的信息Sink
。
struct MergeIter<'a, 'b> {
data: &'a Vec<u8>,
overlay: &'b Vec<(usize, Vec<u8>)>,
// iterator state etc.
}
impl<'a, 'b> Iterator for MergeIter<'a, 'b> {
type Item = &'a [u8];
// ...
}
我认为这是一个小小的谎言,因为迭代器返回的每个 &[u8] 的生命周期并不总是原始的生命周期data
。从插入的数据overlay
具有不同的生命周期,但我不知道如何更准确地注释它。无论如何,借用检查器似乎并不介意 - 以下方法有效:
fn merge<'a, 'b>(data: &'a Vec<u8>, overlay: &'b Vec<(usize, Vec<u8>)>, start: usize) -> Vec<&'a [u8]> {
MergeIter::new(data, overlay, start).collect()
}
impl App {
fn process(&mut self) {
let merged = merge(&self.data, &self.overlay, 0);
// inspect contents of 'merged'
self.sink.process(merged);
}
}
我最终在merge
所有地方都使用了这个功能,但总是针对相同的数据/覆盖。所以我想我会App::merge
为了方便添加一个函数,这就是问题开始的地方:
impl App {
fn merge<'a>(&'a self, start: usize) -> Vec<&'a [u8]> {
MergeIter::new(&self.data, &self.overlay, start).collect()
}
fn process(&mut self) {
let merged = self.merge(0);
// inspect contents of 'merged'
self.sink.process(merged);
}
}
App::process
现在无法通过借用检查器 - 在借用 self 时,它拒绝允许 self.sink 的可变借用。
我已经为此苦苦挣扎了一段时间,如果我理解正确,问题不在于process
这个签名,而是在于:
fn merge<'a>(&'a self, start: usize) -> Vec<&'a [u8]> {
在这里,我基本上告诉借用检查器,向量中返回的引用等同于self
借用。
尽管我觉得我现在已经理解了这个问题,但我仍然觉得我的双手被束缚了。忽略生命周期注释并没有帮助(因为编译器做了等价的?),并且只涉及两个引用,我无法告诉 rust 输出引用的生命周期绑定到其他东西。
我也试过这个:
fn merge<'a, 'b>(&'b self, start: usize) -> Vec<&'a [u8]> {
let data: &'a Vec<u8> = &self.data;
MergeIter::new(&self.data, &self.overlay, start).collect()
}
但是编译器抱怨该let
语句(“由于需求冲突,无法推断出适当的生命周期”——我还发现编译器没有解释所述要求令人愤怒)。
有可能实现这一目标吗?Rust 参考是对生命周期注释和相关语法的一种解释。
rustc 1.0.0-nightly (706be5ba1 2015-02-05 23:14:28 +0000)