Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable does not need to be mutable, but it does

Tags:

macros

rust

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?

like image 951
fadedbee Avatar asked Jul 18 '26 09:07

fadedbee


1 Answers

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.

like image 174
user4815162342 Avatar answered Jul 20 '26 07:07

user4815162342



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!