Macro expansion


#1

I tried to make macro that will return type depending on type I pass to it as argument
For example:

macro_rules! foo { ($t:ty) => (Option::<$t>) }

Everithing is OK until I try to do recursive macro invocation:

foo!(foo!(isize));

This should transform to Option::<Option::<isize>>. Instaed I get compilation error.

src/main.rs:77:11: 77:12 error: no rules expected the token `!`
src/main.rs:77   foo!(foo!(i32));

Is there any method to force macro expansion in place, before it will be passed into another macro?
Or maybe it not possible at all?
Or may be there some workaround you know?


#2

Shouldn’t it be Option<Option<isize>>? I’m pretty sure the :: is not supposed to be there in this context.


#3

You can’t. As per http://doc.rust-lang.org/reference.html#macros,

Currently, macros can expand to expressions, statements, items, or patterns.

You can have a macro that expands out to a statement, like this:

#![feature(trace_macros)]

macro_rules! foo (
    ($x:expr) => (Some($x)); 
    ($x:ident) => (Some($x)); 
);

fn main() {
  trace_macros!(true);
  let x = foo!(100);
  let y = foo!(x);
  println!("{:?}", y);
}

…but not a macro that expands to a type, like this:

struct Foo {
  bar: foo!(isize)
}

The error you’re getting is because you’re trying to use a macro in a space where it’s no valid, not that it’s a recursive call.