< 返回版块

zhangzhenxiang666 发表于 2025-10-28 13:46

Tags:生命周期

// 在manager字段中对于第一个'a它是协变的, 对于第二个'a, 由于mut的原因, Manager<'a>是不变的, 所以'a是不变的,因此整体是不变的
struct Interface<'a> {
    manager: &'a mut Manager<'a>,
}

impl<'a> Interface<'a> {
    pub fn noop(self) {
        println!("interface consumed");
    }
}

// 在text字段中'a是协变的, 因此Manager对于'a是协变的
struct Manager<'a> {
    text: &'a str,
}

// 同理对于List来说, 在'a上是协变的
struct List<'a> {
    manager: Manager<'a>,
}

impl<'a> List<'a> {
    // 这个方法由于Interface对其生命周期参数是不变的, 导致'a是不变的, 又由于'a与List绑定, 导致对List的&mut(可变借用)会与List本身一致
    pub fn get_interface(&'a mut self) -> Interface<'a> {
        Interface {
            manager: &mut self.manager,
        }
    }
}

fn main() {
    let mut list = List {
        manager: Manager { text: "hello" },
    };

    // 按道理来说这里返回的匿名Interface应该会在这一行后直接被drop掉, 因此list也应该被drop掉(见get_interface注释)
    // 但是实际上下面的use_list(&list)的报错是list被可变借用了, 不能再被借用
    // 因此我是否可以认为这个那个逆名的Interface没有被dro掉, 它保持到了use_list(&list)的结束
    list.get_interface().noop();

    println!("Interface should be dropped here and the borrow released");

    use_list(&list);
}

fn use_list(list: &List) {
    println!("{}", list.manager.text);
}

这个理解是否正确, 请佬教一下我

评论区

写评论
xiaoyaou 2025-10-30 11:14

看到这个想起来之前也有个类似的讨论:sqlx生命周期问题

作者 zhangzhenxiang666 2025-10-28 19:05

感谢

--
👇
zylthinking: 借用检查是编译期分析, 它看到的是源代码, 不会关心运行; 你告诉它 'a 它就在代码里面圈定 'a 的范围; 然后检查这个范围内有没有违反借用规则的语句.

大概就这么理解就行

zylthinking 2025-10-28 17:09

借用检查是编译期分析, 它看到的是源代码, 不会关心运行; 你告诉它 'a 它就在代码里面圈定 'a 的范围; 然后检查这个范围内有没有违反借用规则的语句.

大概就这么理解就行

作者 zhangzhenxiang666 2025-10-28 15:00

确实是一样的效果,那就是&'a mut self已经表明了这个可变引用的生命周期与List<'a>一致, 即使是get_interface(&'a mut self)->()调用完成后可以释放掉了, rust的借用检查器也不会释放掉可变引用对吗

--
👇
zylthinking: ``` pub fn get_interface(&'a mut self) -> Interface<'a>

这里其实和返回的 Interface<'a>  没啥关系
&'a mut self 已经表明了存在一个对 List<'a> 的引用, 它的生命周期持续到 'a 结束;
而 List<'a> 也不可能超过 'a 而存在; 因此, 这基本表明了 &'a mut self 创建出来后, 就别想着直接访问 List<'a> 了

你可以试试这个

pub fn get_interface(&'a mut self) -> ()


估计一样的效果, 如果我理解没有错误的话
zylthinking 2025-10-28 14:36
 pub fn get_interface(&'a mut self) -> Interface<'a> 

这里其实和返回的 Interface<'a> 没啥关系 &'a mut self 已经表明了存在一个对 List<'a> 的引用, 它的生命周期持续到 'a 结束; 而 List<'a> 也不可能超过 'a 而存在; 因此, 这基本表明了 &'a mut self 创建出来后, 就别想着直接访问 List<'a> 了

你可以试试这个

 pub fn get_interface(&'a mut self) -> ()

估计一样的效果, 如果我理解没有错误的话

作者 zhangzhenxiang666 2025-10-28 13:59

有佬告诉我说, 这个形变不会影响那个匿名Interface何时被drop, 那么是不是即使被drop掉了, 在借用检查器中, 可变借用依然存在, 所以编辑器才会报可变借用和借用同时存在的问题

1 共 6 条评论, 1 页