rust - 为什么这个借用仍然是 "active"?

标签 rust

这是我遇到的事情的简化示例:

trait Bla<'a> {
    fn create(a: &'a Foo) -> Self;
    fn consume(self) -> u8;
}

struct Foo;
impl Foo {
    fn take(&mut self, u: u8) {}
}

struct Bar {
    foo: Foo,
}

impl Bar {
    fn foobar<'a, 'b, B: Bla<'b>>(&'a mut self)
    where 'a: 'b {
        let u = {
            // immutable borrow occurs here
            // type annotation requires that `self.foo` is borrowed for `'b`
            let foo: &'b Foo = &self.foo;
            let b = B::create(foo);
            b.consume()
        };

        // error[E0502]: cannot borrow `self.foo` as mutable because it is also borrowed as immutable
        self.foo.take(u);
    }
}

为什么是 self.foo即使在退出它被借用的块后仍然被认为是借用的,使用借用的所有东西也被删除了?

最佳答案

数据可能会流向另一个地方。
要理解为什么编译器认为不可变借用可能仍然存在是正确的,请考虑以下 Bla 的实现。这是有效的:

#![feature(once_cell)]

// The data stored in this global static variable exists for the entirety of runtime.
static REFS: SyncLazy<Mutex<Vec<&'static Foo>>> = SyncLazy::new(|| Mutex::new(vec![]));

struct Bad;
impl Bla<'static> for Bad {
    fn create(a: &'static Foo) -> Self {
        // The reference can go somewhere other than `Self`!
        REFS.lock().unwrap().push(a);
        Bad
    }

    fn consume(self) -> u8 {
        // Even if `self` is consumed here, 
        // `self` doesn't necessarily destory the immutable borrow.
        0
    }
}
当您的通用foobar函数接受 Bla 的任何有效实现,有效的实现可能需要 &'static借用保证借用持续整个运行时。因此,它一个错误,因为 consume不保证不可变借用消失。

您可能正在寻找 for<>语法,因为这将允许 Bad实现存在,但将禁止任何人调用 foobarBad :
impl Bar {
    fn foobar<B: for<'b> Bla<'b>>(&mut self) {
        let u = {
                let foo: &Foo = &self.foo;
                let b = B::create(foo);
                b.consume()
        };
        self.foo.take(u);
    }
}
fn main() {
    Bar::foobar::<Bad>(&mut Bar { foo: Foo })
    // ^ error: implementation of `Bla` is not general enough
    // | `Bad` must implement `Bla<'0>`, for any lifetime `'0`...
    // | ...but it actually implements `Bla<'static>`
}
如果不是这种情况,您可能需要提供更多实现细节而不是导致诊断错误的示例。

关于rust - 为什么这个借用仍然是 "active"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67147129/

相关文章:

rust - 闭包参数上未使用的类型参数

rust - Rust tokio_postgres行到对象的映射失败,时间戳列为serde_postgres

windows - 我如何知道我的 Rust 编译器正在使用哪个 Windows 工具链?

rust - 如何使用夜间 channel 执行 cargo 测试?

rust - 我不明白为什么变量必须被克隆而不被引用

rust - 为什么使用rust 使用rsi将参数传递给fn指针

rust - 如何将&[u8]转换为impl Iterator <Item = u8>? [复制]

rust - 如何同时实现反序列化和派生它

rust - 如何用泛型解决分支中类型不兼容的问题

rust - BTreeMap 和 BTreeSet 的分支因子是什么?