[英]“Variable does not live long enough” when returning a Result containing a reference but it does live long enough
我正在實現一個小的實用程序,並且編譯器告訴我變量( TcpStream
)的生存期不夠長,並建議我找到一種使它與當前生存期完全相同的生存期的方法。
error[E0597]: `stream` does not live long enough
--> src/main.rs:47:35
|
47 | match handle_request(&mut stream){
| ^^^^^^ borrowed value does not live long enough
...
54 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 43:1...
--> src/main.rs:43:1
|
43 | / fn handle_array(stream: &mut BufReader<TcpStream>) -> Result<Data,Errors>
44 | | {
45 | | let mut array: Vec<Data> = Vec::with_capacity(50);//arbitrary size, picked differently in the complete program
46 | | for _x in 0..50 {
... |
53 | | Ok(Data::Array(array))
54 | | }
| |_^
use std::collections::HashMap;
use std::io::BufReader;
use std::io::Read;
use std::net::TcpStream;
static TOKEN: &[u8; 2] = b"\r\n";
fn main() {}
#[derive(Debug, Clone)]
pub enum Data {
String(Vec<u8>),
Error(Vec<u8>),
Integer(i64),
Binary(Vec<u8>),
Array(Vec<Data>),
Dictionary(HashMap<String, Data>),
}
#[derive(Debug, Clone)]
pub enum Errors<'a> {
CommandError(&'a str),
EndOfConnection,
NotImplemented,
}
pub fn handle_request(stream: &mut BufReader<TcpStream>) -> Result<Data, Errors> {
//TODO handle the empty stream
let mut buff: [u8; 1] = *b"0";
stream.read_exact(&mut buff); //TODO: handle error here
match &buff {
/* part skipped, not relevant */
b"*" => handle_array(stream),
&[_] => Err(Errors::CommandError("Bad request")),
}
}
/*part skipped, not relevant */
fn handle_array(stream: &mut BufReader<TcpStream>) -> Result<Data, Errors> {
let mut array: Vec<Data> = Vec::with_capacity(50); //arbitrary size, picked differently in the complete program
for _x in 0..50 {
match handle_request(&mut stream) {
Ok(x) => array.push(x.clone()),
Err(x) => return Err(x.clone()),
}
}
Ok(Data::Array(array))
}
我真的很堅持這一點。
看來我無法使用Err的值。 如果我更換
match handle_request(&mut stream){
Ok(x) => array.push(x.clone()),
Err(x) => return Err(x.clone()),
}
同
match handle_request(&mut stream){
Ok(x) => array.push(x.clone()),
Err(_) => return Err(Errors::NotImplemented),
}
問題解決了,但我不知道為什么。
您的問題可以簡化為:
struct Reader;
struct Data;
struct Errors<'a>(&'a str);
fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
for _ in 0..0 {
handle_request(&mut stream)?;
}
unimplemented!();
}
fn handle_request(_stream: &mut Reader) -> Result<Data, Errors> {
unimplemented!()
}
fn main() {}
error[E0597]: `stream` does not live long enough
--> src/main.rs:7:29
|
7 | handle_request(&mut stream)?;
| ^^^^^^ borrowed value does not live long enough
...
11 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 5:1...
--> src/main.rs:5:1
|
5 | / fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
6 | | for _ in 0..0 {
7 | | handle_request(&mut stream)?;
8 | | }
9 | |
10 | | unimplemented!();
11 | | }
| |_^
在handle_array
主體中, stream
的類型為&mut Reader
。 但是,在調用handle_request
,您需要對其進行另一個引用 ,從而創建一個&mut &mut Reader
。
在代碼中添加一些明確的生命周期(出於教育目的,這不會編譯),代碼看起來像這樣:
fn handle_array<'stream>(stream: &'stream mut Reader) -> Result<Data, Errors> {
let tmp: &'tmp mut &'stream mut Reader = &mut stream;
if let Err(x) = handle_request(tmp)
handle_request
需要一個&mut Reader
,因此編譯器會插入一些代碼來為您對齊這兩種類型。 編譯器在執行轉換時必須保持保守,因此選擇了較短的生存期:
fn handle_array<'stream>(stream: &'stream mut Reader) -> Result<Data, Errors> {
let tmp: &'tmp mut &'stream mut Reader = &mut stream;
let tmp2: &'tmp mut Reader = tmp;
if let Err(x) = handle_request(tmp2)
問題的下一個方面是這兩個功能的終生淘汰開始了。 它們的擴展形式如下:
fn handle_array<'stream>(stream: &'stream mut Reader) -> Result<Data, Errors<'stream>>
fn handle_request<'_stream>(_stream: &_stream mut Reader) -> Result<Data, Errors<'_stream>>
這意味着返回的Errors
的生存期與參數的生存期相關,但是在您的情況下, handle_request
的參數具有較短的'tmp
生存期, 而不是 'stream
的生存期。 這說明了為什么會出現編譯器錯誤:您試圖返回一個僅存在於函數內部的 Errors
(變量stream
本身的生存期),但是您試圖返回需要存在更長時間的引用。
我們可以通過僅將stream
handle_request
來解決此handle_request
:
handle_request(stream)?;
不幸的是,這只會改變錯誤:
error[E0499]: cannot borrow `*stream` as mutable more than once at a time
--> src/main.rs:9:40
|
9 | if let Err(x) = handle_request(stream) {
| ^^^^^^ mutable borrow starts here in previous iteration of loop
...
15 | }
| - mutable borrow ends here
這部分是更難解釋。 看到:
目前,Rust的確有些粗糙,但是越來越難以修復! 但是,現在您有兩個主要選擇:
這可能不起作用,因為您不能兩次從流中讀取,但是在其他情況下,它可能會很有用:
fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
let mut array = vec![];
for _ in 0..0 {
if handle_request(stream).is_err() {
return handle_request(stream);
}
if let Ok(r) = handle_request(stream) {
array.push(r);
};
}
unimplemented!();
}
放棄試圖在這種情況下,引用現在 。
struct Errors(String);
fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
let mut array = vec![];
for _ in 0..0 {
array.push(handle_request(stream)?);
}
unimplemented!();
}
為了提高效率,我將使用迭代器編寫該代碼:
fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
let array = (0..0)
.map(|_| handle_request(stream))
.collect::<Result<Vec<_>, _>>()?;
unimplemented!();
}
通過不穩定的 NLL功能和實驗性的 “ Polonius”實現,此代碼可以工作:
struct Errors<'a>(&'a str);
fn handle_array(stream: &mut Reader) -> Result<Data, Errors> {
let mut array = vec![];
for _ in (0..0) {
array.push(handle_request(stream)?);
}
unimplemented!();
}
普遍可用尚需時日...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.