Search code examples
rusttraits

Rust trait object in tuple --- expected trait object, found type


I have been reading chapter 17 in The Rust Programming Language and I have been trying to use trait objects in my code.

Could someone please explain why the function test2 does not compile while the others do?

trait Print {
    fn print(&self) -> String;
}

impl Print for i32 {
    fn print(&self) -> String {
        return format!("{}", &self);
    }
}

impl Print for &str {
    fn print(&self) -> String {
        return format!("'{}'", &self);
    }
}

pub fn test1() {
    let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
    let bxx = Box::new(0);
    let idx = 1;
    v.push((idx, bxx));
    
    for (idx, val) in &v {
        println!("{} - {}", idx, val.print());
    }
}

pub fn test2() {
    let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
    let bxx = Box::new(0);
    let idx = 2;
    let t = (idx, bxx);
    v.push(t);
    
    for (idx, val) in &v {
        println!("{} - {}", idx, val.print());
    }
}

pub fn test3() {
    let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
    v.push((3, Box::new("a")));
    
    for (idx, val) in &v {
        println!("{} - {}", idx, val.print());
    }
}




fn main() {

    test1();
    test2();
    test3();

}

playground


Solution

  • By default when boxing it is gonna take as a box of the espeficit type you are boxing. In your case would be Box<i32>. If you annotate the type specifically then it works:

    pub fn test2() {
        let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
        let bxx: Box<dyn Print> = Box::new(0);
        let idx = 2;
        let t = (idx, bxx);
        v.push(t);
        
        for (idx, val) in &v {
            println!("{} - {}", idx, val.print());
        }
    }
    

    Playground