Fn 闭包类型的静态生命周期是什么意思?

Max*_*ber 8 closures lifetime rust

如果我按照 rustc 的指示操作,并将绑定更改为,以下错误就会消失

where F: Fn() -> () + 'static

pub struct Struct(Box<dyn Fn() -> ()>);
pub fn example<F>(f: F)
where
    F: Fn() -> ()
{
    Struct(Box::new(|| ())); // ok
    Struct(Box::new(f)); // error: The parameter type `F` may not live long eneough
                         // help: consider adding an explicit lifetime bound: `F: 'static`
}
Run Code Online (Sandbox Code Playgroud)

但是,我只是不明白“静态”在这里意味着什么。这似乎并不意味着封闭本身会永远存在。

至少,关闭似乎不会永远存在。如果我让闭包拥有一些数据,那么该数据会在某个时刻被删除,这让我怀疑闭包已被删除:

pub struct Struct(Box<dyn Fn() -> ()>);

#[derive(Debug)]
struct DropMe;
impl Drop for DropMe {
    fn drop(&mut self) {
        println!("dropped");
    }
}

/// prints:
///     "got DropMe"
///     "got DropMe"
///     "dropped"
///     "end of program"
pub fn main() {
    let d = DropMe;
    example(move || {
        println!("got {:?}", d);
    });
    println!("end of program")
}

pub fn example<F>(f: F)
where
    F: Fn() -> () + 'static
{
    let s = Struct(Box::new(f));
    s.0();
    s.0();
}
Run Code Online (Sandbox Code Playgroud)

闭包生命周期是'static上限而不是下限?'static作为上限是有意义的,那么example就会说“给我一个我可以根据需要保留的函数”,这在实践中可能会小于生命'static周期。

如何判断何时+ 'lifetime添加'lifetime为上限和下限?Rustonomicon 关于子类型+方差的章节似乎没有涵盖这一点,而且我在 Rust Book 或 Rust Reference 中找不到我正在寻找的信息。

egg*_*yal 6

T: 'a不是对的实例的生命周期的限制T,而是对借用的事物T(如果有的话)的生命周期的限制:也就是说,所有借用的生命周期都 T必须比 的生命周期长'a

因此F: Trait + 'static要求任何借用都是F终身的'static(或更长时间,这不存在),无论Trait在这种情况下是Fn() -> ()

在你的情况下,闭包取得了所有权d(并借用了&'static str文字);因此它满足F: 'static. 但是,如果不是仅仅move || ...借用闭包d|| ...那么它将无法满足'static(因为借用的生命周期d不能超过调用的范围main)。


Bal*_*Ben 1

我认为问题在于Struct没有通用的生命周期参数,这意味着其实例之一的生命周期没有名称。盒子实例的函数Struct(显然)必须与实例一样长,但向编译器保证这一点的唯一方法是给它一个命名的生命周期。但由于Struct没有生命周期参数,唯一保证持续足够长的命名生命周期是'static

为了解决这个问题,您可以给出Struct一个通用的生命周期参数,然后限制装箱函数也只能存活那么长时间。

pub struct Struct<'a>(Box<dyn 'a + Fn() -> ()>);
pub fn example<F>(f: F)
where
    F: Fn() -> (),
{
    Struct(Box::new(|| ())); // ok
    Struct(Box::new(f)); // also ok; 'a will be inferred from the lifetime of f
}
Run Code Online (Sandbox Code Playgroud)