此代码编译:
struct BufRef<'a> {
buf: &'a [u8],
}
struct Foo<'a> {
buf_ref: BufRef<'a>,
}
impl<'a> Iterator for Foo<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
let result = &self.buf_ref.buf;
Some(result)
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我更改BufRef为:
struct BufRef<'a> {
buf: &'a mut [u8],
}
Run Code Online (Sandbox Code Playgroud)
编译器说:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
--> src\main.rs:12:5
|
12 | / fn next(&mut self) -> Option<Self::Item> {
13 | | let result = &self.buf_ref.buf;
14 | | Some(result)
15 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:13:16
|
13 | let result = &self.buf_ref.buf;
| ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 9:6...
--> src\main.rs:9:6
|
9 | impl<'a> Iterator for Foo<'a> {
| ^^
= note: ...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Run Code Online (Sandbox Code Playgroud)
为什么更改字段会&'a mut [u8]导致错误?
另外,编译器的含义是:
...so that the types are compatible:
expected std::iter::Iterator
found std::iter::Iterator
Run Code Online (Sandbox Code Playgroud)
我认为误导您的是您的代码有折叠的引用。
你的next函数基本上等同于这段代码:
fn next(&mut self) -> Option<&'a [u8]> {
let result: &&'a [u8] = &self.buf_ref.buf;
Some(result)
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为双引用折叠为单引用。在这种情况下,双重引用只会混淆代码。写吧:
fn next(&mut self) -> Option<Self::Item> {
Some(self.buf_ref.buf)
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为引用总是Copy.
但是现在当您将定义更改为 时会发生什么&'a mut?您现在可能正在猜测...可变引用不是, Copy因此相同的简单代码将为您提供易于阅读的错误消息:
self.buf_ref.buf无法从可变引用后面移出
当然,您可以将可变引用重新借用为常量引用,然后尝试返回它,但不幸的是,这不起作用,因为重新借用不能使用与可变变量相同的生命周期,它必须严格更小(或者您可以给指向的值起别名)。编译器将这个重新借用的生命周期指定为函数的生命周期next,但是现在您不能返回这个借用,因为它是本地引用!
不幸的是,我不知道有什么安全的方法可以让你的代码编译。事实上,我非常确定它会创建一个不健全的 API。也就是说,如果您设法编译代码,那么此安全代码将创建未定义的行为:
fn main() {
let mut buf = vec![1,2,3];
let buf_ref = BufRef { buf: &mut buf };
let mut foo = Foo { buf_ref };
let x: &[u8] = foo.next().unwrap();
//note that x's lifetime is that of buf, foo is not borrowed
//x and foo.buf_ref.buf alias the same memory!
//but the latter is mutable
println!("{}", x[0]); //prints 1
foo.buf_ref.buf[0] = 4;
println!("{}", x[0]); //prints what?
}
Run Code Online (Sandbox Code Playgroud)