重构搞砸了可变借款 - 为什么?

时间:2015-05-15 05:24:09

标签: rust lifetime

我试图理解为什么以下重构会导致错误,即使它应该有效地具有相同的行为:

在:

fn req_handler(req: &mut Request) -> IronResult<Response> {
    let pool = req.get::<Read<Database>>().ok().expect("database component not initialised");
    let connection = pool.get().unwrap();

    let maybe_id = req.extensions.get::<Router>().unwrap().find("id");
    ...

后:

pub fn get_pool_connection<'a, 'b, 'c>(req: &'a mut Request<'b, 'c>) -> PooledConnection<'a, PostgresConnectionManager> {
    let pool = req.get_ref::<Read<Database>>().ok().expect("database component not initialised");
    pool.get().unwrap()
}
fn req_handler(req: &mut Request) -> IronResult<Response> {
    let connection = get_pool_connection(req);
    let maybe_id = req.extensions.get::<Router>().unwrap().find("id");

这会导致错误:

src/main.rs:64:20: 64:34 error: cannot borrow `req.extensions` as immutable because `*req` is also borrowed as mutable
src/main.rs:64     let maybe_id = req.extensions.get::<Router>().unwrap().find("id");
                                  ^~~~~~~~~~~~~~
src/main.rs:62:42: 62:45 note: previous borrow of `*req` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*req` until the borrow ends
src/main.rs:62     let connection = get_pool_connection(req);
                                                        ^~~
src/main.rs:76:2: 76:2 note: previous borrow ends here
src/main.rs:61 fn req_handler(req: &mut Request) -> IronResult<Response> {
...
src/main.rs:76 }

所以问题是get_pool_connection借用了请求并返回connection,这阻止了req进一步使用。但为什么会这样呢?保证req使用至少与返回的PooledConnection相同的生命周期。它也没有移动,只是作为&mut传递。那么是什么阻止了请求被使用?

当本地*req和函数参数都是引用时,为什么错误说req被借用?

(相关文档:RequestPool

1 个答案:

答案 0 :(得分:2)

这实际上就是终身注释的含义。如果你有一个具有这个原型的功能:

fn get_bar<'a>(&'a Foo) -> Bar<'a> { ... }

这意味着返回的Bar对象拥有与Foo对象之一相关联的生命周期。结果:

  • Bar个对象借用Foo对象,只要它还活着
  • Bar对象不允许超过Foo对象。

在您的情况下,connection的类型为PooledConnection<'a, ...>,其中'a&'a mut req中定义的生命周期,因此被视为{{1}的可变借用}}

它在重构之前有效,因为req的生命周期实际上与connection的生命周期相关联,pool没有借用req,因为它没有任何生命周期参数。

由于你的重构力量connection借用了req,这是以前不需要的,也许这不是一个合适的重构。