Skip to content

Commit cefddf7

Browse files
committed
Auto merge of #4191 - g-bartoszek:redundant-closure-deref, r=flip1995
redundant_closure_for_method_calls fixes lint does not trigger when there is a difference in mutability lint does not trigger when the method belongs to a trait which is not implemebted directly (Deref) <!-- Thank you for making Clippy better! We're collecting our changelog from pull request descriptions. If your PR only updates to the latest nightly, you can leave the `changelog` entry as `none`. Otherwise, please write a short comment explaining your change. If your PR fixes an issue, you can add "fixes #issue_number" into this PR description. This way the issue will be automatically closed when your PR is merged. If you added a new lint, here's a checklist for things that will be checked during review or continuous integration. - [ ] Followed [lint naming conventions][lint_naming] - [ ] Added passing UI tests (including committed `.stderr` file) - [ ] `cargo test` passes locally - [ ] Executed `util/dev update_lints` - [ ] Added lint documentation - [ ] Run `cargo fmt` Note that you can skip the above if you are just opening a WIP PR in order to get feedback. Delete this line and everything above before opening your PR --> changelog: none
2 parents bd33a97 + d4ad23b commit cefddf7

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

clippy_lints/src/eta_reduction.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rustc::ty::{self, Ty};
66
use rustc::{declare_lint_pass, declare_tool_lint};
77
use rustc_errors::Applicability;
88

9-
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then, type_is_unsafe_function};
9+
use crate::utils::{
10+
implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then, type_is_unsafe_function,
11+
};
1012

1113
declare_clippy_lint! {
1214
/// **What it does:** Checks for closures which just call another function where
@@ -152,7 +154,9 @@ fn get_ufcs_type_name(
152154
let actual_type_of_self = &cx.tables.node_type(self_arg.hir_id);
153155

154156
if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) {
155-
if match_borrow_depth(expected_type_of_self, &actual_type_of_self) {
157+
if match_borrow_depth(expected_type_of_self, &actual_type_of_self)
158+
&& implements_trait(cx, actual_type_of_self, trait_id, &[])
159+
{
156160
return Some(cx.tcx.def_path_str(trait_id));
157161
}
158162
}
@@ -168,7 +172,7 @@ fn get_ufcs_type_name(
168172

169173
fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
170174
match (&lhs.sty, &rhs.sty) {
171-
(ty::Ref(_, t1, _), ty::Ref(_, t2, _)) => match_borrow_depth(&t1, &t2),
175+
(ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(&t1, &t2),
172176
(l, r) => match (l, r) {
173177
(ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _)) => false,
174178
(_, _) => true,
@@ -183,9 +187,8 @@ fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool {
183187
| (ty::Int(_), ty::Int(_))
184188
| (ty::Uint(_), ty::Uint(_))
185189
| (ty::Str, ty::Str) => true,
186-
(ty::Ref(_, t1, _), ty::Ref(_, t2, _))
187-
| (ty::Array(t1, _), ty::Array(t2, _))
188-
| (ty::Slice(t1), ty::Slice(t2)) => match_types(t1, t2),
190+
(ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_types(t1, t2),
191+
(ty::Array(t1, _), ty::Array(t2, _)) | (ty::Slice(t1), ty::Slice(t2)) => match_types(t1, t2),
189192
(ty::Adt(def1, _), ty::Adt(def2, _)) => def1 == def2,
190193
(_, _) => false,
191194
}

tests/ui/eta.fixed

+19
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,22 @@ fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 {
184184
// called. This changes semantics, so the closure must stay.
185185
Box::new(move |x| f()(x))
186186
}
187+
188+
fn call<F: FnOnce(&mut String) -> String>(f: F) -> String {
189+
f(&mut "Hello".to_owned())
190+
}
191+
fn test_difference_in_mutability() {
192+
call(|s| s.clone());
193+
}
194+
195+
struct Bar;
196+
impl std::ops::Deref for Bar {
197+
type Target = str;
198+
fn deref(&self) -> &str {
199+
"hi"
200+
}
201+
}
202+
203+
fn test_deref_with_trait_method() {
204+
let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
205+
}

tests/ui/eta.rs

+19
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,22 @@ fn make_lazy(f: impl Fn() -> fn(u8) -> u8) -> impl Fn(u8) -> u8 {
184184
// called. This changes semantics, so the closure must stay.
185185
Box::new(move |x| f()(x))
186186
}
187+
188+
fn call<F: FnOnce(&mut String) -> String>(f: F) -> String {
189+
f(&mut "Hello".to_owned())
190+
}
191+
fn test_difference_in_mutability() {
192+
call(|s| s.clone());
193+
}
194+
195+
struct Bar;
196+
impl std::ops::Deref for Bar {
197+
type Target = str;
198+
fn deref(&self) -> &str {
199+
"hi"
200+
}
201+
}
202+
203+
fn test_deref_with_trait_method() {
204+
let _ = [Bar].iter().map(|s| s.to_string()).collect::<Vec<_>>();
205+
}

0 commit comments

Comments
 (0)