I'd like to have a struct, Quox which can optionally have each type of closure that there can be(Fn, FnMut and FnOnce) around. I typed it this way:
#[derive(Default, Debug)]
pub struct Quox<Tfn: Fn(&Person) + Sized, Tfnmut: FnMut(&mut Person) + Sized, Tfnonce: FnOnce(&Person) + Sized> {
soft_closure: Option<Tfn>,
mut_closure : Option<Tfnmut>,
move_closure: Option<Tfnonce>,
}
Now, when instantiating it i do it via Box because Rust complains the trait Sized is not implemented for `dyn Fn()`rustcE0277. (Maybe there is a better way or i misunderstand trait objects?):
pub fn main(){
let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
move_closure: None,
mut_closure : None,
soft_closure: None,
};
...
}
- What really perplexes me further is when i create the corresponding types of closures -- why i can assign them willy-nilly to the fields inside
qx:
pub fn main(){
let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
move_closure: None,
mut_closure : None,
soft_closure: None,
};
let greeting = "Hi. We are moving soon!".to_string();
let clsr_move = move |p:&Person| println!("Hi, {}. {} says: {}", p.name, p.name, greeting);
let only_a_ref_clsr = |p:&Person| println!("Hi, {}.",p.name );
// qx.move_closure = Some(Box::new(clsr_move)); // expected
// qx.soft_closure = Some(Box::new(only_a_ref_clsr)); // expected
qx.soft_closure = Some(Box::new(clsr_move)); // Why is this valid???
qx.move_closure = Some(Box::new(only_a_ref_clsr)); // Ok Fn is supertrait to FnOnce
}
Again, what's confusing is that i'm getting no error for trying to assign a (seemingly) FnMut to Fn.
- Furthermore... why assigning the
Boxto an intermediary variable now throws error???
pub fn main(){
let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
move_closure: None,
mut_closure : None,
soft_closure: None,
};
let greeting = "Hi. We are moving soon!".to_string();
let clsr_move = move |p:&Person| println!("Hi, {}. {} says: {}", p.name, p.name, greeting);
let only_a_ref_clsr = |p:&Person| println!("Hi, {}.",p.name );
let someboxmove = Some(Box::new(only_a_ref_clsr));
qx.soft_closure = someboxmove; // Invalid.
}
The error i'm getting is:
let someboxmove: Option<Box<|&Person| -> ()>>
Go to Option | Box | Person | Global
mismatched types
expected enum `Option<Box<dyn for<'r> Fn(&'r traitobjects::Person)>>`
found enum `Option<Box<[closure@src/traitobjects.rs:49:27: 49:66]>>`rustcE0308
traitobjects.rs(49, 27): the found closure
traitobjects.rs(66, 5): expected due to the type of this binding