FWIW, the ambassador crate is my current favorite for this specific use case, if you want some macro-driven sugar. Any macro solution will necessarily require annotating the trait as well. ambassador emits a macro_rules!
macro alongside your trait which is used to implement the actual delegation.
With ambassador, the OP example would look like
use ambassador::{delegatable_trait, Delegate};
#[delegatable_trait]
trait Interface {
fn f1(&self);
fn f2(&self);
}
struct Super {}
impl Interface for Super {
fn f1(&self) {}
fn f2(&self) {}
}
#[derive(Delegate)]
#[delegate(Interface)]
struct Sub1(Super);
(A derive macro is used because it's nicer to IDEs, since it cannot change the struct definition like a non-derive attribute macro could.)