Search code examples
rustclosures

Rust no two closures, even if identical, have the same type


How do to put two closures with the same definition into a Vec?

Here is a minimal reproducible example:

fn main() {
    let mut vec = Vec::new();
    vec.push(Box::new(|| println!("test")));
    vec.push(Box::new(|| println!("test2")));
    
    vec.iter().for_each(|f| (f)());
}

Which failed on compiling with following error:

error[E0308]: mismatched types
 --> src/main.rs:4:23
  |
3 |     vec.push(Box::new(|| println!("test")));
  |                       -- the expected closure
4 |     vec.push(Box::new(|| println!("test2")));
  |              -------- ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
  |              |
  |              arguments to this function are incorrect
  |
  = note: expected closure `[closure@src/main.rs:3:23: 3:25]`
             found closure `[closure@src/main.rs:4:23: 4:25]`
  = note: no two closures, even if identical, have the same type
  = help: consider boxing your closure and/or using it as a trait object

Solution

  • You must explicitly tell that vec holds boxed trait objects:

    fn main() {
        let mut vec: Vec<Box<dyn Fn()>> = Vec::new();
        vec.push(Box::new(|| println!("test")));
        vec.push(Box::new(|| println!("test2")));
        
        vec.iter().for_each(|f| (f)());
    }
    

    On the other hand you can leave it as it and "cast" boxed object with as keyword:

    fn main() {
        let mut vec = Vec::new();
        vec.push(Box::new(|| println!("test")) as Box<dyn Fn()>);
        vec.push(Box::new(|| println!("test2")));
        
        vec.iter().for_each(|f| (f)());
    }
    

    note that you have to do it only once, since now rust will infer that type of vec is indeed Vec<Box<dyn Fn()>>, and further pushing will know to do this cast automatically.