Opportunity to increase compile-time safety for logic errors

Recently, a bug with a big impact happened in a Rust project when the Rust-coreutils date replacement silently ignored the -r flag, as reported by LWN. I will say that I have absolutely no stake in that, coreutils, clap or anything else here, and these are just my passing observations.

One of the comments on the article mentioned that the Rust compiler ideally should have caught the problem. As it stands, with the current code, there was an unused variable which meant the -r flag was silently ignored.

In fact, it dates back all the way to the original commit of the date program. This is what the code looked like before the commit which properly added support for the -r flag:

const OPT_REFERENCE: &str = "reference";
// ...
        .arg(
            Arg::new(OPT_REFERENCE)
                .short('r')
                .long(OPT_REFERENCE)
                .value_name("FILE")
                .value_hint(clap::ValueHint::AnyPath)
                .help(translate!("date-help-reference")),
        )
// ...
// This is all the code which involves OPT_REFERENCE

In this case, the Rust compiler would not complain that OPT_REFERENCE is unused, because it's used to create a new argument. Logically, however, this is not a "real use" of the variable.

This issue could have been caught if there was a way for functions to inform the compiler that they're not actually using the variable, and it should still be considered unused for the purpose of code analysis. In that case, the clap library could be updated to add this hint for the new and long functions listed above.

As an aside, this is what the currently preferred syntax for clap looks like:

use clap::Parser;

/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
    /// Name of the person to greet
    #[arg(short, long)]
    name: String,

    /// Number of times to greet
    #[arg(short, long, default_value_t = 1)]
    count: u8,

    /// Unused test
    #[arg(short, long, default_value_t = true)]
    foo: bool,
}

fn main() {
    let args = Args::parse();

    for _ in 0..args.count {
        println!("Hello {}!", args.name);
    }
}

This also does not raise an error about the unused member foo, because args is used.
Perhaps there could be another kind of hint added, one which states "this member of the struct must be accessed before the struct gets removed"?

The following could be a guard for unused values, if not for two issues.

struct Must<T>(T);
impl<T> Drop for Must<T> {
    fn drop(&mut self) {
        panic!("dropping a value of type Must<T>")
    }
}
impl<T> Must<T> {
    fn new(value: T) -> Self { Self(value) }
    fn discharge(self) -> T where T: Clone {
        let value = self.0.clone();
        std::mem::forget(self);
        value
    }
}

fn main() {
    Must::new(1_usize).discharge();
    
    let x = Must::new(0_usize);
    _ = &x;
}

but

  1. that does not trigger the lint about unconditional panic (which is bound to happen when x goes out of scope),
  2. somewhy Rust does not allow normal destructuring let Self(value) = self; saying that there is Drop impl for Must...
    It shouldn't be a compile error to explicitly waive destructor call and then use the fields as one wishes IMO.

Were there no test cases using that flag?