Reputation: 7144
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
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