Skip to content

Commit e48670c

Browse files
estebankrylev
authored andcommitted
Increase accuracy of lint trigger
1 parent 49f32e0 commit e48670c

File tree

3 files changed

+43
-28
lines changed

3 files changed

+43
-28
lines changed

compiler/rustc_lint/src/noop_method_call.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -62,33 +62,45 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
6262
// Resolve the trait method instance
6363
if let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) {
6464
// Check that it implements the noop diagnostic
65-
if [
66-
sym::noop_method_borrow,
67-
sym::noop_method_clone,
68-
sym::noop_method_deref,
65+
for (s, peel_ref) in [
66+
(sym::noop_method_borrow, true),
67+
(sym::noop_method_clone, false),
68+
(sym::noop_method_deref, true),
6969
]
7070
.iter()
71-
.any(|s| cx.tcx.is_diagnostic_item(*s, i.def_id()))
7271
{
73-
let method = &call.ident.name;
74-
let receiver = &elements[0];
75-
let receiver_ty = cx.typeck_results().expr_ty(receiver);
76-
let expr_span = expr.span;
77-
let note = format!(
78-
"the type `{:?}` which `{}` is being called on is the same as the type returned from `{}`, \
79-
so the method call does not do anything and can be removed.",
80-
receiver_ty, method, method
81-
);
82-
83-
let span = expr_span.with_lo(receiver.span.hi());
84-
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
72+
if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
8573
let method = &call.ident.name;
86-
let message = format!("call to `.{}()` on a reference in this situation does nothing", &method);
87-
lint.build(&message)
88-
.span_label(span, "unnecessary method call")
89-
.note(&note)
90-
.emit()
91-
});
74+
let receiver = &elements[0];
75+
let receiver_ty = cx.typeck_results().expr_ty(receiver);
76+
let receiver_ty = match receiver_ty.kind() {
77+
// Remove one borrow from the receiver as all the trait methods
78+
// we care about here have a `&self` receiver.
79+
ty::Ref(_, ty, _) if *peel_ref => ty,
80+
_ => receiver_ty,
81+
};
82+
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
83+
if receiver_ty != expr_ty {
84+
return;
85+
}
86+
let expr_span = expr.span;
87+
let note = format!(
88+
"the type `{:?}` which `{}` is being called on is the same as \
89+
the type returned from `{}`, so the method call does not do \
90+
anything and can be removed",
91+
receiver_ty, method, method,
92+
);
93+
94+
let span = expr_span.with_lo(receiver.span.hi());
95+
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
96+
let method = &call.ident.name;
97+
let message = format!("call to `.{}()` on a reference in this situation does nothing", &method);
98+
lint.build(&message)
99+
.span_label(span, "unnecessary method call")
100+
.note(&note)
101+
.emit()
102+
});
103+
}
92104
}
93105
}
94106
}

src/test/ui/lint/noop-method-call.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ fn main() {
3737
let a = &&Foo(1u32);
3838
let borrowed: &Foo<u32> = a.borrow();
3939
//~^ WARNING call to `.borrow()` on a reference in this situation does nothing
40+
41+
let xs = ["a", "b", "c"];
42+
let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // ok, but could use `*x` instead
4043
}
4144

4245
fn generic<T>(foo: &Foo<T>) {

src/test/ui/lint/noop-method-call.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,31 @@ LL | let foo_clone: &Foo<u32> = foo.clone();
55
| ^^^^^^^^ unnecessary method call
66
|
77
= note: `#[warn(noop_method_call)]` on by default
8-
= note: the type `&Foo<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed.
8+
= note: the type `&Foo<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
99

1010
warning: call to `.deref()` on a reference in this situation does nothing
1111
--> $DIR/noop-method-call.rs:31:44
1212
|
1313
LL | let derefed: &DerefExample<u32> = deref.deref();
1414
| ^^^^^^^^ unnecessary method call
1515
|
16-
= note: the type `&&DerefExample<u32>` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed.
16+
= note: the type `&DerefExample<u32>` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed
1717

1818
warning: call to `.borrow()` on a reference in this situation does nothing
1919
--> $DIR/noop-method-call.rs:38:32
2020
|
2121
LL | let borrowed: &Foo<u32> = a.borrow();
2222
| ^^^^^^^^^ unnecessary method call
2323
|
24-
= note: the type `&&Foo<u32>` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed.
24+
= note: the type `&Foo<u32>` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed
2525

2626
warning: call to `.clone()` on a reference in this situation does nothing
27-
--> $DIR/noop-method-call.rs:47:8
27+
--> $DIR/noop-method-call.rs:50:8
2828
|
2929
LL | foo.clone();
3030
| ^^^^^^^^ unnecessary method call
3131
|
32-
= note: the type `&Foo<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed.
32+
= note: the type `&Foo<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
3333

3434
warning: 4 warnings emitted
3535

0 commit comments

Comments
 (0)