首页 > 解决方案 > 静态声明的结构,方法采用非静态引用

问题描述

我正在尝试使用Outer静态定义的结构()。Outer有一个方法,它引用一个 struct ( Context),其中的生命周期ContextOuter.

在这个rust playground也可以找到以下代码:

use std::marker::PhantomData;

trait Doable {
    fn do_thing(&self) -> u8;
}

struct Stuff(u8);

struct Context<'a> {
    stuff: &'a mut Stuff,
}

impl<'a> Doable for Context<'a> {
    fn do_thing(&self) -> u8 {
        self.stuff.0 + 1
    }
}

struct Outer<'a, T> {
    buffer: &'a mut [u8],
    used: u8,
    phantom_context: PhantomData<T>,
}

impl<'a, T> Outer<'a, T>
where T: Doable
{
    fn use_context(&'a mut self, context: &mut T) {
        self.used = context.do_thing();
    }
}

fn use_outer_with_context(context: &mut Context) {
    static mut buffer: [u8; 64] = [0u8; 64];
    static mut outer: Outer<'static, Context> = unsafe {
        Outer {
            buffer: &mut buffer,
            used: 0,
            phantom_context: PhantomData,
        }
    };

    unsafe {outer.use_context(context)};
}

fn main() {

    let mut s = Stuff(4);

    let context = Context {stuff: &mut s};

    use_outer_with_context(&mut context);

}

当我尝试编译此代码时,出现以下错误:

error[E0621]: explicit lifetime required in the type of `context`
  --> src/lib.rs:45:31
   |
35 | fn use_outer_with_context(context: &mut Context) {
   |                                    ------------ help: add explicit lifetime `'static` to the type of `context`: `&mut Context<'static>`
...
45 |     unsafe {outer.use_context(context)};
   |                               ^^^^^^^ lifetime `'static` required

我很难理解为什么 rust 编译器期望/要求的生命context周期'staticouter. outlive 不应该可以吗outercontext因为它只context在方法的生命周期内使用use_context()

标签: rustlifetime

解决方案


这里有一个省略的生命周期:

static mut outer: Outer<'static, Context> = unsafe {
                                 ^^^^^^^

由于这是一个静态变量,编译器将推断生命周期,因此is'static的完整类型。outerOuter<'static, Context<'static>>

因此,在对 的调用中,参数use_context的类型是。但是,正在传递一个(源中省略了)。context&mut Context<'static>use_outer_with_context&mut Context<'a>'a

这里的问题是T需要提前指定,而实际上,T由于Context<'a>.

您的示例可以通过T从结构移动到use_context方法来工作。

struct Outer<'a> {
    buffer: &'a mut [u8],
    used: u8,
}

impl<'a> Outer<'a>
{
    fn use_context<T>(&mut self, context: &mut T)
    where
        T: Doable,
    {
        self.used = context.do_thing();
    }
}

fn use_outer_with_context(context: &mut Context) {
    static mut buffer: [u8; 64] = [0u8; 64];
    static mut outer: Outer<'static> = unsafe {
        Outer {
            buffer: &mut buffer,
            used: 0,
        }
    };

    unsafe {
        outer.use_context(context);
    }
}

注意:我&'a mut self改为&mut selfon Outer::use_context; 这'a是不必要的,并且可能导致编译器错误。

可能有你不想转向T单独方法的原因。在那种情况下,我不知道可行的解决方案。如果 Rust 有泛型关联类型,那么就有可能Context用生命周期参数挂起的应用程序来表示。不幸的是,通用关联类型从 Rust 1.41.0 开始没有实现。


推荐阅读