pub const fn must_use<T>(value: T) -> T
hint_must_use #94745)
An identity function that causes an unused_must_use warning to be triggered if the given value is not used (returned, stored in a variable, etc) by the caller.
This is primarily intended for use in macro-generated code, in which a #[must_use] attribute either on a type or a function would not be convenient.
#![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
})
};
}
// Implementation detail of make_error! macro.
#[doc(hidden)]
pub fn make_error(args: fmt::Arguments<'_>) -> Error {
Error(/* ... */)
}
fn demo() -> Option<Error> {
if true {
// Oops, meant to write `return Some(make_error!("..."));`
Some(make_error!("..."));
}
None
}In the above example, we’d like an unused_must_use lint to apply to the value created by make_error!. However, neither #[must_use] on a struct nor #[must_use] on a function is appropriate here, so the macro expands using core::hint::must_use instead.
We wouldn’t want #[must_use] on the struct Error because that would make the following unproblematic code trigger a warning:
fn f(arg: &str) -> Result<(), Error>
#[test]
fn t() {
// Assert that `f` returns error if passed an empty string.
// A value of type `Error` is unused here but that's not a problem.
f("").unwrap_err();
}Using #[must_use] on fn make_error can’t help because the return value is used, as the right-hand side of a let statement. The let statement looks useless but is in fact necessary for ensuring that temporaries within the format_args expansion are not kept alive past the creation of the Error, as keeping them alive past that point can cause autotrait issues in async code:
async fn f() {
// Using `let` inside the make_error expansion causes temporaries like
// `unsync()` to drop at the semicolon of that `let` statement, which
// is prior to the await point. They would otherwise stay around until
// the semicolon on *this* statement, which is after the await point,
// and the enclosing Future would not implement Send.
log(make_error!("look: {:p}", unsync())).await;
}
async fn log(error: Error) {/* ... */}
// Returns something without a Sync impl.
fn unsync() -> *const () {
0 as *const ()
}
© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/std/hint/fn.must_use.html