Commit efe3fe9b8c removed the ability for
`single_match` and `single_match_else` to trigger if comments were
present outside of the arms, as those comments would be lost while
rewriting the `match` expression.
This reinstates the lint, but prevents the suggestion from being applied
automatically in the presence of comments by using the `MaybeIncorrect`
applicability. Also, a note is added to the lint message to warn the
user about the need to preserve the comments if acting upon the
suggestion.
233 lines
4.8 KiB
Rust
233 lines
4.8 KiB
Rust
//@aux-build: proc_macros.rs
|
|
//@require-annotations-for-level: WARN
|
|
|
|
#![warn(clippy::single_match_else)]
|
|
#![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
|
|
extern crate proc_macros;
|
|
use proc_macros::with_span;
|
|
|
|
enum ExprNode {
|
|
ExprAddrOf,
|
|
Butterflies,
|
|
Unicorns,
|
|
}
|
|
|
|
static NODE: ExprNode = ExprNode::Unicorns;
|
|
|
|
fn unwrap_addr() -> Option<&'static ExprNode> {
|
|
let _ = match ExprNode::Butterflies {
|
|
ExprNode::ExprAddrOf => Some(&NODE),
|
|
_ => {
|
|
let x = 5;
|
|
None
|
|
},
|
|
};
|
|
//~^^^^^^^ single_match_else
|
|
|
|
// Don't lint
|
|
with_span!(span match ExprNode::Butterflies {
|
|
ExprNode::ExprAddrOf => Some(&NODE),
|
|
_ => {
|
|
let x = 5;
|
|
None
|
|
},
|
|
})
|
|
}
|
|
|
|
macro_rules! unwrap_addr {
|
|
($expression:expr) => {
|
|
match $expression {
|
|
ExprNode::ExprAddrOf => Some(&NODE),
|
|
_ => {
|
|
let x = 5;
|
|
None
|
|
},
|
|
}
|
|
};
|
|
}
|
|
|
|
#[rustfmt::skip]
|
|
fn main() {
|
|
unwrap_addr!(ExprNode::Unicorns);
|
|
|
|
//
|
|
// don't lint single exprs/statements
|
|
//
|
|
|
|
// don't lint here
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
None => return,
|
|
}
|
|
|
|
// don't lint here
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
None => {
|
|
return
|
|
},
|
|
}
|
|
|
|
// don't lint here
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
None => {
|
|
return;
|
|
},
|
|
}
|
|
|
|
//
|
|
// lint multiple exprs/statements "else" blocks
|
|
//
|
|
|
|
// lint here
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
None => {
|
|
println!("else block");
|
|
return
|
|
},
|
|
}
|
|
//~^^^^^^^ single_match_else
|
|
|
|
// lint here
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
None => {
|
|
println!("else block");
|
|
return;
|
|
},
|
|
}
|
|
//~^^^^^^^ single_match_else
|
|
|
|
match Some(1) {
|
|
Some(a) => println!("${:?}", a),
|
|
// This is an inner comment
|
|
None => {
|
|
println!("else block");
|
|
return;
|
|
},
|
|
}
|
|
//~^^^^^^^^ single_match_else
|
|
//~| NOTE: you might want to preserve the comments from inside the `match`
|
|
|
|
// lint here
|
|
use std::convert::Infallible;
|
|
match Result::<i32, &Infallible>::Ok(1) {
|
|
Ok(a) => println!("${:?}", a),
|
|
Err(_) => {
|
|
println!("else block");
|
|
return;
|
|
}
|
|
}
|
|
//~^^^^^^^ single_match_else
|
|
|
|
use std::borrow::Cow;
|
|
match Cow::from("moo") {
|
|
Cow::Owned(a) => println!("${:?}", a),
|
|
Cow::Borrowed(_) => {
|
|
println!("else block");
|
|
return;
|
|
}
|
|
}
|
|
//~^^^^^^^ single_match_else
|
|
}
|
|
|
|
fn issue_10808(bar: Option<i32>) {
|
|
match bar {
|
|
Some(v) => unsafe {
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
},
|
|
None => {
|
|
println!("None1");
|
|
println!("None2");
|
|
},
|
|
}
|
|
//~^^^^^^^^^^ single_match_else
|
|
|
|
match bar {
|
|
Some(v) => {
|
|
println!("Some");
|
|
println!("{v}");
|
|
},
|
|
None => unsafe {
|
|
let v = 0;
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
},
|
|
}
|
|
//~^^^^^^^^^^^ single_match_else
|
|
|
|
match bar {
|
|
Some(v) => unsafe {
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
},
|
|
None => unsafe {
|
|
let v = 0;
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
},
|
|
}
|
|
//~^^^^^^^^^^^ single_match_else
|
|
|
|
match bar {
|
|
#[rustfmt::skip]
|
|
Some(v) => {
|
|
unsafe {
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
}
|
|
},
|
|
None => {
|
|
println!("None");
|
|
println!("None");
|
|
},
|
|
}
|
|
//~^^^^^^^^^^^^^ single_match_else
|
|
|
|
match bar {
|
|
Some(v) => {
|
|
println!("Some");
|
|
println!("{v}");
|
|
},
|
|
#[rustfmt::skip]
|
|
None => {
|
|
unsafe {
|
|
let v = 0;
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
}
|
|
},
|
|
}
|
|
|
|
match bar {
|
|
#[rustfmt::skip]
|
|
Some(v) => {
|
|
unsafe {
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
}
|
|
},
|
|
#[rustfmt::skip]
|
|
None => {
|
|
unsafe {
|
|
let v = 0;
|
|
let r = &v as *const i32;
|
|
println!("{}", *r);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
fn irrefutable_match() -> Option<&'static ExprNode> {
|
|
match ExprNode::Butterflies {
|
|
ExprNode::Butterflies => Some(&NODE),
|
|
_ => {
|
|
let x = 5;
|
|
None
|
|
},
|
|
}
|
|
//~^^^^^^^ single_match_else
|
|
}
|