mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
748169deaa
Sometimes type annotations are needed for type inferrence to work, or because of coercions. We don't know this, and we also don't want users to possibly repeat the entire pattern.
204 lines
4.6 KiB
Rust
204 lines
4.6 KiB
Rust
#![allow(unused_braces, unused_variables, dead_code)]
|
|
#![allow(
|
|
clippy::collapsible_else_if,
|
|
clippy::unused_unit,
|
|
clippy::let_unit_value,
|
|
clippy::never_loop
|
|
)]
|
|
#![warn(clippy::manual_let_else)]
|
|
|
|
fn g() -> Option<()> {
|
|
None
|
|
}
|
|
|
|
fn main() {}
|
|
|
|
fn fire() {
|
|
let v = if let Some(v_some) = g() { v_some } else { return };
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
let v = if let Some(v) = g() {
|
|
// Blocks around the identity should have no impact
|
|
{
|
|
{ v }
|
|
}
|
|
} else {
|
|
// Some computation should still make it fire
|
|
g();
|
|
return;
|
|
};
|
|
|
|
// continue and break diverge
|
|
loop {
|
|
let v = if let Some(v_some) = g() { v_some } else { continue };
|
|
let v = if let Some(v_some) = g() { v_some } else { break };
|
|
}
|
|
|
|
// panic also diverges
|
|
let v = if let Some(v_some) = g() { v_some } else { panic!() };
|
|
|
|
// abort also diverges
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
std::process::abort()
|
|
};
|
|
|
|
// If whose two branches diverge also diverges
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
if true { return } else { panic!() }
|
|
};
|
|
|
|
// Top level else if
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else if true {
|
|
return;
|
|
} else {
|
|
panic!("diverge");
|
|
};
|
|
|
|
// All match arms diverge
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
match (g(), g()) {
|
|
(Some(_), None) => return,
|
|
(None, Some(_)) => {
|
|
if true {
|
|
return;
|
|
} else {
|
|
panic!();
|
|
}
|
|
},
|
|
_ => return,
|
|
}
|
|
};
|
|
|
|
// Tuples supported for the declared variables
|
|
let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
|
|
v_some
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
// Tuples supported for the identity block and pattern
|
|
let v = if let (Some(v_some), w_some) = (g(), 0) {
|
|
(w_some, v_some)
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
// entirely inside macro lints
|
|
macro_rules! create_binding_if_some {
|
|
($n:ident, $e:expr) => {
|
|
let $n = if let Some(v) = $e { v } else { return };
|
|
};
|
|
}
|
|
create_binding_if_some!(w, g());
|
|
}
|
|
|
|
fn not_fire() {
|
|
let v = if let Some(v_some) = g() {
|
|
// Nothing returned. Should not fire.
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
let w = 0;
|
|
let v = if let Some(v_some) = g() {
|
|
// Different variable than v_some. Should not fire.
|
|
w
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
let v = if let Some(v_some) = g() {
|
|
// Computation in then clause. Should not fire.
|
|
g();
|
|
v_some
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
if false {
|
|
return;
|
|
}
|
|
// This doesn't diverge. Should not fire.
|
|
()
|
|
};
|
|
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
// There is one match arm that doesn't diverge. Should not fire.
|
|
match (g(), g()) {
|
|
(Some(_), None) => return,
|
|
(None, Some(_)) => return,
|
|
(Some(_), Some(_)) => (),
|
|
_ => return,
|
|
}
|
|
};
|
|
|
|
let v = if let Some(v_some) = g() {
|
|
v_some
|
|
} else {
|
|
// loop with a break statement inside does not diverge.
|
|
loop {
|
|
break;
|
|
}
|
|
};
|
|
|
|
enum Uninhabited {}
|
|
fn un() -> Uninhabited {
|
|
panic!()
|
|
}
|
|
let v = if let Some(v_some) = None {
|
|
v_some
|
|
} else {
|
|
// Don't lint if the type is uninhabited but not !
|
|
un()
|
|
};
|
|
|
|
fn question_mark() -> Option<()> {
|
|
let v = if let Some(v) = g() {
|
|
v
|
|
} else {
|
|
// Question mark does not diverge
|
|
g()?
|
|
};
|
|
Some(v)
|
|
}
|
|
|
|
// Macro boundary inside let
|
|
macro_rules! some_or_return {
|
|
($e:expr) => {
|
|
if let Some(v) = $e { v } else { return }
|
|
};
|
|
}
|
|
let v = some_or_return!(g());
|
|
|
|
// Also macro boundary inside let, but inside a macro
|
|
macro_rules! create_binding_if_some_nf {
|
|
($n:ident, $e:expr) => {
|
|
let $n = some_or_return!($e);
|
|
};
|
|
}
|
|
create_binding_if_some_nf!(v, g());
|
|
|
|
// Already a let-else
|
|
let Some(a) = (if let Some(b) = Some(Some(())) { b } else { return }) else { panic!() };
|
|
|
|
// If a type annotation is present, don't lint as
|
|
// expressing the type might be too hard
|
|
let v: () = if let Some(v_some) = g() { v_some } else { panic!() };
|
|
}
|