I have a trait Expression which is defined on multiple types. A typical pattern I tend to include in my types is Box<dyn Expression>. Here's an example:
pub struct BinaryExpr {
l : Box<dyn Expression>, r : Box<dyn Expression>
}
I have another trait ExpressionPrinter which is defined like :
pub trait ExpressionPrinter: Expression {
fn print(&self);
}
As you can see, it takes a immutable reference to self, and is supposed to print a string representation of the any expression type implementing it. Let's say I was implementing this for BinaryExpr
impl ExpressionPrinter for BinaryExpr {
fn print(&self) {
let mut s = start!("BinaryExp");
s.push_str(&self.operator.lexeme);
s.push_str(&self.left.print());
s.push_str(&self.right.print());
dbg!(s);
}
}
This code does not compile because :

Alright, maybe I need to deref from Box before calling the methods, but wait, isn't Box supposed to auto-deref? Then I looked around the docs for Box realizing I don't really understand Boxed trait objects. There's an into_inner but it doesn't work as the inner trait object is !Sized. There's a downcast which
Attempt to downcast the box to a concrete type.
But it requires trait Any to be implemented for each expression type.
Needless to say, this abstraction is not fun anymore with so many restrictions. I don't understand how to call trait object methods.
EDIT: The question as it stands now is how do I cast from a Box<dyn Expression> to a concrete type bounded by ExpressionPrinter?