CodeBlanks Logo Icon CodeBlanks

attribute macro

Write an attribute macro with #[proc_macro_attribute].

Attribute macros

Attribute macros take the whole item they mark and put whatever they want in its place. They also take the attribute's own arguments:

#[proc_macro_attribute]
pub fn olcumle(arg: TokenStream, oge: TokenStream) -> TokenStream {
    let mut f = syn::parse_macro_input!(oge as syn::ItemFn);
    let ad = f.sig.ident.to_string();
    let govde = &f.block;
    f.block = syn::parse_quote!({
        println!("{} çağrıldı", #ad);
        #govde
    });
    quote::quote!(#f).into()
}

// usage:
#[olcumle]
fn kare(x: i32) -> i32 { x * x }

#[tokio::main], things like #[test], and #[get("/")] in web frameworks are attribute macros.

Wrapping with macro_rules!

We can do the same transformation with macro_rules! by passing the function to the macro as an argument:

macro_rules! olcumle {
    (fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => {
        fn $ad($($arg: $tur),*) -> $don {
            println!("{} çağrıldı", stringify!($ad));
            $govde
        }
    };
}

olcumle! {
    fn kare(x: i32) -> i32 { x * x }
}

$govde:block captures the braced body as a single piece.

Practice Report the call

Write the olcumle! macro above and define the function fn kare(x: i32) -> i32 { x * x } with it. In main, print the result of kare(4).

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
macro_rules! olcumle {
    (fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => {
        fn $ad($($arg: $tur),*) -> $don {
            println!("{} çağrıldı", stringify!($ad));
            $govde
        }
    };
}

olcumle! {
    fn kare(x: i32) -> i32 {
        x * x
    }
}

fn main() {
    let s = kare(4);
    println!("{}", s);
}

Expected output

kare çağrıldı
16

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What happens if an attribute macro takes the function but doesn't put it in the output?

  • It warns
  • The function disappears from the program Correct answer
  • The compiler adds it back
  • Panic

Explanation: An attribute macro fully replaces the item; preserving the original item is the macro's responsibility.

2 Capture the body

Question
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:____) => { .. }
Answer
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => { .. }

Explanation: The block fragment matches a braced block.

3 Attribute and role

Term Meaning
#[proc_macro_attribute] Defines an attribute macro
arg: TokenStream Attribute arguments
oge: TokenStream The marked item
syn::ItemFn Function tree

All lessons in Advanced