This is an extremely minor issue and I know how to do disable the warning, but reading up on it I suspect it might indicate that I might be doing something incorrect with my macro. Anyway, I have a struct Rational
for rational numbers:
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Rational {
n: i128,
d: i128,
}
impl Rational {
pub fn new(n: i128, d: i128) -> Self {
Rational { n, d }
}
}
to create these in a readable way I use macros:
macro_rules! rat {
($whole: tt $n : tt / $d : tt) => {
crate::rational::Rational::new($n + $whole * $d, $d)
};
($n : tt / $d : tt) => {
crate::rational::Rational::new($n, $d)
};
($n : tt) => {
crate::rational::Rational::new($n, 1)
};
}
and some code to test and demo this:
let x = 42;
println!("{}", rat!(1));
println!("{}", rat!(2 / 3));
println!("{}", rat!(x));
println!("{}", rat!(x / 2));
println!("{}", rat!(2 / x));
println!("{}", rat!(x 1/2));
println!("{}", rat!(1 4/5));
println!("{}", rat!((5 / 1) / 2)); //this line shows a warning
Hopefully there you can (sort of) see the point of the macros - with a normal function call, things like 1/2
would collapse to 0
before ever being seen by the function. (btw, I know it isn't worth it to do this for single rationals, but I think it might be for quickly parsing larger equations, like equation!(1/2 x + 3 3/4 y + 24 z = 2 3/4 + 4 x)
. This is just a baby step towards that.)
Anyway, the actual problem: on the last example, it complains that the parens around 5/1
are unnecessary. However, if I remove them (println!("{}", rat!(5 / 1 / 2));
) the macro fails with "no rules expected this token in macro call".) (btw, that test is obviously not nice syntax, I just wanted to ensure that it could handle arbitrary expressions.)
So, two questions:
- Is this the result of some sort of poor style on my part in how I constructed these macros?
- Is there a way to disable this warning that's more specific than just a universal
#![allow(unused_parens)]
but which doesn't require me to invoke that at every call site either? (I was wondering if I could somehow bake the allow into the macro itself, tho I don't think that makes sense.)
EDIT: I worked out that it was not the call that was the problem, but the generated code - the parens are necessary to the macro and rust recognizes that, but then the macro outputs new((5/1), 2)
, where the parens are actually unnecessary. I'm not sure of the right way to handle that, though I see a few options.