我可以使用#[must_use]属性将函数标记为具有必须使用或显式忽略的返回值:

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

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

但是,如果我想更改函数,使其现在返回Result,我不能这样做:

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

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

因为对.unwrap()的调用算作"使用",#[must_use]属性应用于整个Result.

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

我还有一个额外的限制,我不能更改这个函数的公共API,所以我不能让它返回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<_, _>是必须使用的.
  • result().unwrap();警告,因为MustUse<_>是必须使用的.
  • result().unwrap().into_inner();警告,因为MustUse<_>::into_inner()是必须使用的.

(请注意,您可以通过调用另一个非必须使用的Result方法(例如result().ok())绕过警告,但无论您做什么,这都是正确的.)

Rust相关问答推荐

将JSON密钥转换为Polars DataFrame

当Option为None时,Option数组是否占用Rust中的内存?

什么时候铁 rust FFI边界上的panic 是未定义的行为?

将数组转换为HashMap的更简单方法

在Rust 中移动原始指针的靶子安全吗

rust 蚀生命周期 不匹配-不一定超过此处定义的生命周期

Rust wasm 中的 Closure::new 和 Closure::wrap 有什么区别

要求类型参数有特定的大小?

tokio::spawn 有和没有异步块

为什么我的trait 对象类型不匹配?

如何在 Rust 中按 char 对字符串向量进行排序?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

意外的正则表达式模式匹配

如何用另一个变量向量置换 rust simd 向量?

如何制作具有关联类型的特征的类型擦除版本?

为什么这里需要类型注解?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?

为什么 Bevy 的 Trait 边界不满足 Rapier 物理插件?

未实现特征时返回泛型