Leveraging #[must_use] for Robust Rust Development

Drashti Shah
2 min readApr 10, 2023

In Rust, the #[must_use] attribute acts as a helpful warning mechanism that prompts developers to avoid inadvertently ignoring the result of a function call or the value of a type. This attribute is particularly useful when working with functions or types that have significant side effects or outcomes that should be addressed.

Understanding #[must_use]

The #[must_use] attribute allows developers to annotate a function or a type in Rust, indicating that the result of the function or the value of the type must not be ignored. When the result of a function or a type marked with #[must_use] is discarded, the Rust compiler will issue a warning, reminding the developer to handle the result appropriately.

Applying #[must_use] to Functions

Imagine a function that returns a Result type, signalling success or failure. It is crucial to examine the result to ensure the operation was successful or to manage any errors that might have occurred. To enforce this, we can use the #[must_use] attribute.

#[must_use]
fn calculate(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("Division by zero is not allowed".to_string())
} else {
Ok(a / b)
}
}

If a developer invokes the calculate function without dealing with the result, the compiler will emit a warning.

fn main() {
let _ = calculate(10, 5); // No warning, because the result is explicitly ignored.
calculate(10, 0); // Warning: unused `Result` that must be used
}

Using #[must_use] with Types

You can also apply the #[must_use] attribute to custom types. For instance, consider a custom Token type that represents an authentication token with an expiration time.

#[must_use = "Token should be used, as it has an expiration time"]
struct Token {
value: String,
expires_in: u64,
}

impl Token {
fn new(value: &str, expires_in: u64) -> Self {
Token {
value: value.to_string(),
expires_in,
}
}
}

fn authenticate() -> Token {
Token::new("example_token", 3600)
}

If a developer creates a Token instance without using it, the compiler will issue a warning.

fn main() {
authenticate(); // This will generate a warning
}

You can also add a custom message to the #[must_use] attribute by providing a string. This message will be displayed in the compiler warning when the value is not used, providing additional context about why the result or value should not be ignored. More details about how to use #[must_use] are here: https://rustwiki.org/en/reference/attributes/diagnostics.html

In conclusion, Rust’s #[must_use] attribute is a valuable tool that helps developers create safer and more reliable code. By utilising this attribute, you can ensure that essential results or values are not inadvertently overlooked, preventing potential issues in your applications.

--

--

Drashti Shah

ESG & climate data scientist by day. Aspiring computational biologist by night.