
[英]Why doesn't a local variable live long enough for thread::scoped?
[英]Function local variable doesn't live long enough [duplicate]
这个问题在这里已有答案:
我正在尝试编写一个围绕serde_json和Rocket的FromData
的包装器来强烈地输入一些与服务器交换的JSON。
我无法编译以下代码:
extern crate serde_json;
extern crate rocket;
extern crate serde;
use serde::ser::Error;
use serde_json::Value;
use rocket::data::DataStream;
use rocket::outcome::IntoOutcome;
use std::io::Read;
static NULL: Value = serde_json::Value::Null;
pub struct ResponseJSON<'v> {
success: bool,
http_code: u16,
data: &'v serde_json::Value,
}
impl<'v> ResponseJSON<'v> {
pub fn ok() -> ResponseJSON<'v> {
ResponseJSON {
success: true,
http_code: 200,
data: &NULL,
}
}
pub fn http_code(mut self, code: u16) -> ResponseJSON<'v> {
self.http_code = code;
self
}
pub fn data(mut self, ref_data: &'v serde_json::Value) -> ResponseJSON<'v> {
self.data = ref_data;
self
}
pub fn from_serde_value(json: &'v serde_json::Value) -> ResponseJSON<'v> {
if !json["success"].is_null() {
ResponseJSON::ok()
.http_code(json["http_code"].as_u64().unwrap() as u16)
.data(json.get("data").unwrap_or(&NULL))
} else {
ResponseJSON::ok()
.data(json.pointer("").unwrap())
}
}
}
impl<'v> rocket::data::FromData for ResponseJSON<'v> {
type Error = serde_json::Error;
fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
if !request.content_type().map_or(false, |ct| ct.is_json()) {
println!("Content-Type is not JSON.");
return rocket::Outcome::Forward(data);
}
let data_from_reader = data.open().take(1<<20);
let value = serde_json::from_reader(data_from_reader);
let unwraped_value : Value = if value.is_ok() { value.unwrap() } else { Value::Null };
if !unwraped_value.is_null() {
Ok(ResponseJSON::from_serde_value(&unwraped_value)).into_outcome()
} else {
Err(serde_json::Error::custom("Unable to create JSON from reader")).into_outcome()
}
}
}
fn main() {
println!("it runs!");
}
编译器的错误:
Compiling tests v0.1.0 (file:///Users/bgbahoue/Projects.nosync/tests)
error: `unwraped_value` does not live long enough
--> src/main.rs:64:48
|
64 | Ok(ResponseJSON::from_serde_value(&unwraped_value)).into_outcome()
| ^^^^^^^^^^^^^^ does not live long enough
...
68 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'v as defined on the body at 53:114...
--> src/main.rs:53:115
|
53 | fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
| ___________________________________________________________________________________________________________________^
54 | | if !request.content_type().map_or(false, |ct| ct.is_json()) {
55 | | println!("Content-Type is not JSON.");
56 | | return rocket::Outcome::Forward(data);
... |
67 | | }
68 | | }
| |_____^
error: aborting due to previous error
由于data_from_reader
, value
和unwraped_value
来自data
我认为编译器可以推断它具有相同的生命周期,但显然情况并非如此。 有什么方法可以说明或做一些在这种情况下会起作用的事情吗?
pub fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
fn open(self) -> DataStream
rocket::data::DataStream::take
:
fn take(self, limit: u64) -> Take<Self>
根据@LukasKalbertodt上面的评论,当ResponseJSON拥有serde_json::Value
时,它确实有效
修改后的代码(按原样粘贴,即使有更好的方法来链接代码的某些部分)
#![allow(dead_code)]
extern crate serde_json;
extern crate rocket;
extern crate serde;
use serde::ser::Error;
use serde_json::Value;
use rocket::outcome::IntoOutcome;
use std::io::Read;
static NULL: Value = serde_json::Value::Null;
pub struct ResponseJSON { // <-- changed to remove the lifetime parameter
success: bool,
http_code: u16,
data: serde_json::Value, // <- changed to remove the '&'
}
impl ResponseJSON {
pub fn ok() -> ResponseJSON {
ResponseJSON {
success: true,
http_code: 200,
data: Value::Null,
}
}
pub fn http_code(mut self, code: u16) -> ResponseJSON {
self.http_code = code;
self
}
pub fn data(mut self, data: serde_json::Value) -> ResponseJSON { // <- changed to remove the '&'
self.data = data;
self
}
pub fn from_serde_value(json: serde_json::Value) -> ResponseJSON { // <- changed to remove the reference & lifetime parameter
if !json["success"].is_null() {
ResponseJSON::ok()
.http_code(json["http_code"].as_u64().unwrap() as u16)
.data(json.get("data").unwrap_or(&NULL).clone())
} else {
ResponseJSON::ok()
.data(json.pointer("").unwrap().clone())
}
}
}
impl rocket::data::FromData for ResponseJSON {
type Error = serde_json::Error;
fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
if !request.content_type().map_or(false, |ct| ct.is_json()) {
println!("Content-Type is not JSON.");
return rocket::Outcome::Forward(data);
}
let data_from_reader = data.open().take(1<<20);
let value = serde_json::from_reader(data_from_reader);
let unwraped_value : Value = if value.is_ok() { value.unwrap() } else { Value::Null };
if !unwraped_value.is_null() {
Ok(ResponseJSON::from_serde_value(unwraped_value)).into_outcome() // <- changed to remove the '&' in front of `unwraped_value`
} else {
Err(serde_json::Error::custom("Unable to create JSON from reader")).into_outcome()
}
}
}
fn main() {
println!("it compiles & runs");
}
cargo run
输出
Compiling tests v0.1.0 (file:///Users/bgbahoue/Projects.nosync/tests)
Finished dev [unoptimized + debuginfo] target(s) in 1.28 secs
Running `target/debug/tests`
it compiles & runs
我的看法是,在这种情况下,输入参数data
的所有权(生命周期?)将传递给data_from_reader
将value
传递给unwraped_value
,返回到返回的rocket::data::Outcome
的临时ResponseJSON; 所以看起来还可以。
对于引用,临时ResponseJSON没有比函数结束更长,因为它比创建它的serde_json::Value
更长,即unwraped_value
lifetime,即函数的结束; 因此编译问题。
虽然不是100%肯定我的解释,但是会喜欢你对此的看法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.