pub fn must_use<T>(value: T) -> T
🔬This is a nightly-only experimental API. (
hint_must_use
#94745)Expand description
如果调用者未使用给定值 (返回、存储在变量中等),则会触发 unused_must_use
警告的标识函数。
这主要用于宏生成的代码,其中类型或函数上的 #[must_use]
属性 不方便。
Example
#![feature(hint_must_use)]
use core::fmt;
pub struct Error(/* ... */);
#[macro_export]
macro_rules! make_error {
($($args:expr),*) => {
core::hint::must_use({
let error = $crate::make_error(core::format_args!($($args),*));
error
})
};
}
// make_error 的实现细节! macro.
#[doc(hidden)]
pub fn make_error(args: fmt::Arguments<'_>) -> Error {
Error(/* ... */)
}
fn demo() -> Option<Error> {
if true {
// 哎呀,本来想写 `return Some(make_error!("..."));`
Some(make_error!("..."));
}
None
}
Run在上面的示例中,我们希望 unused_must_use
lint 应用于 make_error!
创建的值。
但是,结构体上的 #[must_use]
和函数上的 #[must_use]
都不适用于这里,因此宏使用 core::hint::must_use
进行扩展。
-
我们不希望在
struct Error
上使用#[must_use]
,因为这会使以下无问题的代码触发警告:
Runfn f(arg: &str) -> Result<(), Error> #[test] fn t() { // 如果传递一个空字符串,则断言 `f` 将返回错误。 // 这里没有使用 `Error` 类型的值,但这不是问题。 f("").unwrap_err(); }
-
在
fn make_error
上使用#[must_use]
无济于事,因为返回值 is 被用作let
语句的右侧。let
语句看起来毫无用处,但实际上对于确保format_args
扩展中的临时对象在创建Error
之后不会保持活动状态是必要的,因为在创建Error
之后保持它们活动可能会导致异步代码中的 autotrait 问题:
Runasync fn f() { // 在 make_error 扩展中使用 `let` 会导致诸如 `unsync()` 之类的临时变量在 `let` 语句的分号处,该分号位于 await 点之前。 // 否则它们会一直停留在 *this* 语句的分号上,也就是在 await 点之后,并且封闭的 Future 不会实现 Send。 log(make_error!("look: {:p}", unsync())).await; } async fn log(error: Error) {/* ... */} // 返回没有 Sync impl 的内容。 fn unsync() -> *const () { 0 as *const () }