We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 8 of 26
The wildcard trap: `_` arms freeze your enum against the future
A supervisor turns signal lines into status strings.
pub fn handle(events: Vec<String>) -> Vec<String>
| line | status |
|---|---|
start |
running |
stop |
halted |
pause |
paused |
resume |
running |
reconnect 3 |
retrying #3 |
| anything else |
unknown |
Read the starter before you read anything else
The starter is what this code looked like one release ago, when Signal
had three variants and _ => "paused" was a perfectly reasonable way to say
“the other one”. Since then someone added Resume and Reconnect.
Notice what did not happen. The build did not break. No test in the
original suite failed. The wildcard quietly absorbed both new variants and
started reporting a connection retry as paused. That is the entire lesson,
and it is worth sitting with for a moment: the wildcard is the switch that
turns exhaustiveness checking off. Everything the previous item promised —
the compiler walking you to every site that needs updating — stops applying
the moment you write _.
Two gates, deliberately
This problem also injects a lint that is normally off:
#![warn(clippy::wildcard_enum_match_arm)]
wildcard_enum_match_arm lives in clippy’s restriction group, which is
allow-by-default and which you should never enable wholesale — its lints
contradict each other on purpose. Cherry-picked, though, it is exactly the
tool for this job, and under -D warnings a warn-level lint is a build
failure. So the starter fails twice: the tests catch the wrong answers, and
the lint catches the construct that caused them.
Keep the attribute in your submission. It is part of the exercise.
When a wildcard is right
This is a habit, not a commandment, and the honest version of it matters:
-
#[non_exhaustive]upstream enums require one.std::io::ErrorKindcan gain variants in any release, so amatchon it that compiles today without a wildcard would break your build on a routine toolchain upgrade. Rust makes you write_there, and it is right to. - Genuinely large enums where thirty variants share one behaviour are more readable with a wildcard than with thirty copies of the same arm.
- Everywhere else, the wildcard is buying you thirty seconds now and costing you a silent bug later.
There is also a middle ground most people never learn:
Signal::Reconnect { .. } => ..., // ignores the payload
Signal::Reconnect(..) => ..., // same, for a tuple variant
These ignore the data but still name the variant, so adding a new variant
still breaks the match. If your reason for reaching for _ was “I do not care
about the fields”, this is what you actually wanted.
The rule is “know why you wrote it”, not “never write it”.
Related lints worth recognising
match_wildcard_for_single_variants — you wrote _ and it covers exactly one
variant; just name it. match_wild_err_arm — Err(_) => panic!(...) throws
away the error someone went to the trouble of handing you. single_match_else
— a two-arm match that an if let ... else would say more plainly. All three
are allow-by-default; they are worth knowing about even when the gate is
silent.
Remember the grade is compile + tests + clippy -D warnings.
Loading visualization…
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.