I’m writing a calculator application in Rust, which has an Action
enum class describing either an operation or a value:
#[derive(Clone)]
enum Operation<W: Write> {
ValueNone(fn() -> MyResult<Value>),
ValueOne(fn(Value) -> MyResult<Value>),
ValueTwo(fn(Value, Value) -> MyResult<Value>),
ValueAll(fn(Vec<Value>) -> MyResult<Value>),
EngineNone(fn(&mut Engine<W>, &mut W) -> MyResult<bool>),
}
#[derive(Clone, PartialEq)]
struct Value {
number: Option<BigRational>,
meaning: Meaning,
comment: Option<String>,
}
#[derive(Clone)]
enum Action<W: Write> {
Operation(Rc<Operation<W>>),
Value(Value),
}
The Operation::EngineNone
enum value is intended to encapsulate operations like “show stack” or “show help”.
For various reasons, I would like to clone an action in certain situations:
fn apply_action<W: Write>(action: Action<W>) {
let action = action.clone();
...
}
However, this results in a compiler error:
error[E0599]: the method `clone` exists for enum `Action<W>`, but its trait bounds were not satisfied
--> src/engine.rs:33:25
|
33 | let action = action.clone();
| ^^^^^ method cannot be called on `Action<W>` due to unsatisfied trait bounds
|
::: src/action.rs:12:1
|
12 | pub enum Action<W: Write> {
| ------------------------- method `clone` not found for this enum because it doesn't satisfy `Action<W>: Clone`
|
note: trait bound `W: Clone` was not satisfied
--> src/action.rs:11:10
|
11 | #[derive(Clone)]
| ^^^^^ unsatisfied trait bound introduced in this `derive` macro
help: consider restricting the type parameter to satisfy the trait bound
|
32 | fn apply_action<W: Write>(action: Action<W>) where W: Clone {
| ++++++++++++++
I cannot implement the suggested change, because I am passing a std::io::Stdout
object, which does not implement Clone
. However, I do not understand why a W
needs to be cloneable here, because I am not storing it anywhere in Action
, merely passing it to the function defined in the Operation::EngineNone
enum value.
Can anyone (i) explain why Rust is complaining here, and (ii) suggest a workaround?