Separate declaration of type using macro_rules!

How can I correctly declare type inside declarative macro by separating type's name itself and it's generics ?

Consider this example:

struct RectangleA<const WIDTH: usize, const LENGTH: usise>;
struct RectangleB<const WIDTH: usize, const LENGTH: usise>;

I want to separate type declaration (and possibly it's genercics) between few macroses to match on different parameters. I see it like this:

macro_rules! get_type {
    (false) => {
        RectangleA
    }
    (true) => {
        RectangleB
    }
}

macro_rules! impl_something {
    ($SOME_FLAG: expr) => {
        get_type!($SOME_FLAG)::<5, 10>
    }
}

Try <get_type!($SOME_FLAG)>::<5, 10>. The extra <> force it to be interpreted as type.

Does not seems to work, playground link

That playground link doesn't have any code; you have to click the Share button to store the code.

Based on your original message, the problem is probably that you used $SOME_FLAG:expr in impl_something. :expr makes the matched expression opaque such that it cannot be further matched by passing it to other macros. Use :tt instead.

Sorry, edited the link

this will never work. there are certain positions where a macros invocation can appear, the list of valid macro invocations:

"type" is valid, but "incomplete generic type" (or, "type constructor", if you will) is not valid.

what's more, $SOME_FLAG is captured as an expr metavariable, which cannot be matched against literal tokens. only tt, ident and lifetime metavariables can be forwarded and examined again. see:

1 Like

"type" is valid, but "incomplete generic type" (or, "type constructor", if you will) is not valid.

Here is one possible way to work around that:

struct RectangleA<const WIDTH: usize, const LENGTH: usize>;
struct RectangleB<const WIDTH: usize, const LENGTH: usize>;

macro_rules! get_type {
    (false, $($args:tt)*) => {
        RectangleA::<$($args)*>
    };
    (true, $($args:tt)*) => {
        RectangleB::<$($args)*>
    };
}

macro_rules! test {
    ($FLAG:tt) => {
        get_type!($FLAG, 5, 10)
    };
}

fn main() {
    type x = test!(true);
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.