must_use in std::hint - Rust (original) (raw)

pub const fn must_use<T>(value: T) -> T

🔬This is a nightly-only experimental API. (hint_must_use #94745)

Expand description

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.

§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 = <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi><mi>r</mi><mi>a</mi><mi>t</mi><mi>e</mi><mo>:</mo><mo>:</mo><mi>m</mi><mi>a</mi><mi>k</mi><msub><mi>e</mi><mi>e</mi></msub><mi>r</mi><mi>r</mi><mi>o</mi><mi>r</mi><mo stretchy="false">(</mo><mi>c</mi><mi>o</mi><mi>r</mi><mi>e</mi><mo>:</mo><mo>:</mo><mi>f</mi><mi>o</mi><mi>r</mi><mi>m</mi><mi>a</mi><msub><mi>t</mi><mi>a</mi></msub><mi>r</mi><mi>g</mi><mi>s</mi><mo stretchy="false">!</mo><mo stretchy="false">(</mo></mrow><annotation encoding="application/x-tex">crate::make_error(core::format_args!(</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">cr</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">::</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">mak</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.02778em;">rror</span><span class="mopen">(</span><span class="mord mathnormal">core</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">::</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">or</span><span class="mord mathnormal">ma</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">s</span><span class="mclose">!</span><span class="mopen">(</span></span></span></span>($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.

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();  
}  
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 ()  
}