如何使结果的内在价值 must_use

How to make the inner value of a Result must_use

我可以使用 #[must_use] 属性将函数标记为具有必须使用或明确忽略的 return 值:

#[must_use]
fn plain() -> i32 {
  1
}

fn main() {
  plain();  // warning
}

但是,如果我想改变我的功能,现在 return 变成 Result,我不能这样做:

#[must_use]
fn result() -> Result<i32, ()> {
  Ok(1)
}

fn main() {
  result().unwrap();
}

因为对 .unwrap() 的调用算作一次“使用”,并且 #[must_use] 属性应用于整个 Result

有没有办法让 #[must_use] 也适用于内部类型?本质上,我想确保 i32 不会被分号意外地“吃掉”。

我有额外的限制,我不能改变这个函数的 public API,所以我不能把它变成 return 一个 Result<MustUse<i32>, ()> 或其他东西那些线。

您不能通过直接向 Result 添加您自己的注释来做到这一点,但您可以使用新类型轻松做到这一点:

#[must_use]
#[repr(transparent)]
pub struct MustUse<T>(T);

impl<T> From<T> for MustUse<T> {
    fn from(v: T) -> Self {
        Self(v)
    }
}

impl<T> MustUse<T> {
    #[must_use]
    fn into_inner(self) -> T {
        self.0
    }
}

现在,给出这个声明:

fn result() -> Result<MustUse<i32>, ()> {
  Ok(1.into())
}

以下所有情况都会导致警告:

  • result(); 发出警告,因为 Result<_, _> 是 must-use。
  • result().unwrap(); 发出警告,因为 MustUse<_> 是 must-use。
  • result().unwrap().into_inner(); 发出警告,因为 MustUse<_>::into_inner() 是 must-use。

(请注意,您可以通过调用 Result 的另一个非 must-use 方法来绕过警告,例如 result().ok(),但无论您做什么做。)