Macro return type

Hi all,

I wonder is there anyway to strict return type in marco, such as:

macro_rules! gen_str {
    ($arg:expr) => {
        if $arg == "World" {
            "Hello world"
        } else {
            "Hello goodbye"
        }
    };
}

I wanna make sure the return value type is &str, is it possible?
Thanks

Macros operate on syntax, not types, so this is not possible to do directly. There may be some hacky ways, but I'd recommend against it.

Hi,

but the accept parameters can have types right?
I saw some codes like ($arg:expr, &str)
is it possible do the same with return?

No, macros operate on syntax only. If there is a matcher that is ($arg:expr, &str), the latter half of that expects a literal &str to be provided — it does not indicate that $arg is a string.

1 Like

sorry I misunderstood this, I thought this is forcing the input parameter to be a &str. Thank you very much.

What you can do is put the output into a &str variable inside the macro before returning it:

macro_rules! gen_str {
    ($arg:expr) => {
        let out: &str = { ... };
        out
    }
}

Or call a closure with a type annotation:

macro_rules! gen_str {
    ($arg:expr) => {
        (||->&str { ... })()
    }
}

Either of these will cause the type check to fail if the ... doesn't actually produce &str.

2 Likes

Note to OP: you have to be careful with closure abstractions, however. If you intend to use the macro with expressions that contain some specific kinds of control flow that only make sense, or change meaning, in a given context, then adding a closure will change the semantics of the code or cause it to fail to compile. Concretely, you won't be able to use it with expressions that contain break, continue, return, and ?.

3 Likes