请看下面的代码:
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
(playground link)
它不会编译,并产生以下错误:
error: lifetime may not live long enough
--> src/lib.rs:12:9
|
8 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
9 | fn do_stuff(&mut self) {
| - let's call the lifetime of this reference `'1`
...
12 | Self::subroutine(&zipped);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
我并不完全理解这个抱怨--self
肯定总是有一个生命周期被赋给我们正在使用impl
的类吗?--但是我可以理解zip()
的两个参数需要持续相同的时间,所以我将do_stuff
改为&'a mut self
。
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&'a mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
但是,现在编译失败,并显示:
error[E0502]: cannot borrow `foo.output` as immutable because it is also borrowed as mutable
--> src/lib.rs:27:16
|
26 | foo.do_stuff();
| -------------- mutable borrow occurs here
27 | let _out = &foo.output;
| ^^^^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
为什么在do_stuff
的参数列表中指定self
的生存期意味着我以后突然不能使用foo
的不可变引用;我能做些什么呢
1条答案
按热度按时间wj8zmpe11#
在这里写
fn do_stuff(&'a mut self)
意味着,这个借用的自我的生命周期,必须和这个自我所借用的一样长,那通常不是你想要的。你的错误就在这里
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
。想想你声明的词汇意义。你的方法除了需要一个“parent”生命周期什么都不返回?没有理由这样做。简单的解决方案就是为你的Item引入一个新的生命周期。就像fn subroutine<'i, Arg: Iterator<Item=(&'i u8, &'i u8)>>(_zipped: &Arg) {}
一样。除非你的函数返回一些链接到'a
的东西,否则这里不应该有parent的生命周期。此外,最好接受
IntoIterator
,因为它更通用,没有理由通过引用接受它,最后,当您有如此复杂的通用时,最好使用where
,如果您真的想要学究气,您需要两个生命周期: