I was wondering if there was a way to force a variable to be a trait object. I had a situation where I wanted to get a closure from a match
, so I boxed the closures up. However, the compiler still got angry about the match arms having incompatible types.
I have the following condensed example (playground):
#![allow(dead_code)]
struct Noise {
callback: Option<Box<dyn Fn(&Self, f64) -> f64 + Sync>>
}
impl Noise {
pub fn noise(&self, _p: f64) -> f64 {
unimplemented!()
}
pub fn wrap(mut self, freq: f64) -> Self {
//let new_callback: Box<dyn Fn(&Self, f64) -> f64 + Sync> = match self.callback {
let new_callback = match self.callback {
Some(callback) => Box::new(
move |noise: &Self, p: f64| callback(noise, p * freq)
),
None => Box::new(
move |noise: &Self, p: f64| noise.noise(p * freq)
)
};
self.callback = Some(new_callback);
self
}
}
which gives
Compiler output
Compiling playground v0.0.1 (/playground)
error[E0308]: `match` arms have incompatible types
--> src/lib.rs:17:21
|
13 | let new_callback = match self.callback {
| ____________________________-
14 | | Some(callback) => Box::new(
| _|_______________________________-
15 | | | move |noise: &Self, p: f64| callback(noise, p * freq)
16 | | | ),
| |_|_____________- this is found to be of type `std::boxed::Box<[closure@src/lib.rs:15:17: 15:70 callback:_, freq:_]>`
17 | | None => Box::new(
| _|_____________________^
18 | | | move |noise: &Self, p: f64| noise.noise(p * freq)
19 | | | ),
| |_|_____________^ expected closure, found a different closure
20 | | };
| |_________- `match` arms have incompatible types
|
= note: expected type `std::boxed::Box<[closure@src/lib.rs:15:17: 15:70 callback:_, freq:_]>`
found struct `std::boxed::Box<[closure@src/lib.rs:18:17: 18:66 freq:_]>`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
Of course, I can solve this by giving new_callback
an explicit type, as seen in the commented out line. But I was wondering if there was a better/shorter way to convince the compiler that these arms have compatible types.