Is there a convention for unused variables? e.g. "_"


Was working on a thing and I made a for value in 1...x loop, and was curious if there's a standard for unused variables since I'm not using value. Is it just _ ?

Use clippy for linting your code. It will tell you pretty much what the convention is. But for all purposes and needs, yes, either _ or if you want a more descriptive name, just prefix your variable name with an _.


There is a semantic difference between these two options: if you use _ as a name, the corresponding value will be Dropped immediately; this is not the case with _name, where normal Drop rules apply (at the end of the current block).


Make sure to read the compiler warnings:

warning: unused variable: `x`
 --> src/
2 |     for x in 0..10 {
  |         ^ help: if this is intentional, prefix it with an underscore: `_x`
  = note: `#[warn(unused_variables)]` on by default

So the way to say "intentionally unused" is to prefix it with an underscore.

You can also use _ as a pattern to not have a binding at all.


Actually no, the value will not even be moved! _ is not a variable name, it's a pattern that matches everything but doesn't take over the value.

fn main() {
    let a = vec![1, 2, 3];
    let _ = a; // does nothing
    // Haha, I am still here!!!
    println!("{}", a.len());

And because this is often surprising to people at the top level, it's really important that it work this way when it's nested. For example,

if let opt @ Some(_) = returns_option_of_string() {

only works because the _ doesn't bind the inside of the option.

(And for orthogonality, it does the same thing even when not nested.)


Thank you for the answers everyone!

So, overall, what is good practice for using _ ? When should you avoid it, and when should you use it?

1 Like

Prefer _ for "I really don't care" local variables, like for _ in 0..n.

The only place you use let _guard = …; is in special scope-based resource management scenarios where you need the guard to live despite not using it. That should be rare.


One such rare instance: I made the mistake of thinking _ was equivalent to _foo a while back. I was using drop_guard to clean up partially initialized data on error, and made the mistake of thinking that let _ = drop_guard::guard(&status, ...); expressed that I want to keep the returned object around until it goes out of scope, but I don't actually want to use it.

1 Like

One thing you can consider for those cases: calling drop on it manually to help make it extra-clear that you're caring about where the drop happens, and that it's important that it not be let _ =.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.