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

  • 本文关键字:不需要 变量 rust macros
  • 更新时间 :
  • 英文 :


我有一个可以工作的宏:

#[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
}}
}

该警告与警告所能得到的一样温和,这种警告抑制通常出现在宏定义中。

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

通过为空调用添加特殊情况修复:

#[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
}};
}

相关内容

最新更新