I want to make these warnings go away

I am a big believer in the idea that learning comes best when one is involved in doing. I've been working through various resources, searching terms on Google, asking lots of questions on this forum, & etc, and will, of course, continue those practices as I continue to learn the Rust programming language. As with my students when I was a high school math teacher, the concepts behind the mechanics we teach often don't get learned until the student has been using the mechanics for a while. So, I have started working on my pet project and am hoping that some of those strange & fuzzy concepts that seem so simple to experienced programmers will eventually come clear. (Note: Some attempts to address my questions below were posted on this thread, but it all is still quite fuzzy and mysterious to me anyway.)

Here is my beginning code:

#[derive(Debug)]
struct Variable {
    var_name: String,
    is_num: bool,
    is_list: bool,
}

struct Question {
    qtext: String,
    var_vec: Vec<Variable>,
    answer: String, // A numeric answer will need to be converted into a string.
}

fn main() {
    let var1 = Variable {
        var_name: "num1".to_string(),
        is_num: true,
        is_list: false,
    };

    let var2 = Variable {
        var_name: "num2".to_string(),
        is_num: true,
        is_list: false,
    };
    let varvec = vec![var1, var2];

    let q1 = Question {
        qtext: String::from("What is ~~num1~~ plus ~~num2~~?"),
        var_vec: varvec,
        answer: String::from("To be calculated"),
    };
    println!("\n Question:  {}", q1.qtext);
    println!("\n Variable vector:   {:?}", q1.var_vec);
    println!("\n Answer: {}", q1.answer);
    println!("\n ");
}

This code works and does what I expected, but I get warnings that are just plain annoying. I'm sure that the problem orbits the fact that I really don't understand "attributes" or "debug" or the line #[derive(Debug)], but hopefully that understanding will come to me later. Right now I just want to get rid of these annoying warnings.

Here's what the compiler kicks out:

warning: fields `var_name`, `is_num` and `is_list` are never read
  --> src/main.rs:8:5
   |
7  | struct Variable {
   |        -------- fields in this struct
8  |     var_name: String,
   |     ^^^^^^^^^^^^^^^^
9  |     is_num: bool,
   |     ^^^^^^^^^^^^
10 |     is_list: bool,
   |     ^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default
   = note: `Variable` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis

I really don't know what the compiler is complaining about, but what I really want to know is how do I get rid of these warnings???

Thanks for your help.

1 Like
#![allow(dead_code)]

Put that at the top of your main.rs file. You can do this for any warning by looking at the note telling you what the warning is called. You can also attach a regular attribute to the thing causing the warning. So, that would involve putting #[allow(dead_code)] on the struct Variable definition (either immediately before or after the #[derive(Debug)] line).

#[derive(Debug)]
#[allow(dead_code)]
struct Variable {
    var_name: String,
    is_num: bool,
    is_list: bool,
}

Please, please don't abuse this or use it long-term. Those warnings are there for a reason.

The message is pretty unambiguous: you never, anywhere in the code, directly read from the var_name, is_num, or is_list fields. The derived Debug implementation deliberately excludes itself. It's warning you because you generally don't add functions or fields that you never use. That you aren't using them could indicate a problem.

In this specific case, you can also prefix the field names with _ (so, something like _var_name. This is a hint to the compiler that you know the symbol won't be used, but you need it for some other reason.

5 Likes

The direct answer to your question is that you can configure the built-in lints to be allowed via the methods in the documentation or, e.g.

# Assuming some unix-alike with bash-like shell
RUSTFLAGS='-A dead_code -A unused_variables' cargo check

And there are even lint groups so you can silence a lot at once

RUSTFLAGS='-A unused' cargo check
# Not recommended but it exists
RUSTFLAGS='-A warnings' cargo check

I prefer this approach to putting the flags in Cargo.toml or putting attributes in my source files, as generally I only do this in the development phase before all the code exists or before I've gotten my visibility story worked out (pub mod, pub fn et cetera). Rust's errors are on the whole quite good, and I rarely consider something to be in a stable state[1] if I'm still getting warnings about it.


As for the specific warnings, the compiler noted that you never actually wrote code that reads any of the fields of a Variable. (Moreover it is not public, and even if it was the fields are not public, so code outside of this crate can't read those fields either.)

The note about derived Debug is because the derived implementation of Debug does read those fields, but the lint doesn't consider that a use of the fields (as a lot of people derive Debug for everything, and if that was considered a use in and of itself, the lint would be mostly useless).

If you only intended to debug-print this data structure, it would make sense to put an #[allow(dead_code)] attribute on it. But I don't think I've every seen such a structure myself, and chances are you eventually intend to make use of all the fields in Variable within your code. Once you do that, the dead_code lint will stop firing.

If you manaully implemented Debug in a way that read the fields, it would also stop firing. If you made the struct and all the fields pub, it would also stop firing. The downside of doing these just to silence the lint is the same as disabling warnings in your code instead of ephemerally: later on when you wish you had some indication that the code was dead and could be removed,[2] no warnings will fire.


  1. i.e. something where I'd want to "permanently" disable warnings by using an attribute in my source code ↩︎

  2. or just want to know your code has gotten to a point others are more likely to consider idiomatic ↩︎

4 Likes
for var in &q1.var_vec {
        println!("Variable: {}, {}, {}", var.var_name, var.is_num, var.is_list);
    }

Just print the variable.

It is simply saying that you have defined things in your program that you don't use. This, I presume, is meant as a reminder that whatever idea you had in mind when you defined those things you have not completed it yet. Or forgotten to do so. Which might mean your code is not yet correct.

I think you might question a student of maths about why they spend effort deriving equations for u, v, t, whatever when they never actually used them in their final proof. If nothing else having such dead code hanging around is an indication of something not done, or something to confuse future readers.

Solutions:

  1. Remove the unused items. Or...
  2. Add whatever you intended to your code that will use them. Or...
  3. Use that "dead_code* lint mentioned above. Or...
  4. Prefix the names with _.
2 Likes