告诉 Rust 编译器返回值不包含构造函数中提供的引用

问题描述 投票:0回答:1

我有一些包含一些数据的结构,如下所示:

struct A {
    // Some data
}

struct B<'s> {
    a: &'s mut A
    c: C<'s>
}

impl<'s> B<'s> {
    fn new(a: &'s mut A) -> B<'s> {
        let c = C::new();
        B { a, c }
    }

    fn extract_c(self) -> C<'s> {
        self.c
    }
}

struct C<'s> {
    // Some other data not referencing A in any way
}

我还有创建和修改所述结构的函数,如下所示:

fn modify(b: &mut B) {
    // Modifies b.a and b.c
}

fn construct_c<'s>(a: &'s mut A) -> C<'s> {
    let mut b = B::new(a); // C is created in B::new
    modify(&mut b);
    b.extract_c()
}

我想在其他地方使用

construct_c
,这样我可以在获得调用结果后再次引用 A ,如下所示:

fn main() {
    let mut a = A::new();
    let c = construct_c(&mut a);  // First mutable borrow of `a`
    println!("{a}");   // Second borrow of `a`
    let result = do_sth_with_c(c);  // Move of `c`
    do_sth_with_a(a);
    // Some other code...
}

但是,当我尝试这样做时,编译器说当我调用

do_sth_with_c
时,我正在使用
a
的第一个可变借用,即使
c
不保存对提供给
a
的引用
construct_c

当我删除

println!("{a}");
do_sth_with_a
时,代码可以编译,但我确实需要打印该信息并在调用
do_sth_with_c
之前执行此操作。有没有办法告诉编译器
C
a
的引用一无所知,并且在调用
construct_c
后创建新引用是安全的?

编辑: 当我用

&mut A
替换所有引用
Rc<RefCell<A>>
时,代码将编译。但是有没有另一种方法而不使用
Rc
RefCell

rust reference return-value borrow-checker
1个回答
0
投票

您在关于

C
的评论中写道,“其他一些数据未以任何方式引用
A
”。但是通过使用相同的生命周期,您可以告诉编译器它们“是”相关的。所以,改变你的定义 struct B<'s> { a: &'s mut A c: C<'s> } fn construct_c<'s>(a: &'s mut A) -> C<'s> { let mut b = B::new(a); modify(&mut b); b.extract_c() }

struct B<'s, 'c> { a: &'c mut A c: C<'c> } fn construct_c<'s, 'c>(a: &'s mut A) -> C<'c> { let mut b = B::new(a); modify(&mut b); b.extract_c() }

现在每个生命周期都可以独立变化,特别是,现场的生命周期
c

允许长于

'a
也就是说,我怀疑您在未显示的部分中可能还有更多问题。令人怀疑的是 

C

有生命周期,但它是用无参数

new()
创建的。值得怀疑的是,调整后,
construct_c()
采用的是不受约束的生命周期参数
'c
,该参数不会出现在任何输入中。
C类型借用了什么数据?
为了正确使用生命周期,你必须有这个问题的答案。
您可能会尝试使用引用,其中拥有的数据会更好。

© www.soinside.com 2019 - 2024. All rights reserved.