Skip to content

Commit 9bdfd06

Browse files
author
Michael Wright
committed
Fix or_fun_call bad suggestion
Closes #4514
1 parent f30bf69 commit 9bdfd06

File tree

3 files changed

+54
-25
lines changed

3 files changed

+54
-25
lines changed

clippy_lints/src/methods/mod.rs

+30-25
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,7 @@ fn lint_or_fun_call<'a, 'tcx>(
13771377

13781378
let mut finder = FunCallFinder { cx: &cx, found: false };
13791379
if { finder.visit_expr(&arg); finder.found };
1380+
if !contains_return(&arg);
13801381

13811382
let self_ty = cx.tables.expr_ty(self_expr);
13821383

@@ -2190,28 +2191,6 @@ fn lint_option_and_then_some(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &
21902191
const LINT_MSG: &str = "using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`";
21912192
const NO_OP_MSG: &str = "using `Option.and_then(Some)`, which is a no-op";
21922193

2193-
// Searches an return expressions in `y` in `_.and_then(|x| Some(y))`, which we don't lint
2194-
struct RetCallFinder {
2195-
found: bool,
2196-
}
2197-
2198-
impl<'tcx> intravisit::Visitor<'tcx> for RetCallFinder {
2199-
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
2200-
if self.found {
2201-
return;
2202-
}
2203-
if let hir::ExprKind::Ret(..) = &expr.node {
2204-
self.found = true;
2205-
} else {
2206-
intravisit::walk_expr(self, expr);
2207-
}
2208-
}
2209-
2210-
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
2211-
intravisit::NestedVisitorMap::None
2212-
}
2213-
}
2214-
22152194
let ty = cx.tables.expr_ty(&args[0]);
22162195
if !match_type(cx, ty, &paths::OPTION) {
22172196
return;
@@ -2229,9 +2208,7 @@ fn lint_option_and_then_some(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &
22292208
then {
22302209
let inner_expr = &some_args[0];
22312210

2232-
let mut finder = RetCallFinder { found: false };
2233-
finder.visit_expr(inner_expr);
2234-
if finder.found {
2211+
if contains_return(inner_expr) {
22352212
return;
22362213
}
22372214

@@ -2988,3 +2965,31 @@ fn is_bool(ty: &hir::Ty) -> bool {
29882965
false
29892966
}
29902967
}
2968+
2969+
// Returns `true` if `expr` contains a return expression
2970+
fn contains_return(expr: &hir::Expr) -> bool {
2971+
struct RetCallFinder {
2972+
found: bool,
2973+
}
2974+
2975+
impl<'tcx> intravisit::Visitor<'tcx> for RetCallFinder {
2976+
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
2977+
if self.found {
2978+
return;
2979+
}
2980+
if let hir::ExprKind::Ret(..) = &expr.node {
2981+
self.found = true;
2982+
} else {
2983+
intravisit::walk_expr(self, expr);
2984+
}
2985+
}
2986+
2987+
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
2988+
intravisit::NestedVisitorMap::None
2989+
}
2990+
}
2991+
2992+
let mut visitor = RetCallFinder{ found: false };
2993+
visitor.visit_expr(expr);
2994+
visitor.found
2995+
}

tests/ui/or_fun_call.fixed

+12
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,16 @@ fn test_or_with_ctors() {
9999
.or(Some(Bar(b, Duration::from_secs(2))));
100100
}
101101

102+
103+
// Issue 4514 - early return
104+
fn f() -> Option<()> {
105+
let a = Some(1);
106+
let b = 1i32;
107+
108+
let _ = a.unwrap_or(b.checked_mul(3)?.min(240));
109+
110+
Some(())
111+
}
112+
113+
102114
fn main() {}

tests/ui/or_fun_call.rs

+12
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,16 @@ fn test_or_with_ctors() {
9999
.or(Some(Bar(b, Duration::from_secs(2))));
100100
}
101101

102+
103+
// Issue 4514 - early return
104+
fn f() -> Option<()> {
105+
let a = Some(1);
106+
let b = 1i32;
107+
108+
let _ = a.unwrap_or(b.checked_mul(3)?.min(240));
109+
110+
Some(())
111+
}
112+
113+
102114
fn main() {}

0 commit comments

Comments
 (0)