Open
Description
Summary
I have the following code:
pub fn find_railroad_name(lcomponents: &mut Vec<&str>) -> Option<String> {
if let Some(last) = lcomponents.last() {
match *last {
"r.r." | "railroad" | "rr" => {
lcomponents.pop();
return Some(lcomponents.join(" "));
}
_ => (),
}
}
None
}
Clippy warns about this:
20 warning: this `match` can be collapsed into the outer `if let`
--> rust/models/src/boundary_name.rs:283:13
|
283 | / match *last {
284 | | "r.r." | "railroad" | "rr" => {
285 | | lcomponents.pop();
286 | | return Some(lcomponents.join(" "));
287 | | }
288 | | _ => (),
289 | | } ▐
| |_____________^ ▐
| ▐
help: the outer pattern can be modified to include the inner pattern ▐
--> rust/models/src/boundary_name.rs:282:21 ▐
| ▐
282 | if let Some(last) = lcomponents.last() { ▐
| ^^^^ replace this binding ▐
283 | match *last { ▐
284 | "r.r." | "railroad" | "rr" => { ▐
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern ▐
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match ▐
= note: `#[warn(clippy::collapsible_match)]` on by default ▐
I tried doing what it suggested and got three compiler errors:
pub fn find_railroad_name(lcomponents: &mut Vec<&str>) -> Option<String> {
if let Some("r.r." | "railroad" | "rr") = lcomponents.last() {
lcomponents.pop();
return Some(lcomponents.join(" "));
}
None
}
1 error[E0308]: mismatched types ▐
--> rust/models/src/boundary_name.rs:282:21 ▐
| ▐
282 | if let Some("r.r." | "railroad" | "rr") = lcomponents.last() { ▐
| ^^^^^^ ------------------ this expression has type `std::option::Option<&&str>` ▐
| | ▐
| expected `&&str`, found `&str` ▐
| ▐
= note: expected reference `&&_` ▐
found reference `&'static _` ▐
What I ended up needing to do was:
pub fn find_railroad_name(lcomponents: &mut Vec<&str>) -> Option<String> {
if let Some(&"r.r." | &"railroad" | &"rr") = lcomponents.last() {
lcomponents.pop();
return Some(lcomponents.join(" "));
}
None
}
It feels a little weird to be putting referenced, static strings inside a Some()
pattern match like that. Anyway, I wanted to alert to the fact that the Clippy suggestion isn't sufficient in this case. Should this be special-cased, or does this actually count as a False-Positive?
Reproducer
I tried this code:
fn main() {
let lcomponents: Vec<&str> = "B&O R.R.".to_lowercase().split_whitespace().collect();
if let Some(rr_name) = find_railroad_name(&mut lcomponents) {
println!("Found: {rr_name}");
}
}
pub fn find_railroad_name(lcomponents: &mut Vec<&str>) -> Option<String> {
if let Some(last) = lcomponents.last() {
match *last {
"r.r." | "railroad" | "rr" => {
lcomponents.pop();
return Some(lcomponents.join(" "));
}
_ => (),
}
}
None
}
I expected to see this happen: No warning, I think? Not sure.
Instead, this happened: Warning
Version:
rustc 1.84.0 (9fc6b4312 2025-01-07)
binary: rustc
commit-hash: 9fc6b43126469e3858e2fe86cafb4f0fd5068869
commit-date: 2025-01-07
host: aarch64-apple-darwin
release: 1.84.0
LLVM version: 19.1.5
Version
Additional Labels
No response