Besides that a enum
in Rust has a discriminator, enum
s are not just (constant) integers.
If you need constant integers, you can just define some:
const MAGIC_LAMP: u32 = 1;
const DEATH_DOLL: u32 = 2;
const SCROLL_OF_EXIT: u32 = 3;
Besides that a enum
in Rust has a discriminator, enum
s are not just (constant) integers.
If you need constant integers, you can just define some:
const MAGIC_LAMP: u32 = 1;
const DEATH_DOLL: u32 = 2;
const SCROLL_OF_EXIT: u32 = 3;
FYI, mandatory case is exactly how Haskell solves this problem and distinguishes variables from constructors.
If we added a lint to handle this case in particular, where the naming convention is not being followed and those lints that would explain what's going on are silenced, it would have to have multiple conditions to minimize false positives:
use
d and it could be confused with a binding)A separate lint would be one advising against use
ing the enum variants if all of them are value-less.
Another lint should be created with similar heuristics for the const
case: if all other match arms are consts, but there's one or more bare bindings, warn.
I would advice not to silence lints in general, but if you have to, to do so with specific lints and not lint families and not at the top level, whenever possible.
match self {
MAGIC_LAMP => "Magic Lamp",
DEATH_DOLL => "Death Doll",
SCROLL_OF_EXIT => "Scroll of Exit",
}
Couldn't this warn regardless of Enum Variants or casing simply because the second 2 match arms are unreachable?
Any match arm following an irrefutable pattern could be a mistake.
To keep the lint simple, maybe that's enough for the first 80%
That may be true, but I also think it's a common trait among experienced programmers that they tend to want to write idiomatic code.
I've broken with common conventions while porting code as well. I'm ashamed to admit it, but I have one crate that uses a lot of Hungarian Notation, simply because it was easier to do it that way.
This already exists: unreachable_patterns
is warn-by-default. But, the unreachable code lints are included in the unused
group and so #[allow(unused)]
disabled it.
Perhaps we need a lint for disabling lints
+1
While using Zig I got used to the sometimes draconian compiler errors for style and unused vars. There are no warnings, only errors! Everyone has an initial knee-jerk aversion to this, but then you get used to it, you use the LSP commands to disable the unused var errors (with _ = var_name
), etc. Overall I came away with a very positive view of it. It really keeps the code clean, and in general I do think stricter is better.
I wish Rust had gone down that path, but it didn't. To use Rust reliably you must pay attention to the warnings and not disable the default warnings. So if there is way to make disabling them more difficult, that would be one way to help the problem. Perhaps it's too late to find a good way to make such a change -- I'm not sure.
Typescript is an interesting comparison too due to their origin; they have a bunch of hard errors where they don't know what to do, but also a bunch of checks they also emit as errors without distinction in output but that don't prevent emitting output.
Unfortunately Rust is already considered unfriendly by newcomers as is; imho if it had gone the stricter route it would be less popular than it currently is.
The more I think about the current status quo the more I like it:
Do you want the language to be stricter? just enable the pedantic âI wish the group was named strict insteadâ clippy lints.
Do you want it to be less strict and stop it from preventing you from shooting yourself in the foot? Just disable all the lints and use
unsafe
all over the place!
Maybe it should be removed from the unused group.
I can kind of see why people don't want to be warned about unused code whilst making big changes early in a project, and therefore allow(unused).
I don't think anyone would also want to allow an unreachable pattern at the same time. It's not caused by unfinished code, it's caused by broken code.
This is a really nasty footgun. I got bite by it at least two times, and it takes a while to see the warning in the match case when you are in the middle of development, and there are already dozens of other warnings.
Some specific lint like #deny(non_snake_case_pattern_identifier)
would resolve that. Ever time it happens I search to see if clippy have already a lint for that, but to no aval.
unused
is described in the docs as "Lints that detect things being declared but not used, or excess syntax" which is already fairly broad, and includes a bunch of things that make it seem even broader: map_unit_fn
, path_statements
, redundant_semicolons
, unused_attributes
, unused_braces
, unused_doc_comments
, unused_parens
, and possibly some others all seem like they're pointing out things that are not likely to be the result of unfinished code.
I'd say this is just covering way too many different things to be a useful grouping in the first place, and just removing one or two things like unreachable_patterns
doesn't seem like the right change - maybe it needs splitting in two, or some other more drastic rearrangement?
But, personally I just set #![allow(dead_code)]
when I'm still writing something, as I find the other warnings from unused
to generally be useful even in the early stages as they tend to point at things local to the code I'm currently writing and remind me which things are/aren't taken care of already.
I find
#![cfg_attr(test, allow(dead_code))]
to be a particularly convenient version of that, so I can keep cargo test
ing as needed, but I once it's time to cargo run --release
I start seeing the extra stuff again.
this is actually how all local bindings are introduced, from let
to function arguments, they're all patterns.
Yes, it's source of endless bugs for me and it looks like for you too. Indeed , people use _ for all uncaught cases, but when they use something different than _, they got surprised Good catch.
Careful! That will prevent you from getting dead code warnings from your tests, such as if you forget #[test]
on a test function and it doesnât run.
It's unfortunate that the overarching lint group has a shorter name than the specific lints. This of course makes sense (groups are more broad, specific lints are.... more specific) but for the design aspect of long_function_name_because_i_know_what_im_doing
it's too bad that it's kinda too late to rename the unused
lint group if disabling it can cause harm.
@kp99 was there a diagnostic (message from the compiler) that suggested or steered you towards disabling the unused
lint specifically?
If we change the diagnostics we may be able to steer new users away from allow(unused) and towards allow(dead_code)?