Why am I getting an error for an unused variable?


#1

According to Rust’s own article https://doc.rust-lang.org/1.8.0/book/if.html

I am doing exactly what Rust is telling me to do but then when I clicked on Run button in one of the examples, I hit an error, why is that?


#2

Warnings are not errors, and won’t stop the build by default (note that your code still compiled and ran, it just doesn’t output anything!)

It’s just warning you that you’ve got a variable in your code that never gets used for anything - you can get the warning to go away by:

  • Using the variable for something (maybe you should try printing it with println! to start with?)
  • Removing the variable
  • Adding a _ to the beginning of the variable name (which is the standard way of telling the compiler ‘Yes, this is unused on purpose’)

#3

Also, as an aside - the version of the book you’re reading is the first edition, which has recently been replaced with the second edition - I’d recommend the latter if you’re just starting to learn Rust :slight_smile:


#4

Ok so I am now printing y and now I am getting this error, also why am I not getting an error for the x variable?


#5

Oh ok so what should I do to fix this broken code then?


#6

Ah, that’s perhaps a little unclear at first glance - println! takes a format string as the first argument, followed by the actual things you want to print. You should change your code to this:

println!("{}", y);

The book explains this in a little more detail: https://doc.rust-lang.org/stable/book/second-edition/ch02-00-guessing-game-tutorial.html#printing-values-with-println-placeholders

You’re not getting an warning for x because the x variable is used - you use it in your if expression :slight_smile:


#7

Thanks my man,

In other languages you are able to print the contents in a integer variable, but why in Rust you must type println!("{}", y); in order to print y?


#8

Yeah, that can a bit annoying, but I don’t think there’s any way to do it by passing just the integer unfortunately :frowning:. You’ll need another macro to achieve it. Probably not worth the cost.


#9

And in some “other languages” you have to do printf("%d\n", y); and if y is the wrong type or you use the wrong format specifier, you get the wrong output. Rust avoids that particular pitfall by making println! a macro that checks the types of its arguments at compile time.

Slightly less pedantically, there’s more than one way to print a variable. Here are three:

println!("{}", y);
println!("{:?}", y);
println!("{:08}", y);

Chapter 5 talks about {:?}. I’m not sure if the book addresses other formatting options, but it’s not dissimilar to Python’s str.format. The full spec is in the documentation for the fmt module.


#10

Allowing println!(y); probably isn’t worth it since that would mean strings get interpreted differently depending on whether they’re literals or not, or you can’t use a format string with no substitutions, the latter of which would be a breaking change.

If you’re really hung up about it, just define a display!(y) macro like:

macro_rules! display { ($y:expr) => { println!("{}", $y) } }

#11

C allows printf(y), and this is a security vulnerability!

Rust’s println! is similar to C’s, but of course prevents that vulnerability at compile time.

println expects a formatting string that defines how its other arguments are going to be displayed, e.g. "{}" vs "{:?}" or "the hex number is {:04x}". If you did println!(y) it would expect y to be the formatting string, so if y contained something that looks like {} it would try to read more arguments, which there are none.

For cases where you know you have just a plain string there’s write_str, but for printing to stdout adding println!("{}" is still the easiest way.


#12

Because the common case is almost always that you want to do some formatting, even when doing debug-println’s, e.g. print!("inside function, y={}", y), or nicely display multiple variables at once, e.g print!("my debug: x={}, y={}, z={}, y_again={1}", x, y, z)

After your first sixty minutes of rust, you’ll use the formatting version more often than not :slight_smile:


#13

In Java you can type println(y);, does this mean that Java suffers the same vulnerability?


#14

Note the difference, “printLN” vs “printF”.
Java does its formatting in a separate StringFormatter class, println does only the printing part, not the formatting, so the ambiguity is never there.


#15

No, Java uses overloading for this. Closest equivalent in Rust would be:

fn print_whatever(whatever: impl std::fmt::Display) {
    println!("{}", whatever);
}

fn main() {
   print_whatever("hello");
   print_whatever(123);
}

#16

@Joe232 I would really recommend joining the #rust-beginners channel on Mozilla IRC. You’ll most likely be able to get much quicker answers and support than on the forums (although both are useful means of communication!)