Почему этот заем длится до конца функции? - PullRequest
0 голосов
/ 23 октября 2019

В следующем коде эта строка выдает ошибку (строка 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
}
...