Is statement annotatable (How to instrument statement) in Rust Compiler Plugin?


#1

Hi, I am looking for methods to instrument rust statements and I am wondering whether rust compiler plugin is the right approach. Demonstration of my intent:

before:
foo();
after: checkfoo(); foo();

Rust compiler plugin provides several ways to extend syntax,

  • register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension), register a syntax extension of any kind.
  • register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension), register legacy custom derives
  • register_macro(&mut self, name: &str, expander: MacroExpanderFn), register a macro of the usual kind.
  • register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject), register a compiler lint pass
  • register_late_lint_pass(&mut self, lint_pass: LateLintPassObject), register a compiler lint pass
  • register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>)
  • register_mir_pass(&mut self, pass: Box<for<'pcx> MirMapPass<'pcx>>), register a MIR pass
  • pub fn register_llvm_pass(&mut self, name: &str), register an LLVM pass, this is handled through static C++ objects with constructors. This method simply adds a name to the list of passes to execute.
  • register_attribute(&mut self, name: String, ty: AttributeType), register an attribute with an attribute type. Registered attributes will bypass the custom_attribute feature gate.

I am considering to use register_syntax_extension to register a new extension, SyntaxExtension is defined as :
pub enum SyntaxExtension { MultiDecorator(Box<MultiItemDecorator>), MultiModifier(Box<MultiItemModifier>), ProcMacro(Box<ProcMacro>), AttrProcMacro(Box<AttrProcMacro>), NormalTT(Box<TTMacroExpander>, Option<Span>, bool), IdentTT(Box<IdentMacroExpander>, Option<Span>, bool), CustomDerive(Box<MultiItemModifier>), }

Through comparison, I determined I can delare a MulitiModifier to annotate the job.

     // `meta_item` is the annotation, and `item` is the item being modified.
    pub trait MultiItemModifier {
    fn expand(&self,
	              ecx: &mut ExtCtxt,
	              span: Span,
	              meta_item: &ast::MetaItem,
	              item: Annotatable)
      -> Vec<Annotatable>;
}

The question is the Annotatable is not applied to ‘statements’:

#[derive(Debug,Clone)]
pub enum Annotatable {
    Item(P<ast::Item>),
    TraitItem(P<ast::TraitItem>),
    ImplItem(P<ast::ImplItem>),
}

Item,TraitItem, ImplItem, don’t have a ‘statement’ type. So I wondering is it plausible to instrument the statement using the ‘SyntaxExtension’?


#2

I’m fighting with similar thing. I believe you can use macro to inject a function definition that would wrap your statement and decorate it witk MultiModifier. That’s the only way I can come up with and I’d really wish that compiler would provide better way to do it.