将值传递给 Enum 变体时出现 Rust 'use of moved value' 错误
Rust 'use of moved value' error when passing value into Enum variant
我对 Rust 很陌生(才几天)。当然,我已经被所有权的概念困住了。
我有一个相当冗长的问题,所以这里是我使用的所有相关声明:
pub struct ThePrimaryStruct<'a> {
frames: Vec<Frame<'a>>,
stack: Vec<Object<'a>>,
ip: usize
}
pub struct FunctionObject<'a> {
pub min_arity: i32,
pub max_arity: i32,
pub chunk: Chunk<'a>,
pub name: &'a str,
}
pub struct Frame<'a> {
pub function: FunctionObject<'a>,
// ... other struct members
}
pub struct Chunk<'a> {
pub codes: Vec<OpCode>, // OpCode is an enum
pub locations: Vec<(i64, i64)>,
pub constants: Vec<Object<'a>>
}
pub enum Object<'a> {
Function(FunctionObject<'a>),
// Other enum variants
}
以上代码没有问题。当我为 ThePrimaryStruct
实现以下方法时出现问题:
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- Source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
运行 这会导致错误:
error[E0382]: use of moved value: `func`
|
37 | let func: FunctionObject = Compiler::compile(source);
| ---- move occurs because `func` has type `FunctionObject<'_>`, which does not implement the `Copy` trait
...
40 | self.stack.push(Object::Function(func));
| ---- value moved here
...
44 | function: func,
| ^^^^ value used here after move
我明白为什么会出现这个错误(或者至少我想我明白了):Object::Function
变体取得 func
的所有权,然后在我们完成推送对象时从内存中删除进入 self.stack
。然后这会与 Frame
结构的初始化产生冲突,因为我试图使用一个不再存在的值。
我已经尝试为结构 FunctionObject
实现 Copy
特性,但这会产生更多问题,因为 FunctionObject
有一个 Chunk<'a>
类型的成员,它本身有向量成员。
编辑:
克隆绝对可以解决问题。但是,通过克隆 FunctionObject
,我将复制 chunk
中的数据,它可以是任意长的大小。在使用 Object::Function(&func)
的 stack
和使用 Frame { function: &func, ... }
的 frame
中引用 FunctionObject
会导致 'func' does not live long enough
错误。
我正在尝试做的事情是否存在根本性错误?
您似乎有一个 FunctionObject
想要同时存储在 stack
和 frame
中。
更好的解决方案可能是不将 FunctionObject
直接存储在堆栈和帧上,而是使用 smart pointers。
我将向您展示一个使用 Rc
的解决方案,但是,您似乎在制作一个编译器,因此您可能需要一个不同的数据结构来存储您的函数对象,例如 arena .
下面的代码只包括我对你原来的修改,不过你也可以看看on the playground where I got it to compile:
pub struct Frame<'a> {
pub function: std::rc::Rc<FunctionObject<'a>>,
// ... other struct members
}
pub enum Object<'a> {
Function(std::rc::Rc<FunctionObject<'a>>),
// Other enum variants
}
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
let func = std::rc::Rc::new(func);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func.clone()));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- No longer source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
Rc
通过引用计数来管理一个对象。
当删除最后一个 Rc
时,值 (FunctionObject
) 也将被删除。
在 func
上使用 .clone()
复制引用并增加计数,但不复制基础对象。
我对 Rust 很陌生(才几天)。当然,我已经被所有权的概念困住了。
我有一个相当冗长的问题,所以这里是我使用的所有相关声明:
pub struct ThePrimaryStruct<'a> {
frames: Vec<Frame<'a>>,
stack: Vec<Object<'a>>,
ip: usize
}
pub struct FunctionObject<'a> {
pub min_arity: i32,
pub max_arity: i32,
pub chunk: Chunk<'a>,
pub name: &'a str,
}
pub struct Frame<'a> {
pub function: FunctionObject<'a>,
// ... other struct members
}
pub struct Chunk<'a> {
pub codes: Vec<OpCode>, // OpCode is an enum
pub locations: Vec<(i64, i64)>,
pub constants: Vec<Object<'a>>
}
pub enum Object<'a> {
Function(FunctionObject<'a>),
// Other enum variants
}
以上代码没有问题。当我为 ThePrimaryStruct
实现以下方法时出现问题:
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- Source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
运行 这会导致错误:
error[E0382]: use of moved value: `func`
|
37 | let func: FunctionObject = Compiler::compile(source);
| ---- move occurs because `func` has type `FunctionObject<'_>`, which does not implement the `Copy` trait
...
40 | self.stack.push(Object::Function(func));
| ---- value moved here
...
44 | function: func,
| ^^^^ value used here after move
我明白为什么会出现这个错误(或者至少我想我明白了):Object::Function
变体取得 func
的所有权,然后在我们完成推送对象时从内存中删除进入 self.stack
。然后这会与 Frame
结构的初始化产生冲突,因为我试图使用一个不再存在的值。
我已经尝试为结构 FunctionObject
实现 Copy
特性,但这会产生更多问题,因为 FunctionObject
有一个 Chunk<'a>
类型的成员,它本身有向量成员。
编辑:
克隆绝对可以解决问题。但是,通过克隆 FunctionObject
,我将复制 chunk
中的数据,它可以是任意长的大小。在使用 Object::Function(&func)
的 stack
和使用 Frame { function: &func, ... }
的 frame
中引用 FunctionObject
会导致 'func' does not live long enough
错误。
我正在尝试做的事情是否存在根本性错误?
您似乎有一个 FunctionObject
想要同时存储在 stack
和 frame
中。
更好的解决方案可能是不将 FunctionObject
直接存储在堆栈和帧上,而是使用 smart pointers。
我将向您展示一个使用 Rc
的解决方案,但是,您似乎在制作一个编译器,因此您可能需要一个不同的数据结构来存储您的函数对象,例如 arena .
下面的代码只包括我对你原来的修改,不过你也可以看看on the playground where I got it to compile:
pub struct Frame<'a> {
pub function: std::rc::Rc<FunctionObject<'a>>,
// ... other struct members
}
pub enum Object<'a> {
Function(std::rc::Rc<FunctionObject<'a>>),
// Other enum variants
}
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
let func = std::rc::Rc::new(func);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func.clone()));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- No longer source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
Rc
通过引用计数来管理一个对象。
当删除最后一个 Rc
时,值 (FunctionObject
) 也将被删除。
在 func
上使用 .clone()
复制引用并增加计数,但不复制基础对象。