This is inspired by @vague 's surprising answer at Listing all branches of enums w/ 'unit' arms - #2 by vague
Now I am wondering if the following (which I previously considered impossible) to be possible with macro rules:
We start with the end goal (manually written)
use super::*;
pub struct Bar {}
pub trait Bar_Aux_T {
fn cat(&self, obj: &Bar, x: u32);
fn dog(&self, obj: Rc<Bar>, y: String);
fn apple(&self, obj: &Bar, a: i32, b: i32);
}
impl Bar {
fn cat(self: &Bar, aux: &dyn Bar_Aux_T, x: u32) {
aux.cat(self, x)
}
fn dog(self: Rc<Bar>, aux: &dyn Bar_Aux_T, y: String) {
aux.dog(self, y)
}
fn apple(self: &Bar, aux: &dyn Bar_Aux_T, a: i32, b: i32) {
aux.apple(self, a, b)
}
}
Now, the question is: can we wrap a macro around pub trait Bar_T
and have it auto generate the part in impl Bar
as follows:
-
the only thing in the trait are function declarations
-
there are only two types of function declarations
fn func_name(&self, obj: &Bar, ...)
fn func_name(&self, obj: Rc<Bar>, ...)
- these need to, respectively transformed into:
fn func_name(&self, obj: &dyn Bar_Aux_T, ...)
fn func_name(self: Rc<Self>, obj: &dyn Bar_Aux_T, ...)
===
Why can't I do this myself? If we look at @vague 's previous solution there is "repetition" and "binding" but there isn't what I'd call "enum choice"
So in the parsing part, we need to somehow store whether we are parsing a obj: &Bar
or an obj: Rc<Bar>
, then later we need to "dispatch" and do different things based on which one we got.
This is the part I can not figure out.
Concretely, I need help writing a macro_rules foo s.t.
foo! {
pub trait Bar_Aux_T {
fn cat(&self, obj: &Bar, x: u32);
fn dog(&self, obj: Rc<Bar>, y: String);
fn apple(&self, obj: &Bar, a: i32, b: i32);
}
}
will auto generate the
impl Bar {
fn cat(self: &Bar, aux: &dyn Bar_Aux_T, x: u32) {
aux.cat(self, x)
}
fn dog(self: Rc<Bar>, aux: &dyn Bar_Aux_T, y: String) {
aux.dog(self, y)
}
fn apple(self: &Bar, aux: &dyn Bar_Aux_T, a: i32, b: i32) {
aux.apple(self, a, b)
}
}
Thanks!