【问题标题】:Value doesn't live long enough, despite being constrained to尽管受限于
【发布时间】:2016-07-12 22:17:36
【问题描述】:

以下 Rust 代码编译失败:

pub struct UserAction<'u> {
    _act: &'u mut (FnMut() + 'u)
}

impl<'u, F: FnMut() + 'u> From<F> for UserAction<'u> {
    fn from(f: F) -> Self {
        UserAction { _act: (&mut f) as &'u mut (FnMut() + 'u) }
    }
}

我从rustc 1.10 stable 得到的错误是:

lives.rs:7:38: 7:39 error: `f` does not live long enough
lives.rs:7             UserAction { _act: (&mut f) as &'u mut (FnMut() + 'u) }
                                                ^
lives.rs:6:31: 8:10 note: reference must be valid for the lifetime 'u as defined on the block at 6:30...
lives.rs:6         fn from(f: F) -> Self {
                                         ^
lives.rs:6:31: 8:10 note: ...but borrowed value is only valid for the scope of function body at 6:30
lives.rs:6         fn from(f: F) -> Self {
                                         ^
error: aborting due to previous error

我不知道为什么这是一个错误; F 类型的寿命至少与 'u 的寿命一样长,因为它受到限制。我错过了什么,我该如何解决这个错误?

【问题讨论】:

    标签: compiler-errors closures rust lifetime


    【解决方案1】:

    作为mcarton says,您将闭包的所有权传递给函数,然后尝试获取对它的引用。庆幸编译器发现了错误并阻止您使用对某些会导致内存损坏的超出范围的变量的引用。

    限制F: FnMut() + 'u 规定F 必须是实现FnMut 特征并且包含比'u 寿命更长的引用 的类型。它并没有说F 本身必须比那个生命周期更长。事实上,我们可以看到f在方法退出后没有所有者,所以它的生命周期就结束了——这就是错误。

    应该工作的最直接等效方法是使用 boxed trait object 而不是 trait object reference

    pub struct UserAction<'u> {
        _act: Box<FnMut() + 'u>,
    }
    
    impl<'u, F: FnMut() + 'u> From<F> for UserAction<'u> {
        fn from(f: F) -> Self {
            UserAction { _act: Box::new(f) }
        }
    }
    

    另一种选择是渗透泛型类型:

    pub struct UserAction<F> {
        _act: F,
    }
    
    impl<F: FnMut()> From<F> for UserAction<F> {
        fn from(f: F) -> Self {
            UserAction { _act: f }
        }
    }
    

    【讨论】:

    • 谢谢!我最终选择了基于Box 的方法。
    【解决方案2】:

    f 是该 from 方法的本地,所以所有对它的引用。 你想要的是:

    pub struct UserAction<'u> {
        _act: &'u mut (FnMut() + 'u)
    }
    
    impl<'u, F: FnMut() + 'u> From<&'u mut F> for UserAction<'u> {
    //                             ^^^^^^^
        fn from(f: &'u mut F) -> Self {
    //             ^^^^^^^
            UserAction { _act: f as &'u mut (FnMut() + 'u) }
        }
    }
    

    【讨论】:

    • 编译时,我现在根本无法使用它。表达式Self::from(&amp;mut || {}) 会导致错误“借用值的寿命不够长”。
    • @Ptharien'sFlame 你可以这样做,如果你将闭包放在一个持续时间比Self::from 的结果更长的变量中 - 这将允许引用足够长的时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 2016-03-26
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2021-04-13
    相关资源
    最近更新 更多