Someone recently pointed out this confusing code to me. It seems like there should be a warning for this. It is very confusing and I can't imagine when you'd ever intend to do this.
The case is when you have a unit struct S
then it can be matched by the pattern S
in let
, if let
or while let
. It makes for very is confusing code.
The code below prints DFDFDD
. Extra instances of S
are created and it isn't obvious that is what the code is doing. Specifically, the let
statement does a match instead of an assignment so that value is dropped before the call to println!
.
use std::fmt::{self, Display};
struct S;
impl Display for S {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("F")
}
}
impl Drop for S {
fn drop(&mut self) {
print!("D");
}
}
fn f() -> S {
S
}
fn main() {
let S = f(); // Confusing match instead of assigment
print!("{}", S);
match S
{
S => print!("{}", S) // Confusing match against value of same type
}
}
I would propose that two warnings be added. The first one seems more important and more likely to be done accidentally.
- Warning when matching unit structs in
let
,if let
, andwhile let
using the bare struct name. If the match is intended, it should be matched withS{}
which is already legal Rust code. - Warning when matching unit structs in
match
using the bare struct name if the type of the expression being matched is the struct type. Again,S{}
could be used if the match is intended.
Am I missing some reason these should not be warnings?
Would adding these warnings require an RFC or can I create an issue in the compiler repo? (My reading of the guidelines seems to say an RFC is needed. That is more effort than I am willing to put in.)