Skip to content

Commit c733376

Browse files
committed
Auto merge of #4522 - mikerite:fix-4514, r=phansch
Fix `or_fun_call` bad suggestion Closes #4514 changelog: Fix `or_fun_call` bad suggestion
2 parents 8af4e09 + f88c224 commit c733376

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
@@ -1376,6 +1376,7 @@ fn lint_or_fun_call<'a, 'tcx>(
13761376

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

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

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

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

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

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

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)