Skip to content

Commit 2f343a0

Browse files
committed
saftey commit
1 parent 13c7361 commit 2f343a0

File tree

4 files changed

+29
-25
lines changed

4 files changed

+29
-25
lines changed

clippy_lints/src/and_then_then_some.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability;
33
use clippy_utils::{fn_def_id, match_def_path};
44
use rustc_errors::Applicability;
55
use rustc_hir::def::Res;
6-
use rustc_hir::{Block, Closure, Expr, ExprKind, FnDecl, HirId, Node, Pat, Path, QPath, Ty};
6+
use rustc_hir::{Block, Closure, Expr, ExprKind, FnDecl, HirId, Node, Pat, Path, QPath, Ty, Param, Body};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::declare_lint_pass;
99
use rustc_span::Span;
@@ -58,14 +58,18 @@ impl<'tcx> LateLintPass<'tcx> for AndThenThenSome {
5858
fn then_some_closure_arg<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(Span, &'tcx Expr<'tcx>)> {
5959
match expr.kind {
6060
ExprKind::Closure(Closure {
61-
fn_decl: FnDecl {
61+
/*fn_decl: FnDecl {
6262
inputs: [Ty { hir_id: arg_id, .. }],
6363
..
64-
},
64+
},*/
6565
body,
6666
..
6767
}) => {
68-
if let Node::Expr(expr) = cx.tcx.hir_node(body.hir_id) {
68+
if let Node::Expr(expr) = cx.tcx.hir_node(body.hir_id) &&
69+
let Body{ params: [ Param{ hir_id: arg_id, .. } ], .. } =
70+
cx.tcx.hir().body(*body)
71+
{
72+
6973
(peel_closure_body(cx, expr, *arg_id)).map(|body| (cx.tcx.hir().span(*arg_id), body))
7074
} else {
7175
None
@@ -101,6 +105,16 @@ fn peel_closure_body<'tcx>(
101105
}
102106
}
103107

108+
fn get_pat_hid(node: Node<'_>) -> Option<HirId> {
109+
match node {
110+
Node::Param(Param{ pat: Pat { hir_id, .. }, .. }) |
111+
Node::Pat(Pat{ hir_id, .. }) => Some(*hir_id),
112+
_ => {
113+
None
114+
},
115+
}
116+
}
117+
104118
fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -> bool {
105119
match local.kind {
106120
ExprKind::Path(QPath::Resolved(
@@ -110,19 +124,9 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
110124
..
111125
},
112126
)) => {
113-
// FIXME: this is the best way i could find to compare if
114-
// a local refers to a specific closure argument.
115-
//
116-
// it breaks if the closure argument has an explicitly declared type,
117-
// since the spans only align for TyKind::Infer
118-
if let Node::Pat(Pat { span: local_span, .. }) = (cx.tcx.hir_node(*local_hid))
119-
&& let Node::Ty(Ty { span: arg_span, .. }) = (cx.tcx.hir_node(arg_hid))
120-
&& local_span == arg_span
121-
{
122-
true
123-
} else {
124-
false
125-
}
127+
let local_pat_id = get_pat_hid(cx.tcx.hir_node(*local_hid));
128+
local_pat_id.is_some() &&
129+
local_pat_id == get_pat_hid(cx.tcx.hir_node(arg_hid))
126130
},
127131
// is not local at all, so definitly isn't a local defined at the given position
128132
_ => false,
@@ -132,7 +136,7 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
132136
fn show_sugg(cx: &LateContext<'_>, span: Span, selfarg: &Expr<'_>, closure_args: Span, predicate: &Expr<'_>) {
133137
let mut appl = Applicability::MachineApplicable;
134138
let sugg = format!(
135-
"{}.filter(|{}| {})",
139+
"{}.filter(|&{}| {})",
136140
snippet_with_applicability(cx, selfarg.span, "<OPTION>", &mut appl),
137141
snippet_with_applicability(cx, closure_args, "<ARGS>", &mut appl),
138142
snippet_with_applicability(cx, predicate.span, "<PREDICATE>", &mut appl)

tests/ui/and_then_then_some.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ 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.filter(|v: String| v.starts_with('f'));
1010
}

tests/ui/and_then_then_some.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ 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| 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));
1010
}

tests/ui/and_then_then_some.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: use of `and_then` + `then_some` is equivelent to `filter`
1+
error: use of `Option::and_then` and `bool::then_some` is equivelent to `filter`
22
--> tests/ui/and_then_then_some.rs:6:14
33
|
44
LL | let _y = x.clone().and_then(|v| v.starts_with('f').then_some(v));
@@ -7,17 +7,17 @@ LL | let _y = x.clone().and_then(|v| v.starts_with('f').then_some(v));
77
= note: `-D clippy::and-then-then-some` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::and_then_then_some)]`
99

10-
error: use of `and_then` + `then_some` is equivelent to `filter`
10+
error: use of `Option::and_then` and `bool::then_some` is equivelent to `filter`
1111
--> tests/ui/and_then_then_some.rs:8:14
1212
|
1313
LL | let _z = x.clone().and_then(|v| bool::then_some(v.starts_with('f'), v));
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Option::filter` instead: `x.clone().filter(|v| v.starts_with('f'))`
1515

16-
error: use of `and_then` + `then_some` is equivelent to `filter`
16+
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| 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, |v: String| bool::then_some(v.starts_with('f'), v));
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `Option::filter` instead: `x.filter(|v: String| v.starts_with('f'))`
2121

2222
error: aborting due to 3 previous errors
2323

0 commit comments

Comments
 (0)