Reputation: 44787
I have a macro which works:
#[macro_export]
macro_rules! btreemap {
($( $key: expr => $val: expr ),*) => {{
let mut map = ::std::collections::BTreeMap::new();
$( map.insert($key, $val); )*
map
}}
}
but which the compiler warns about:
warning: variable does not need to be mutable
--> src/util.rs:16:11
|
16 | let mut map = ::std::collections::BTreeMap::new();
| ----^^^
| |
| help: remove this `mut`
|
::: src/foo.rs:49:13
|
79 | foo: btreemap!{},
| ----------- in this macro invocation
|
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
If I remove the mut
, I get an error:
error[E0596]: cannot borrow `map` as mutable, as it is not declared as mutable
--> src/util.rs:17:10
|
16 | let map = ::std::collections::BTreeMap::new();
| --- help: consider changing this to be mutable: `mut map`
17 | $( map.insert($key, $val); )*
| ^^^ cannot borrow as mutable
|
::: src/bar.rs:110:18
|
116 | let bar = btreemap!{quux => wibble};
| -------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
i.e. If mut
it warns on empty invocations, but if it's not if errors on non-empty invocations.
How can I fix this?
Upvotes: 7
Views: 2520
Reputation: 155126
How can I fix this?
You can suppress the warning by adding #[allow(unused_mut)]
to the code generated by the macro:
macro_rules! btreemap {
($( $key: expr => $val: expr ),*) => {{
#[allow(unused_mut)]
let mut map = ::std::collections::BTreeMap::new();
$( map.insert($key, $val); )*
map
}}
}
The warning is about as benign as a warning can get, and warning suppressions of this kind are often seen in macro definitions.
Another possibility is the one you already discovered, to special-case empty expansion. But I'd prefer the explicit warning suppression because it eliminates the (bogus) warning without complicating the macro. The special case you introduced wasn't actually necessary - the exact same code would be generated without it.
Upvotes: 8
Reputation: 44787
Fixed by adding a special case for the empty invocation:
#[macro_export]
macro_rules! btreemap {
() => {{
::std::collections::BTreeMap::new()
}};
($( $key: expr => $val: expr ),*) => {{
let mut map = ::std::collections::BTreeMap::new();
$( map.insert($key, $val); )*
map
}};
}
Upvotes: 7