В следующем коде эта строка выдает ошибку (строка 106 в полном файле):
_exec_ruleset_result = ruleset.exec(&mut ctx, req.trace_on).clone();
Ошибка:
`ctx` does not live long enough
borrowed value does not live long enoughrustc(E0597)
execute_ruleset.rs(106, 61): borrowed value does not live long enough
execute_ruleset.rs(129, 1): `ctx` dropped here while still borrowed
execute_ruleset.rs(129, 1): borrow might be used here, when `ctx` is dropped and runs the destructor for type `parser::execution_context::ExecutionContext<'_>`
Строка 129 - это конецфункции. Таким образом, компилятор говорит, что изменчивый заем ctx длится до конца функции или за ее пределами. ПОЧЕМУ ???
Используя границы в скобках, я предположил, что ruleset
рано выходит из области видимости. Затем, клонируя возвращаемое значение из ruleset.exec
, я предполагал, что возвращаемое значение перед клоном выйдет из области видимости. Почему этот изменчивый заем продлевается?
#[post("/rulesets/{name}")]
fn route((path, req, data): (web::Path<String>, web::Json<ExecuteRulesetRequest>, web::Data<RwLock<ServiceState>>)) -> HttpResponse {
let mut state = data.write().unwrap();
state.tally();
let ruleset_name = (*path).clone();
let http_response;
let found_in_cache;
let mut ctx = ExecutionContext::default();
{
// Add data sent by caller to the context .
if let Some(value) = &req.context { ctx.store(&req.context_name, value); }
let mut exec_response = ExecuteRulesetResponse::new_without_context();
{
match state.ruleset_cache.get(&ruleset_name) {
Some((ruleset_from_cache, _time)) => {
found_in_cache = true;
let _exec_ruleset_result;
{
// TODO: This clone of a whole RuleSet is an expensive abomination,
// but the calls to `trace` deeper in the code modify the Expression temporarily,
// and that is not threadsafe. Need to refactor trace to have state passed in, maybe a logger.
let mut ruleset = ruleset_from_cache.clone();
_exec_ruleset_result = ruleset.exec(&mut ctx, req.trace_on).clone();
}
// Transcribe values from exec_ruleset_result into exec_response, then into HttpResponse.
// exec_response.did_command_succeed = exec_ruleset_result.did_ruleset_pass || exec_ruleset_result.did_ruleset_fail;
// exec_response.passed = exec_ruleset_result.did_ruleset_pass;
// exec_response.failed = exec_ruleset_result.did_ruleset_fail;
// if exec_ruleset_result.errors.len() > 0 {
// exec_response.errors = Some(exec_ruleset_result.errors.clone().into());
// }
},
None => { found_in_cache = false; }
}
}
if found_in_cache {
// if req.return_context { exec_response.context = Some(ctx.clone().into()); }
http_response = HttpResponse::Ok().json(exec_response);
}
else {
http_response = HttpResponse::NotFound().json(ExecuteRulesetResponse::new_with_error(format!("Unable to find RuleSet {} in cache", ruleset_name)));
}
}
http_response
}