Fix FP on if_then_some_else_none when there is early return

This commit is contained in:
dswij 2021-11-16 13:39:52 +08:00
parent 57a8804ef9
commit ec3d1c8ca3
2 changed files with 22 additions and 2 deletions

View file

@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{higher, is_else_clause, is_lang_ctor, meets_msrv, msrvs};
use clippy_utils::{contains_return, higher, is_else_clause, is_lang_ctor, meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind};
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
@ -82,6 +82,7 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
if let Some(els_expr) = els_block.expr;
if let ExprKind::Path(ref qpath) = els_expr.kind;
if is_lang_ctor(cx, qpath, OptionNone);
if !stmts_contains_early_return(then_block.stmts);
then {
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
@ -114,3 +115,11 @@ impl LateLintPass<'_> for IfThenSomeElseNone {
extract_msrv_attr!(LateContext);
}
fn stmts_contains_early_return(stmts: &[Stmt<'_>]) -> bool {
stmts.iter().any(|stmt| {
let Stmt { kind: StmtKind::Semi(e), .. } = stmt else { return false };
contains_return(e)
})
}

View file

@ -102,3 +102,14 @@ fn into_some<T>(v: T) -> Option<T> {
fn into_none<T>() -> Option<T> {
None
}
// Should not warn
fn f(b: bool, v: Option<()>) -> Option<()> {
if b {
v?; // This is a potential early return, is not equivalent with `bool::then`
Some(())
} else {
None
}
}