我一直在尝试在Rust中创建一个简单的解释器。这是一段代码片段。
use std::vec::Vec;
use std::option::Option;
use std::borrow::Borrow;
trait Data {}
trait Instruction {
fn run(&self, stack: &mut Vec<Box<Data>>) -> Option<&Data>;
}
struct Get {
stack_index: usize,
}
impl Instruction for Get {
fn run(&self, stack: &mut Vec<Box<Data>>) -> Option<&Data> {
Some(stack[self.stack_index].borrow())
}
}
fn main() {}
上面包含一条简单的Get
指令。它有一个run
方法,它只返回给定堆栈Data
中的值。 Data
是一个抽象的特征,实际上代表任何类型的数据。我还没有实现Data
。
但是,编译代码会生成错误代码E0495
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> <anon>:17:14
|
17 | Some(stack[self.stack_index].borrow())
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:63...
--> <anon>:16:64
|
16 | fn run(&self, stack: &mut Vec<Box<Data>>) -> Option<&Data> {
| ________________________________________________________________^ starting here...
17 | | Some(stack[self.stack_index].borrow())
18 | | }
| |_____^ ...ending here
note: ...so that reference does not outlive borrowed content
--> <anon>:17:14
|
17 | Some(stack[self.stack_index].borrow())
| ^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the body at 16:63...
--> <anon>:16:64
|
16 | fn run(&self, stack: &mut Vec<Box<Data>>) -> Option<&Data> {
| ________________________________________________________________^ starting here...
17 | | Some(stack[self.stack_index].borrow())
18 | | }
| |_____^ ...ending here
note: ...so that expression is assignable (expected std::option::Option<&Data>, found std::option::Option<&Data>)
--> <anon>:17:9
|
17 | Some(stack[self.stack_index].borrow())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我错过了什么?
答案 0 :(得分:3)
如What is the return type of the indexing operation on a slice?中所述,stack[self.stack_index]
将返回值中的值。然后,您尝试返回对局部变量的引用,这是Is there any way to return a reference to a variable created in a function?中所述的不允许的。
实际上,您需要执行Some(&*stack[self.stack_index])
,它会取消引用Box
以获取Data
,然后重新引用它。由于您的实现不符合lifetime elision的规则,因此您需要为特征方法和实现添加显式生命周期:
fn run<'a>(&self, stack: &'a mut Vec<Box<Data>>) -> Option<&'a Data>
我可能会使用get
和map
来实现它:
stack.get(self.stack_index).map(Box::as_ref)