Why is warn unused_assignments on by default?

I'm new to rust and like what I've seen so far. I'm checking out the tour and discovered that a common programming pattern I use to define default values in procedural languages is tossing up a warning. My question is why is this and what is the better way to solve the same problem? ( Hopefully with less code not more! )

The pattern is very simple. On function entry assign a default value to some variable, then in the body allow various conditions to change it. Once function ends, if no conditions were triggered then the default value prevails.

In rust (the tour at least), using such a pattern tossing a warning:

warning: value assigned to `v` is never read

`#[warn(unused_assignments)]` on by default

Below is the example from the tour that I modified that displays this warning.

Any advise on this would be most appreciated.
Thanks!

fn main() {
    let mut x = 0;
    let mut v = "sorry charlie";
    v = loop {
        x += 1;
        if x == 13 {
            break "found the 13";
        }
        if x == 14 {
            break;
        }
    };
    println!("from loop: {}", v);
}

I think in this case, the warning helps find a logic bug in the code. You assign a string to v, but then immediately reassign it to the expression the loop gives. v will never be "sorry charlie" no matter what because the loop will keep going until it breaks with a value and overwrites v.

It might make more sense to do let v = loop { ... }.

Also, the following code doesn't give a warning:

fn main() {
    let mut x = 0;
    let mut v = "sorry charlie";
    loop {
        x += 1;
        if x == 13 {
            v = "found the 13";
            break;
        }
        if x == 14 {
            break;
        }
    };
    println!("from loop: {}", v);
}
2 Likes

You can fix this warning by removing the unused assignment. Change this line:

let mut v = "sorry charlie";

to this:

let mut v;

Then the compiler will also let you know that the variable is never mutated, so you can change it to:

let v;

Then you might notice that there's no need to declare the variable in one statement and initialize it in the next. You could combine these into a single statement that declares and initializes the variable:

let v = loop {
    x += 1;
    if x == 13 {
        break "found the 13";
    }
};
3 Likes

Thank you very much for the quick replies!

You may have noticed that I already modified the code to contain a condition that gets hit which does not return a value. When I did this I was about to reply that this caused me to recognize my logic error demonstrated by a break without a return value does not mean no assignment is made. My logic error was to assume that the default value from the original "sorry charlie" assignment would be retained.

I'm liking rust even more now!

Thanks again!

1 Like

How interesting. I only now noticed that ArifRoktim included the exact change (if x == 14) block that I had in my subsequent edit that he probably missed because he was so quick to respond!

It tosses a new error (not warning this time) about using different types. I'm assuming that's because the break; in the block returns a () unit value which is a different type.

I edited to add that code block after seeing your edit. Probably should've made that clearer.

You can't break with different return types, but you can get the behavior you want by instead assigning to v inside the loop like shown my code block above.

Correct; break; is equivalent to break ();, just like return; is equivalent to return ();.

Another way to do this, then, is to rephrase it with Option:

fn main() {
    let mut x = 0;
    let v = loop {
        x += 1;
        if x == 13 {
            break Some("found the 13");
        }
        if x == 14 {
            break None;
        }
    };
    println!("from loop: {}", v.unwrap_or("sorry charlie"));
}
1 Like

Thanks for all the suggestions.

I see how the sample as written would be better to have the if x == 13 condition be written to test a random integer generation for 13, that way the x == 14 would be possible.