Problem
How can I create a Rust macro that only accepts certain number literals in a scalable manor?
Ideally, such a solution meets the following requirements:
- Scales to hundreds of allowed numbers
- Raises compile time errors where the macro is called when the number literal is invalid
Non-solutions
Multiple branches
You can create a macro where each arm accepts a specific number as shown below. However I also want to perform computation on the allowed numbers, leading to lots of code duplication since I'm dealing with hundreds of allowed numbers.
macro_rules! my_macro {
(1) => {
1
};
(2) => {
2
};
(3) => {
3
};
}
Using compile_error!
The compile_error!
macro reports the error inside my_macro
, not on the arguments to my_macro!
. This can be very unintuitive.
macro_rules! my_macro {
($num: literal) => {
// if number is invalid
compile_error!("number is invalid")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // error is reported here
// else
$num
};
}
// Let's say 34 is an invalid number
my_macro!(34)
Context
I'm trying to emulate a behavior with TypeScript's type system where you can create a type that limits the specific numbers a function accepts.
type AllowedNumbers = 1 | 2 | 3
const myFunc = (num: AllowedNumbers) => {
// ...
}
You can panic in a const to create a compile-time error dependent on a literal.
This produces the following error.
Your idea to use
compile_error
doesn't work anyway since there's no way to conditionally compile it based on the value of a literal besides using multiple branches.I think this is as good as you'll get with declarative macros. You could create better error messages if you write a procedural macro.