Attribute macro patterns for finding variables implementing a given type or trait

Can someone please advise whether there are any patterns for writing attribute macros which have some logic to parse body expressions and determine whether variables are of a given type which implements a trait?

For example:


pub struct Context;

pub type RefContext = Rc<RefCell<Context>>;

pub trait WithContext {
    fn set_context(&mut self, ctx: RefContext);
}

struct Item {
    ctx: Option<RefContext>
}

impl Item {
    fn new(ctx: RefContext) -> Item {
        Item { ctx: Some(ctx) }
    }
    fn default() -> Item {
        Item{ ctx: None }
    }
}

impl WithContext for Item {
    fn set_context(&mut self, ctx: RefContext) {
        self.ctx = ctx;
    }
}

fn run(ctx: RefContext) {
    let item = Item::new(ctx.clone());
    //...
}

#[with_context]
fn run2(ctx: RefContext) {
    // with_context macro figures out all variables which are of Type Item
    // and then under the hood adds additional expression to set_context(ctx.clone())
    // or more generally "figure out" all variables which implement a trait WithContext
    // i suspect the latter is not achievable?? 
    let item = Item::default(); 
    // ^^ macro finds this and adds item.set_context(ctx.clone())
    let item2 = Item::default();
    // ^^ macro finds this and adds item2.set_context(ctx.clone())
    //...    
}

This isn’t how macros work in general. Macros are expanded before types exist. First macros are expanded, then the compiler determines what traits exist and what types exist based on the generated code and surrounding code. You will need to find a way to generate identical code whether or not each variable ends up implementing the trait.

@dtolnay, thanks for confirming - i had my doubts about such approach. The “hacky” pattern i had in mind was to manually maintain a set of type names (as string) somewhere and matching parsed token items against it - but that’s sounds wacky and poor/unstable.