首页 > 解决方案 > 如何确保 self 在不借入的情况下超过返回值

问题描述

假设有这样的事情:

trait B {}
struct BB {}
impl B for BB {}

struct A {}
impl A {
    // With this, A can be dropped before B
    // fn get_b(&mut self) -> Box<dyn B> {...}

    fn get_b<'a>(&'a mut self) -> Box<dyn B + 'a> {...}
    fn mut_a(&mut self) {}
}

fn main() {
    let mut a = A {};
    let b = a.get_b();

    // These lines don't compile
    a.mut_a(); // A is borrowed. Is there any way to make this compile?

    // Does not compile and should not. b must be dropped before a
    drop(a);
    drop(b);
}

有什么方法可以确保在不a借用的情况下b(出于unsafe代码原因)寿命长a吗?

编辑:a和都b必须是可变的(如果声明mut)并且应该保持可移动。它唯一需要确保的是 B 在 A 之前被删除。

标签: rustborrow-checker

解决方案


如果您提供A两个字段,例如lifetimeand data,您可以对get_b进行共享引用lifetime并对mut_a进行可变引用data

trait B {}
struct BB {}
impl B for BB {}

struct A {
    pub lifetime: ALifetime,
    pub data: AData,
    #[allow(dead_code)]
    private: (), // prevent destructuring
}
struct ALifetime {}
struct AData {}
impl A {
    fn new() -> Self {
        Self { lifetime: ALifetime {}, data: AData {}, private: () }
    }
}
impl ALifetime {
    fn get_b<'a>(&'a self) -> Box<dyn B + 'a> { Box::new(BB{}) }
}
impl AData {
    fn mut_a(&mut self) {}
}

fn main() {
    let mut a = A::new();
    let b = a.lifetime.get_b();
    a.data.mut_a(); // Only `a.data` is borrowed here.
    // drop(b);
    drop(a); // Not allowed. b must be dropped before a
}

操场:https ://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ccd1a25cacd21d4364f2f3add1499015


推荐阅读