我有一个引用计数的RefCell
s的向量,并想将(Vec
)引用的mut
传递到RefCell
s中的一个函数中。引用不必使函数调用失效。
似乎应该有可能(只用一个,像&*x.borrow_mut()
这样的东西就可以了)。我试图保留RefMut
和&mut
的中间向量来控制生存期,但是我还没有想出一种使它起作用的方法:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a> {
pub r: &'a mut SomeTrait,
}
fn foo(_: &[Wrapper]) {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
foo(&v_wrapper[..]);
}
(playground)
显然存在一生的问题:
rustc 1.11.0 (9b21dcd6a 2016-08-15)
error: borrowed value does not live long enough
--> <anon>:17:60
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^
note: reference must be valid for the block suffix following statement 2 at 17:107...
--> <anon>:17:108
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^
note: ...but borrowed value is only valid for the block at 17:71
--> <anon>:17:72
|>
17 |> let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|ref mut rm| Wrapper{ r: &mut ***rm }).collect();
|> ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
我确实控制
foo
,因此可以更改其API以使事情变得更容易,但是它在不同的模块/ crate 中,并且我真的不希望它知道我将SomeTrait
对象保留在Rc<RefCell<_>>
中。 最佳答案
首先,我同意@delnan的建议,如果可以的话,应该切换到基于迭代器的接口(interface)。
大部分代码都很好,在将foo
和Wrapper
更改为更灵活之后,我能够调整其余部分并进行编译:
use std::cell::{RefCell,RefMut};
use std::vec::Vec;
use std::rc::Rc;
trait SomeTrait {}
struct Wrapper<'a, 'b> where 'b: 'a {
pub r: &'a mut (SomeTrait + 'b),
}
fn foo<'a, 'b>(_: &'a mut [Wrapper<'a, 'b>]) where 'b: 'a {}
fn main() {
let mut v1: Vec<Rc<RefCell<SomeTrait>>> = unimplemented!();
let mut v_rm: Vec<RefMut<_>> = v1.iter_mut().map(|r| r.borrow_mut()).collect();
let mut v_wrapper: Vec<Wrapper> = v_rm.iter_mut().map(|mut rm| Wrapper{ r: &mut **rm }).collect();
foo(&mut v_wrapper[..]);
}
此处要理解的关键是,每个特征对象类型都有一个隐式生命周期,因为impl可能包含引用。没有
SomeTrait
这样的类型,只有SomeTrait + 'a
或SomeTrait + 'b
或SomeTrait + 'static
这样的类型。您的代码中的问题是Rust推断出的两件事之间不匹配。
Rc<RefCell<SomeTrait>>
的地方,Rust假设您的意思是Rc<RefCell<SomeTrait + 'static>>
。 fn foo(_: &[Wrapper]) {}
的位置,应用了不同的规则,Rust假设您的意思是fn foo<'a>(_: &'a [Wrapper<'a> + 'a])
。 天啊在这些假设下,这个难题确实没有解决办法,这就是为什么我不得不放松一下。
如果您不希望使用
'b
生存期参数,则可以抛弃它,而只需在使用它的位置(根据'b
的类型)将'static
更改为Wrapper::r
即可。灵活性较差:您将被限制为具有静态生存期的SomeTrait
impls。关于rust - 将Vec <Rc <RefCell <T >>>转换为&[&mut T],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39701253/