使用非静态引用的方法静态声明的结构
Statically declared struct with method taking a non-static reference
我正在尝试使用静态定义的结构 (Outer
)。 Outer
有一个引用结构 (Context
) 的方法,其中 Context
的生命周期短于 Outer
.
下面的代码也可以在这个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 编译器 expects/requires context
的生命周期与 outer
的生命周期相同 ('static
)。 outer
比 context
长寿应该没问题,因为它只在 use_context()
方法的生命周期内使用 context
吗?
此处省略了生命周期:
static mut outer: Outer<'static, Context> = unsafe {
^^^^^^^
由于这是一个静态变量,编译器将推断出 'static
生命周期,因此 outer
的完整类型是 Outer<'static, Context<'static>>
.
因此,在对use_context
的调用中,context
参数的类型是&mut Context<'static>
。但是,use_outer_with_context
正在传递 &mut Context<'a>
('a
在源代码中被省略)。
这里的问题是 T
需要提前指定,而实际上,由于 Context<'a>
中的生命周期,T
可能会因调用而异。 =33=]
可以通过将 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);
}
}
注意:我在 Outer::use_context
上将 &'a mut self
更改为 &mut self
; 'a
是不必要的,会导致编译器错误。
您可能不想 T
移动到单个方法是有原因的。在那种情况下,我不知道可行的解决方案。如果 Rust 有 generic associated types,那么可以用生命周期参数 pending application 来表示 Context
。不幸的是,从 Rust 1.41.0 开始,泛型关联类型并未实现。
我正在尝试使用静态定义的结构 (Outer
)。 Outer
有一个引用结构 (Context
) 的方法,其中 Context
的生命周期短于 Outer
.
下面的代码也可以在这个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 编译器 expects/requires context
的生命周期与 outer
的生命周期相同 ('static
)。 outer
比 context
长寿应该没问题,因为它只在 use_context()
方法的生命周期内使用 context
吗?
此处省略了生命周期:
static mut outer: Outer<'static, Context> = unsafe {
^^^^^^^
由于这是一个静态变量,编译器将推断出 'static
生命周期,因此 outer
的完整类型是 Outer<'static, Context<'static>>
.
因此,在对use_context
的调用中,context
参数的类型是&mut Context<'static>
。但是,use_outer_with_context
正在传递 &mut Context<'a>
('a
在源代码中被省略)。
这里的问题是 T
需要提前指定,而实际上,由于 Context<'a>
中的生命周期,T
可能会因调用而异。 =33=]
可以通过将 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);
}
}
注意:我在 Outer::use_context
上将 &'a mut self
更改为 &mut self
; 'a
是不必要的,会导致编译器错误。
您可能不想 T
移动到单个方法是有原因的。在那种情况下,我不知道可行的解决方案。如果 Rust 有 generic associated types,那么可以用生命周期参数 pending application 来表示 Context
。不幸的是,从 Rust 1.41.0 开始,泛型关联类型并未实现。