对如何解释"Box<dyn Fn(Args)>"感到困惑



我真的不知道如何提出这个问题,但是谁能解释一下为什么这个工作:

https://play.rust-lang.org/?version=stable&模式= debug&版= 2018,要点= 969 cf50f66746c4aa3941200e01f1570

enum SlotFn<'a, Comp, Args = (), R = ()> 
where Args: 'static,
R: Default + 'static,
{
SimpleFn(fn(Args) -> R),
MemberFn(fn(&'a Comp) -> R),
MemberFnMut(fn(&'a mut Comp, Args) -> R),
}
impl<'a, Comp, Args, R> SlotFn<'a, Comp, Args, R> 
where Args: 'static,
R: Default + 'static,{
fn from_member(f: fn(&'a Comp) -> R) -> Self{
SlotFn::MemberFn(f)
}
fn from_member_mut(f: fn(&'a mut Comp, Args) -> R) -> Self {
SlotFn::MemberFnMut(f)
}
fn emit(&self, comp: &'a Comp, args: Args) -> R {
match self {
SlotFn::SimpleFn(f) => f(args),
SlotFn::MemberFn(f) => f(comp),
_ => Default::default()
}
}
fn emit_mut(&mut self, comp: &'a mut Comp, args: Args) -> R {
match self {
SlotFn::MemberFnMut(f) => f(comp, args),
_ => Default::default()
}
}
}

struct Test(u32);
impl Test {
fn reffunc(&self) {
println!("value: {}", self.0);
}
fn reffunc_mut(&mut self, val: u32) {
self.0 = val;
}
}

fn main() {
let mut test = Test(0);
let slot = SlotFn::from_member(Test::reffunc);
let mut mslot = SlotFn::from_member_mut(Test::reffunc_mut);
mslot.emit_mut(&mut test, 10);
slot.emit(&test, ());
}

而不是this:

https://play.rust-lang.org/?version=stable&模式= debug&版= 2018,要点= 1534 d9b49327272ddbbd04826efd644a

enum SlotFn<'a, Comp, Args = (), R = ()> 
where Args: 'static,
R: Default + 'static,
{
SimpleFn(Box<dyn Fn(Args) -> R + Send + Sync + 'static>),
MemberFn(Box<dyn Fn(&'a Comp) -> R + Send + Sync + 'static>),
MemberFnMut(Box<dyn FnMut(&'a mut Comp, Args) -> R + Send + Sync + 'static>),
}
impl<'a, Comp, Args, R> SlotFn<'a, Comp, Args, R> 
where Args: 'static,
R: Default + 'static,{

fn from_member<F>(f: F) -> Self where F: Fn(&'a Comp) -> R + Send + Sync + 'static{
SlotFn::MemberFn(Box::new(f))
}
fn from_member_mut<F>(f: F) -> Self where F: FnMut(&'a mut Comp, Args) -> R + Send + Sync + 'static{
SlotFn::MemberFnMut(Box::new(f))
}
fn emit(&self, comp: &'a Comp, args: Args) -> R {
match self {
SlotFn::SimpleFn(f) => f(args),
SlotFn::MemberFn(f) => f(comp),
_ => Default::default()
}
}
fn emit_mut(&mut self, comp: &'a mut Comp, args: Args) -> R {
match self {
SlotFn::MemberFnMut(f) => f(comp, args),
_ => Default::default()
}
}
}

struct Test(u32);
impl Test {
fn reffunc(&self) {
println!("value: {}", self.0);
}
fn reffunc_mut(&mut self, val: u32) {
self.0 = val;
}
}

fn main() {
let mut test = Test(0);
let slot = SlotFn::from_member(Test::reffunc);
let mut mslot = SlotFn::from_member_mut(Test::reffunc_mut);
mslot.emit_mut(&mut test, 10);
slot.emit(&test, ());
}
在第二种情况下,我得到以下错误:
error[E0502]: cannot borrow `test` as immutable because it is also borrowed as mutable
mutable borrow might be used here, when `mslot` is dropped and runs the destructor for type `SlotFn<'_, Test, u32>`

from_member()'a'a1,from_member_mut()'a'a2。如果'a1'a2重叠,这是一个错误,test'a2可变地借用,而'a1则被借用。那么'a1'a2是什么呢?

它们最短的时间是从创建SlotFn(每个SlotFn都有自己的)对象到销毁它,因为在这段时间里SlotFn可以访问'a的数据。

在第一个代码中,我们可以提前销毁SlotFns,因为它们不实现Drop,因此它们在销毁时不能执行任何操作,因此无法观察到提前销毁。因此,在第一段代码中,编译器将'a1'a2分别缩短到emit_mut()emit(),因此它们不冲突。

在第二种情况下,它们可能实现Drop——dyn Trait总是被认为实现了Drop,因为编译器不知道里面是什么——因此,它们的生命周期必须在块的末尾结束,因为Drop可以观察到'a。所以它们是冲突的。

最新更新