如何指定方法参数的生命周期必须比自身的生命周期长?

How to specify that method argument must have longer lifetime than self's lifetime?

我想为 C 库编写一个安全的 Rust 包装器。我需要用 Rust 的术语表达 C 的库原始指针所有权规则。

该库具有其私有结构,例如:struct handle {void *_data} 并将 setter 公开为 set_data(struct handle*, void *data)

我想制作该方法的 Rust 版本,其签名为“data 必须至少与 handle 一样长”。

我试过:

set_data(&'a self, &'a data:…)

但借用检查器似乎将其应用于该函数内的生命周期,而不是对象的整个生命周期。

我也试过给impl增加生命周期,但还是不行。完整测试用例:

#![allow(unused_variables)]
struct Handle<'a>;

impl<'a> Handle<'a> {
    pub fn set_data(&'a mut self, data: &'a DropCanary) {
        // save data raw ptr
    }

    pub fn use_data(&'a self) {
        // use data raw ptr
        println!("alive?");
    }
}

fn main() {
    let mut handle = Handle;
    let long_enough_lifetime = DropCanary{label:"long"};

    {
        let short_lifetime = DropCanary{label:"short"};
        handle.set_data(&short_lifetime); // This shouldn't be allowed!
        handle.set_data(&long_enough_lifetime); // This is OK
    }

    handle.use_data();
}

/// --- just for testing ---

struct DropCanary {
    label: &'static str,
}

impl Drop for DropCanary {
    fn drop(&mut self) {
        println!("dropped: {}", self.label);
    }
}

问题是下面的代码compiles并输出:

dropped: short
alive?
dropped: long

所以它会导致释放后使用,因为 Rust 不知道 short_lifetime 必须比 handle 长寿。

这应该适合你 (playpen)。

您的示例编译的原因很简单,因为您没有在示例中的结构中使用生命周期。由于您不使用它,因此对它没有任何限制,也可以将其省略。如果您不在结构中存储任何具有生命周期的数据,则可以使用标记类型替换我使用的选项 here.

#![allow(unused_variables)]
struct Handle<'a>(Option<&'a DropCanary>);

impl<'a> Handle<'a> {
    pub fn set_data(&mut self, data: &'a DropCanary) {
        self.0 = Some(data);
        // save data raw ptr
    }

    pub fn use_data(&self) {
        // use data raw ptr
        println!("alive?");
    }
}

fn main() {
    let mut handle = Handle(None);
    let long_enough_lifetime = DropCanary{label:"long"};

    {
        let short_lifetime = DropCanary{label:"short"};
        //handle.set_data(&short_lifetime); // This shouldn't be allowed!
        handle.set_data(&long_enough_lifetime); // This is OK
    }

    handle.use_data();
}

/// --- just for testing ---

struct DropCanary {
    label: &'static str,
}

impl Drop for DropCanary {
    fn drop(&mut self) {
        println!("dropped: {}", self.label);
    }
}