I'm playing with symbolic math and would like to be able to write code that looks like this:

let x = var('x');
let y = var('y');
let two = num(2);
let sum = x + y;
let twice_x = two * x;

The problem is that math operators move their operands, so the last line would complain about use of a moved value (i.e. x), unless I make math expressions Copy. But math expressions can contain any other math expressions, so I need some type of redirection like Box, Rc or Arc, but those don't allow a Copy implementation.

The types for Self and Rhs in operator overloading traits can be whatever you want, so you can implement the operators for references. They will always "move" the type, but the moved type can be &Foo.

Have you looked at the rug crate? It is a binding for gmp. It allows you to write efficient expressions with heap-allocated integers and is reasonably ergonomic.

This is where using a macro could be useful, so that you only write the impl of Add<&T> for &T, and get the macro impls to divert the others to this one.

Keep in mind, though, that taking ownership of a value allows its allocation to be reused. Macros are still helpful when there are multiple, similarly shaped value types.