JamesThomasMoon
JamesThomasMoon

Reputation: 7144

macro_rules presume type about arguments

tl;dr I think I want a macro declaration to infer type (how do I create this macro?)

This macro fails to compile (rust playground)

macro_rules! debug_assert_none {
    ($($arg:tt),+) => {
        $(
            if cfg!(debug_assertions) {
                match $arg {
                    None => {}
                    Some(..) => panic!("not None")
                }
            }
        )+
    };
}

#[test]
fn test_debug_assert_none() {
    debug_assert_none!(None);
    debug_assert_none!(None, None);
}

Fails with error

error[E0282]: type annotations needed
  --> src/lib.rs:15:24
   |
15 |     debug_assert_none!(None);
   |                        ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
   |
help: consider specifying the generic argument
   |
15 |     debug_assert_none!(None::<T>);
   |                            +++++

For more information about this error, try `rustc --explain E0282`.

How do I satisfy the required type declaration for a presumed Option? Or is there some other problem with this code?

Upvotes: 0

Views: 186

Answers (1)

cafce25
cafce25

Reputation: 27437

How is the compiler supposed to know the size it has to reserve for a bare None? It can't because it could hold any other type. As soon as you use your macro in a real world scenario, the type should be possible to infer, but if you want to pass in a bare None, you can always specify it explicitly by just giving it a type; usually one uses unit () for unused parameters.

debug_assert_none!(None::<()>);

Of course, you could also change your macro to help type inference but that would restrict the macro to work only with values of that one type:

macro_rules! debug_assert_none {
    ($($arg:tt),+) => {
        $(
            if cfg!(debug_assertions) {
                let x: &Option<()> = &$arg;
                match $arg {
                    None => {}
                    Some(..) => panic!("not None")
                }
            }
        )+
    };
}

Upvotes: 0

Related Questions