Skip to content

Commit 1090186

Browse files
committed
add and test another edge case (explicit return)
1 parent 4e8fe6c commit 1090186

File tree

4 files changed

+22
-6
lines changed

4 files changed

+22
-6
lines changed

clippy_lints/src/and_then_then_some.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ fn peel_closure_body<'tcx>(
8585
closure_arg_id: HirId,
8686
) -> Option<&'tcx Expr<'tcx>> {
8787
match expr.kind {
88+
ExprKind::Ret(Some(wrapped_expr)) =>
89+
// duplicated blocks because 2023 reference statements are awkward.
90+
// "&" peels multiple layers of indirection instead of just one like we want.
91+
peel_closure_body(cx, wrapped_expr, closure_arg_id),
8892
// it would be nice if we could lift { x; y.a() } into { x; y }.a()
8993
ExprKind::Block(
9094
Block {
@@ -136,7 +140,9 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
136140
fn show_sugg(cx: &LateContext<'_>, span: Span, selfarg: &Expr<'_>, closure_args: Span, predicate: &Expr<'_>) {
137141
let mut appl = Applicability::MachineApplicable;
138142
// FIXME: this relies on deref coertion, which won't work correctly if the predicate involves something
139-
// other than a method call.
143+
// other than a method call. this is because `and_then` takes an argument by
144+
// value, while `filter` takes an argument by reference.
145+
140146
let sugg = format!(
141147
"{}.filter(|{}| {})",
142148
snippet_with_applicability(cx, selfarg.span, "<OPTION>", &mut appl),

tests/ui/and_then_then_some.fixed

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ fn main() {
66
let _y = x.clone().filter(|v| v.starts_with('f'));
77

88
let _z = x.clone().filter(|v| v.starts_with('f'));
9-
let _w = x.filter(|v| v.starts_with('f'));
9+
let _w = x.clone().filter(|v| v.starts_with('f'));
10+
#[allow(clippy::needless_return)]
11+
let _v = x.clone().filter(|v| v.starts_with('g'));
1012
}

tests/ui/and_then_then_some.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ fn main() {
66
let _y = x.clone().and_then(|v| v.starts_with('f').then_some(v));
77

88
let _z = x.clone().and_then(|v| bool::then_some(v.starts_with('f'), v));
9-
let _w = Option::and_then(x, |v: String| bool::then_some(v.starts_with('f'), v));
9+
let _w = Option::and_then(x.clone(), |v: String| bool::then_some(v.starts_with('f'), v));
10+
#[allow(clippy::needless_return)]
11+
let _v = x.clone().and_then(|v| return v.starts_with('g').then_some(v));
1012
}

tests/ui/and_then_then_some.stderr

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ LL | let _z = x.clone().and_then(|v| bool::then_some(v.starts_with('f'), v))
1616
error: use of `Option::and_then` and `bool::then_some` is equivelent to `filter`
1717
--> tests/ui/and_then_then_some.rs:9:14
1818
|
19-
LL | let _w = Option::and_then(x, |v: String| bool::then_some(v.starts_with('f'), v));
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Option::filter` instead: `x.filter(|v| v.starts_with('f'))`
19+
LL | let _w = Option::and_then(x.clone(), |v: String| bool::then_some(v.starts_with('f'), v));
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Option::filter` instead: `x.clone().filter(|v| v.starts_with('f'))`
2121

22-
error: aborting due to 3 previous errors
22+
error: use of `Option::and_then` and `bool::then_some` is equivelent to `filter`
23+
--> tests/ui/and_then_then_some.rs:11:11
24+
|
25+
LL | let _v = x.clone().and_then(|v| return v.starts_with('g').then_some(v));
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Option::filter` instead: `x.clone().filter(|v| v.starts_with('g'))`
27+
28+
error: aborting due to 4 previous errors
2329

0 commit comments

Comments
 (0)