rust 对'Box〈dyn Fn(Args)>'的解释感到困惑

ntjbwcob  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(175)

我真的不知道该怎么问这个问题,但有人能解释一下为什么会这样吗?
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=969cf50f66746c4aa3941200e01f1570

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, ());
}

但不是这个
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1534d9b49327272ddbbd04826efd644a

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>`
kuarbcqp

kuarbcqp1#

我们把from_member()'a称为'a1,把from_member_mut()'a称为'a2,如果'a1'a2重叠,这是一个错误,test'a2借用,而它被'a1借用,那么'a1'a2是什么呢?
最短的时间是从创建SlotFn(对于每个SlotFn)对象到销毁它,因为在这段时间内SlotFn可以访问'a的数据。
在第一段代码中,我们可以提前销毁SlotFn,因为它们没有实现Drop,因此在销毁时无法执行任何操作,因此无法观察到提前销毁。因此,在第一段代码中,编译器将'a1'a2分别缩短到emit_mut()emit(),因此它们不会冲突。
然而在第二种情况下,它们可能实现了Drop-dyn Trait总是被认为实现了Drop,因为编译器不知道里面是什么-因此,它们的生命周期必须在块的末尾结束,因为Drop可以观察到'a

相关问题