What are the potential complications to returning a boxed trait object in lieu of Self?

What are the potential complications to returning a boxed trait object in lieu of Self? Specifically, trait objects are generally forbidden from returning Self, but it looks like this can be worked around at times by returning a trait object instead. For example, the following code defines a trait that can either cache or compute on a piece of data. In order to facilitate a cache and compute in a single line of syntax (obj.set().compute()), I'd like set to return a reference to Self, which is precluded. To get around it, I return a box to a reference of a trait object instead, which appears to work, but I don't fully understand whether this will have unforeseen consequences. Any problem using this kind of pattern?

// Trait that caches and computes
trait MyTrait {
    // Set our internal value.  Generally, want to return &Self here.
    fn set <'a> (&'a mut self, x: f64) -> Box<&'a dyn MyTrait>;

    // Compute with our internal value
    fn compute(&self, y: f64) -> f64;
}

// Struct that holds internal data that we want to cache
struct MyStruct {
    // Internal data
    data: f64,
}

// Allows setting and computing on the data
impl MyTrait for MyStruct {
    // Set our internal value
    fn set <'a> (&'a mut self, x: f64) -> Box<&'a dyn MyTrait> {
        self.data = x;
        Box::new(self)
    }

    // Compute with our internal value
    fn compute(&self, y: f64) -> f64 {
        self.data * 2. * y
    }
}

// Function that takes a trait object of MyTrait and then modifies and computes with it
fn foo(obj: &mut dyn MyTrait) {
    // Should be 5.52
    println!("Result is: {}", obj.set(1.2).compute(2.3));
}

// Test everything
fn main() {
    foo(&mut MyStruct { data: 3.4 });
}

Creating a box is kinda expensive since it requires memory allocation, but you can just return the reference instead?

fn set <'a> (&'a mut self, x: f64) -> &'a dyn MyTrait;
1 Like

Good catch. Thanks! In general, though, given the trait object restriction on returning Self or &Self, is there a general problem with returning Box <dyn MyTrait> in lieu of Self and &dyn MyTrait in lieu of &Self?

Well the compiler can better optimize it if it knows the actual type.