变量不需要是可变的,但是确实可以

问题描述

我有一个可以工作的宏:

#[macro_export]
macro_rules! btreemap {
    ($( $key: expr => $val: expr ),*) => {{
         let mut map = ::std::collections::btreemap::new();
         $( map.insert($key,$val); )*
         map
    }}
}

但是编译器警告的内容

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)

如果我删除mut,则会收到错误消息:

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)

即如果mut会在空调用时发出警告,但如果非空调用错误,则不会发出警告。

我该如何解决

解决方法

我该如何解决?

您可以通过在宏生成的代码中添加#[allow(unused_mut)]来取消警告:

macro_rules! btreemap {
    ($( $key: expr => $val: expr ),*) => {{
        #[allow(unused_mut)]
        let mut map = ::std::collections::BTreeMap::new();
        $( map.insert($key,$val); )*
        map
    }}
}

警告与警告所能获得的一样好,并且在宏定义中经常看到这种警告抑制。

另一种可能性是您已经发现的一种特殊情况的空扩展。但是我更喜欢显式警告抑制,因为它消除了(虚假的)警告而不会使宏复杂化。您介绍的特殊情况实际上并不是不必要的 -如果没有它,则会生成完全相同的代码。

,

通过为空调用添加特殊情况来解决:

const